@resurrect-protocol/contracts 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -6
- package/abi/{ResurrectRegistryV1.json → ResurrectBeaconV1.json} +10 -2
- package/abi/ResurrectOnchainSite.json +234 -0
- package/deployments/ethereum-mainnet-explorer.json +355 -0
- package/deployments/ethereum-mainnet.json +30 -17
- package/package.json +11 -8
- package/src/ResurrectBeaconV1.sol +39 -0
- package/src/ResurrectOnchainSite.sol +182 -0
- package/src/ResurrectRegistryV1.sol +0 -34
package/README.md
CHANGED
|
@@ -1,20 +1,52 @@
|
|
|
1
1
|
# `@resurrect-protocol/contracts`
|
|
2
2
|
|
|
3
|
-
Canonical
|
|
3
|
+
Canonical Resurrect Solidity sources, ABIs, and Ethereum mainnet deployment records.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install @resurrect-protocol/contracts
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
## Beacon
|
|
10
|
+
|
|
9
11
|
```js
|
|
10
|
-
import
|
|
12
|
+
import beaconAbi from '@resurrect-protocol/contracts/abi/ResurrectBeaconV1.json' with { type: 'json' }
|
|
11
13
|
import ethereumMainnet from '@resurrect-protocol/contracts/deployments/ethereum-mainnet.json' with { type: 'json' }
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
Solidity tools can import `@resurrect-protocol/contracts/src/
|
|
16
|
+
Solidity tools can import `@resurrect-protocol/contracts/src/ResurrectBeaconV1.sol`. The permissionless beacon exposes exactly `VERSION`, `MAX_TTL`, `MAX_RECORD_BYTES`, and `announce`. It has no owner, administrator, allowlist, pause, upgrade, withdrawal, or peer-storage path. Despite the name, it is a rendezvous beacon rather than an upgradeable proxy beacon.
|
|
17
|
+
|
|
18
|
+
The canonical deployment is [`0x136c191B5e6541532E42Ecd7C719C29D7ecdf468`](https://etherscan.io/address/0x136c191B5e6541532E42Ecd7C719C29D7ecdf468#code) on Ethereum mainnet, chain ID `1`, receipt block `25943058`. Its deployment JSON includes the transaction, deployer, compiler settings, bytecode hashes, Etherscan and Sourcify links, and audit metadata.
|
|
19
|
+
|
|
20
|
+
Applications may use the canonical deployment or deploy the exact source elsewhere, but must pin the chosen chain, address, deployment block, namespace, and constants. A shared stateless beacon does not create a shared peer list. RPC providers remain caller-selected, and an event remains an untrusted discovery hint until the signed record, sequence, expiry, endpoints, and application handshake are verified.
|
|
21
|
+
|
|
22
|
+
OneDollarAudit job [#904](https://www.onedollaraudit.com/audit/904) reviewed the exact canonical address and produced an [immutable IPFS report](https://bafkreid22gqqrzwo6b6scxqnmcmiinru3xzigz74xkere2573r6ivulzjq.ipfs.community.bgipfs.com/) with 0 Critical, 0 High, 0 Medium, 2 Low, and 1 Informational finding.
|
|
23
|
+
|
|
24
|
+
## Immutable explorer
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import siteAbi from '@resurrect-protocol/contracts/abi/ResurrectOnchainSite.json' with { type: 'json' }
|
|
28
|
+
import explorerMainnet from '@resurrect-protocol/contracts/deployments/ethereum-mainnet-explorer.json' with { type: 'json' }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Solidity tools can import `@resurrect-protocol/contracts/src/ResurrectOnchainSite.sol`. The contract implements ERC-5219 and the ERC-6944 `5219` resolve mode, reconstructing immutable resources from bytecode-storage contracts. It has no owner, mutable storage, or upgrade path.
|
|
32
|
+
|
|
33
|
+
The source-verified production router is `0x14765f12a7f068EDf42dF4920fd5170ADBa73306` on Ethereum mainnet at block `25943864`. Its deployment JSON records the 24 data contracts, all 25 transaction hashes and blocks, every resource hash and payload length, the router runtime and manifest hashes, compiler settings, Etherscan and Sourcify verification, deployment cost, gateway URLs, and runtime verification results. The embedded explorer uses the canonical `ResurrectBeaconV1` at `0x136c191B5e6541532E42Ecd7C719C29D7ecdf468`.
|
|
34
|
+
|
|
35
|
+
Open it through:
|
|
36
|
+
|
|
37
|
+
- `https://resurrect.wei.limo/` — primary human-readable entry point;
|
|
38
|
+
- `https://resurrect.wei.domains/` — alternative name gateway;
|
|
39
|
+
- `web3://resurrect.wei/`;
|
|
40
|
+
- `web3://0x14765f12a7f068EDf42dF4920fd5170ADBa73306:1/`;
|
|
41
|
+
- `https://0x14765f12a7f068edf42df4920fd5170adba73306.w3eth.io/`; or
|
|
42
|
+
- `https://0x14765f12a7f068edf42df4920fd5170adba73306.1.w3link.io/`.
|
|
43
|
+
|
|
44
|
+
The deployment JSON also records the WNS contract, `resurrect.wei` token ID,
|
|
45
|
+
owner, expiry, resolved address, ERC-6821 `contentcontract`, registration and
|
|
46
|
+
configuration transactions, cost, and byte-for-byte WNS gateway verification.
|
|
15
47
|
|
|
16
|
-
|
|
48
|
+
Consumers should independently compare deployed code and resources with the pinned source and build artifact before relying on them.
|
|
17
49
|
|
|
18
|
-
|
|
50
|
+
## License
|
|
19
51
|
|
|
20
|
-
|
|
52
|
+
Resurrect's original source and deployment metadata are licensed under MIT. Dependency licenses remain their own.
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
],
|
|
44
44
|
"anonymous": false
|
|
45
45
|
},
|
|
46
|
-
{
|
|
47
|
-
|
|
46
|
+
{
|
|
47
|
+
"type": "error",
|
|
48
|
+
"name": "InvalidTTL",
|
|
49
|
+
"inputs": [{ "name": "supplied", "type": "uint32", "internalType": "uint32" }]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"type": "error",
|
|
53
|
+
"name": "RecordTooLarge",
|
|
54
|
+
"inputs": [{ "name": "supplied", "type": "uint256", "internalType": "uint256" }]
|
|
55
|
+
}
|
|
48
56
|
]
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"type": "constructor",
|
|
4
|
+
"inputs": [
|
|
5
|
+
{
|
|
6
|
+
"name": "pathHashes",
|
|
7
|
+
"type": "bytes32[]",
|
|
8
|
+
"internalType": "bytes32[]"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "contentTypes",
|
|
12
|
+
"type": "string[]",
|
|
13
|
+
"internalType": "string[]"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "chunks",
|
|
17
|
+
"type": "address[][]",
|
|
18
|
+
"internalType": "address[][]"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "lengths",
|
|
22
|
+
"type": "uint256[]",
|
|
23
|
+
"internalType": "uint256[]"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "expectedManifestHash",
|
|
27
|
+
"type": "bytes32",
|
|
28
|
+
"internalType": "bytes32"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"stateMutability": "nonpayable"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"type": "function",
|
|
35
|
+
"name": "INDEX_PATH_HASH",
|
|
36
|
+
"inputs": [],
|
|
37
|
+
"outputs": [
|
|
38
|
+
{
|
|
39
|
+
"name": "",
|
|
40
|
+
"type": "bytes32",
|
|
41
|
+
"internalType": "bytes32"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"stateMutability": "view"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "function",
|
|
48
|
+
"name": "manifestHash",
|
|
49
|
+
"inputs": [],
|
|
50
|
+
"outputs": [
|
|
51
|
+
{
|
|
52
|
+
"name": "",
|
|
53
|
+
"type": "bytes32",
|
|
54
|
+
"internalType": "bytes32"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"stateMutability": "view"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"type": "function",
|
|
61
|
+
"name": "request",
|
|
62
|
+
"inputs": [
|
|
63
|
+
{
|
|
64
|
+
"name": "resource",
|
|
65
|
+
"type": "string[]",
|
|
66
|
+
"internalType": "string[]"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "",
|
|
70
|
+
"type": "tuple[]",
|
|
71
|
+
"internalType": "struct KeyValue[]",
|
|
72
|
+
"components": [
|
|
73
|
+
{
|
|
74
|
+
"name": "key",
|
|
75
|
+
"type": "string",
|
|
76
|
+
"internalType": "string"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "value",
|
|
80
|
+
"type": "string",
|
|
81
|
+
"internalType": "string"
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"outputs": [
|
|
87
|
+
{
|
|
88
|
+
"name": "statusCode",
|
|
89
|
+
"type": "uint16",
|
|
90
|
+
"internalType": "uint16"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "body",
|
|
94
|
+
"type": "string",
|
|
95
|
+
"internalType": "string"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"name": "headers",
|
|
99
|
+
"type": "tuple[]",
|
|
100
|
+
"internalType": "struct KeyValue[]",
|
|
101
|
+
"components": [
|
|
102
|
+
{
|
|
103
|
+
"name": "key",
|
|
104
|
+
"type": "string",
|
|
105
|
+
"internalType": "string"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "value",
|
|
109
|
+
"type": "string",
|
|
110
|
+
"internalType": "string"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"stateMutability": "view"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"type": "function",
|
|
119
|
+
"name": "resolveMode",
|
|
120
|
+
"inputs": [],
|
|
121
|
+
"outputs": [
|
|
122
|
+
{
|
|
123
|
+
"name": "mode",
|
|
124
|
+
"type": "bytes32",
|
|
125
|
+
"internalType": "bytes32"
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
"stateMutability": "pure"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"type": "function",
|
|
132
|
+
"name": "resourceInfo",
|
|
133
|
+
"inputs": [
|
|
134
|
+
{
|
|
135
|
+
"name": "path",
|
|
136
|
+
"type": "string",
|
|
137
|
+
"internalType": "string"
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
"outputs": [
|
|
141
|
+
{
|
|
142
|
+
"name": "exists",
|
|
143
|
+
"type": "bool",
|
|
144
|
+
"internalType": "bool"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"name": "contentType",
|
|
148
|
+
"type": "string",
|
|
149
|
+
"internalType": "string"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "length",
|
|
153
|
+
"type": "uint256",
|
|
154
|
+
"internalType": "uint256"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"name": "chunks",
|
|
158
|
+
"type": "address[]",
|
|
159
|
+
"internalType": "address[]"
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"stateMutability": "view"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"type": "error",
|
|
166
|
+
"name": "ArrayLengthMismatch",
|
|
167
|
+
"inputs": []
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"type": "error",
|
|
171
|
+
"name": "DuplicatePath",
|
|
172
|
+
"inputs": [
|
|
173
|
+
{
|
|
174
|
+
"name": "pathHash",
|
|
175
|
+
"type": "bytes32",
|
|
176
|
+
"internalType": "bytes32"
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"type": "error",
|
|
182
|
+
"name": "EmptyResource",
|
|
183
|
+
"inputs": [
|
|
184
|
+
{
|
|
185
|
+
"name": "pathHash",
|
|
186
|
+
"type": "bytes32",
|
|
187
|
+
"internalType": "bytes32"
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"type": "error",
|
|
193
|
+
"name": "InvalidChunk",
|
|
194
|
+
"inputs": [
|
|
195
|
+
{
|
|
196
|
+
"name": "pathHash",
|
|
197
|
+
"type": "bytes32",
|
|
198
|
+
"internalType": "bytes32"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"name": "chunk",
|
|
202
|
+
"type": "address",
|
|
203
|
+
"internalType": "address"
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"type": "error",
|
|
209
|
+
"name": "MissingIndex",
|
|
210
|
+
"inputs": []
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"type": "error",
|
|
214
|
+
"name": "ResourceLengthMismatch",
|
|
215
|
+
"inputs": [
|
|
216
|
+
{
|
|
217
|
+
"name": "pathHash",
|
|
218
|
+
"type": "bytes32",
|
|
219
|
+
"internalType": "bytes32"
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"name": "expected",
|
|
223
|
+
"type": "uint256",
|
|
224
|
+
"internalType": "uint256"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"name": "actual",
|
|
228
|
+
"type": "uint256",
|
|
229
|
+
"internalType": "uint256"
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"deploymentKind": "erc-5219-static-site",
|
|
4
|
+
"application": "Resurrect Explorer",
|
|
5
|
+
"network": "ethereum-mainnet",
|
|
6
|
+
"chainId": 1,
|
|
7
|
+
"address": "0x14765f12a7f068EDf42dF4920fd5170ADBa73306",
|
|
8
|
+
"canonicalBeacon": {
|
|
9
|
+
"contract": "ResurrectBeaconV1",
|
|
10
|
+
"address": "0x136c191B5e6541532E42Ecd7C719C29D7ecdf468",
|
|
11
|
+
"deploymentBlock": 25943058
|
|
12
|
+
},
|
|
13
|
+
"deploymentBlock": 25943864,
|
|
14
|
+
"firstDeploymentBlock": 25943834,
|
|
15
|
+
"firstDeploymentTimestamp": "2026-09-10T01:54:47Z",
|
|
16
|
+
"deploymentTimestamp": "2026-09-10T02:00:47Z",
|
|
17
|
+
"transactionHash": "0x4a128735f12908e0979982b3b3e92d575a5bdd6b19f280eaaf6a6fb8c40e05b0",
|
|
18
|
+
"deployer": "0x6E4a6b178Fea5FA7cE3051615C49F26b177E74F0",
|
|
19
|
+
"immutable": true,
|
|
20
|
+
"resolveMode": "5219",
|
|
21
|
+
"manifestHash": "0x36f8d8a77af7849aa040a86d4f7663ab5a185b9d72e2ab500c9db85785ddd026",
|
|
22
|
+
"manifestEncoding": "keccak256(abi.encode(string[6] paths, string[6] contentTypes, bytes32[] resourceHashes))",
|
|
23
|
+
"runtimeBytecodeHash": "0x7d6198765aea906764d581185b310fa9c2a41670c5a6b674233b442c11ea9ecd",
|
|
24
|
+
"source": {
|
|
25
|
+
"repository": "https://github.com/cazala/resurrect",
|
|
26
|
+
"contractPath": "contracts/src/ResurrectOnchainSite.sol",
|
|
27
|
+
"deploymentScriptPath": "contracts/script/DeployResurrectExplorer.s.sol",
|
|
28
|
+
"explorerArtifactPath": "apps/explorer/dist"
|
|
29
|
+
},
|
|
30
|
+
"compiler": {
|
|
31
|
+
"language": "Solidity",
|
|
32
|
+
"version": "0.8.24",
|
|
33
|
+
"optimizer": true,
|
|
34
|
+
"optimizerRuns": 20000,
|
|
35
|
+
"bytecodeHash": "none",
|
|
36
|
+
"cborMetadata": false
|
|
37
|
+
},
|
|
38
|
+
"storage": {
|
|
39
|
+
"scheme": "immutable-contract-runtime-bytecode",
|
|
40
|
+
"sentinelBytes": 1,
|
|
41
|
+
"maxPayloadBytesPerChunk": 24000,
|
|
42
|
+
"resourceBytes": 467179,
|
|
43
|
+
"chunkContracts": 24,
|
|
44
|
+
"transactions": 25
|
|
45
|
+
},
|
|
46
|
+
"deploymentCost": {
|
|
47
|
+
"gasUsed": 104317581,
|
|
48
|
+
"weiPaid": "7086418126710057",
|
|
49
|
+
"ethPaid": "0.007086418126710057"
|
|
50
|
+
},
|
|
51
|
+
"gateways": {
|
|
52
|
+
"primary": "https://resurrect.wei.limo/",
|
|
53
|
+
"wns": "https://resurrect.wei.limo/",
|
|
54
|
+
"weiLimo": "https://resurrect.wei.limo/",
|
|
55
|
+
"weiDomains": "https://resurrect.wei.domains/",
|
|
56
|
+
"web3Name": "web3://resurrect.wei/",
|
|
57
|
+
"web3": "web3://0x14765f12a7f068EDf42dF4920fd5170ADBa73306:1/",
|
|
58
|
+
"w3eth": "https://0x14765f12a7f068edf42df4920fd5170adba73306.w3eth.io/",
|
|
59
|
+
"w3link": "https://0x14765f12a7f068edf42df4920fd5170adba73306.1.w3link.io/"
|
|
60
|
+
},
|
|
61
|
+
"wns": {
|
|
62
|
+
"name": "resurrect.wei",
|
|
63
|
+
"status": "active",
|
|
64
|
+
"contract": "0x0000000000696760E15f265e828DB644A0c242EB",
|
|
65
|
+
"tokenId": "41087391431831184440468199834649177938136395864233436476895591760904781888274",
|
|
66
|
+
"tokenIdHex": "0x5ad6a3b22580f32032bc963e77903e6c2d7baa9199d605fa31cc1613dd98fb12",
|
|
67
|
+
"owner": "0x3107af70F278D3824f9BaB4222b3361A545356C2",
|
|
68
|
+
"resolvedAddress": "0x14765f12a7f068EDf42dF4920fd5170ADBa73306",
|
|
69
|
+
"contentcontract": "eth:0x14765f12a7f068EDf42dF4920fd5170ADBa73306",
|
|
70
|
+
"contenthash": "0x",
|
|
71
|
+
"registeredAt": "2026-09-10T12:10:47Z",
|
|
72
|
+
"expiresAt": "2027-09-10T12:10:47Z",
|
|
73
|
+
"expiresAtUnix": 1820578247,
|
|
74
|
+
"registrationFeeWei": "500000000000000",
|
|
75
|
+
"registrationAndConfigurationGasUsed": 350304,
|
|
76
|
+
"weiPaid": "526901469028467",
|
|
77
|
+
"ethPaid": "0.000526901469028467",
|
|
78
|
+
"transactions": {
|
|
79
|
+
"commit": {
|
|
80
|
+
"hash": "0x0645328813aa11e75aaf9286bc11d35dd3905f417131736ebdcef8a9c54298d9",
|
|
81
|
+
"block": 25946893
|
|
82
|
+
},
|
|
83
|
+
"reveal": {
|
|
84
|
+
"hash": "0x010cce17ac09ea0a1deda110993d904e5af402217fe954439636866a9dad79c4",
|
|
85
|
+
"block": 25946901
|
|
86
|
+
},
|
|
87
|
+
"setAddr": {
|
|
88
|
+
"hash": "0x420f900ae42dfa456770c5334694de467d81e3f804fd3d6c58db92f549f3e09f",
|
|
89
|
+
"block": 25946902
|
|
90
|
+
},
|
|
91
|
+
"setContentcontract": {
|
|
92
|
+
"hash": "0x45d0cd803dd6e04f623d42e2cb5519f954fd0ec958a52a7b8cd37b57fec98674",
|
|
93
|
+
"block": 25946904
|
|
94
|
+
},
|
|
95
|
+
"transferOwnership": {
|
|
96
|
+
"hash": "0x3c8ee9a2452daab45ab1030a6abaea5a6b4296f5360388e91ca7820205d4fd8d",
|
|
97
|
+
"block": 25948245,
|
|
98
|
+
"from": "0x6E4a6b178Fea5FA7cE3051615C49F26b177E74F0",
|
|
99
|
+
"to": "0x3107af70F278D3824f9BaB4222b3361A545356C2"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"verification": {
|
|
104
|
+
"sourceCode": {
|
|
105
|
+
"etherscan": {
|
|
106
|
+
"status": "pass",
|
|
107
|
+
"url": "https://etherscan.io/address/0x14765f12a7f068EDf42dF4920fd5170ADBa73306#code",
|
|
108
|
+
"contractName": "ResurrectOnchainSite",
|
|
109
|
+
"compilerVersion": "v0.8.24+commit.e11b9ed9",
|
|
110
|
+
"optimizer": true,
|
|
111
|
+
"optimizerRuns": 20000,
|
|
112
|
+
"proxy": false
|
|
113
|
+
},
|
|
114
|
+
"sourcify": {
|
|
115
|
+
"status": "pass",
|
|
116
|
+
"url": "https://repo.sourcify.dev/1/0x14765f12a7f068EDf42dF4920fd5170ADBa73306",
|
|
117
|
+
"apiUrl": "https://sourcify.dev/server/v2/contract/1/0x14765f12a7f068EDf42dF4920fd5170ADBa73306?fields=all",
|
|
118
|
+
"jobUrl": "https://sourcify.dev/server/verify-ui/jobs/e869b535-a13a-42a0-8d38-9c68a5d2b301",
|
|
119
|
+
"match": "match",
|
|
120
|
+
"creationMatch": "match",
|
|
121
|
+
"runtimeMatch": "match",
|
|
122
|
+
"matchId": "48334992",
|
|
123
|
+
"verifiedAt": "2026-09-10T02:03:21Z"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"ethereumRpc": {
|
|
127
|
+
"status": "pass",
|
|
128
|
+
"resolveMode": true,
|
|
129
|
+
"manifestHash": true,
|
|
130
|
+
"canonicalBeaconEmbedded": true,
|
|
131
|
+
"allResourceBodiesByteForByte": true,
|
|
132
|
+
"resourceMetadata": true,
|
|
133
|
+
"notFoundResponse": true
|
|
134
|
+
},
|
|
135
|
+
"w3eth": {
|
|
136
|
+
"status": "pass",
|
|
137
|
+
"allAssetsByteForByte": true,
|
|
138
|
+
"rootDocumentServed": true
|
|
139
|
+
},
|
|
140
|
+
"w3link": {
|
|
141
|
+
"status": "pass",
|
|
142
|
+
"allAssetsByteForByte": true,
|
|
143
|
+
"rootDocumentServed": true
|
|
144
|
+
},
|
|
145
|
+
"weiLimo": {
|
|
146
|
+
"status": "pass",
|
|
147
|
+
"url": "https://resurrect.wei.limo/",
|
|
148
|
+
"nameRecordsMatchRouter": true,
|
|
149
|
+
"allAssetsByteForByte": true,
|
|
150
|
+
"rootDocumentServed": true
|
|
151
|
+
},
|
|
152
|
+
"weiDomains": {
|
|
153
|
+
"status": "pass",
|
|
154
|
+
"url": "https://resurrect.wei.domains/",
|
|
155
|
+
"nameRecordsMatchRouter": true,
|
|
156
|
+
"allAssetsByteForByte": true,
|
|
157
|
+
"rootDocumentServed": true,
|
|
158
|
+
"browserRendered": true
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
"resources": [
|
|
162
|
+
{
|
|
163
|
+
"path": "index.html",
|
|
164
|
+
"contentType": "text/html; charset=utf-8",
|
|
165
|
+
"bytes": 846,
|
|
166
|
+
"keccak256": "0xa041546d52f4a94300f04fb1ced3e058f843f2cd9edf54cab9370b7c4dff37a3",
|
|
167
|
+
"chunks": [
|
|
168
|
+
{
|
|
169
|
+
"address": "0x85D83Ac987CD03A516e43e524d2Ed2F9af2EC4D3",
|
|
170
|
+
"transactionHash": "0x0fa25ef1cf1c0b73dab2db9293053766a74ab8f08288632773315a59547b61c0",
|
|
171
|
+
"block": 25943834,
|
|
172
|
+
"payloadBytes": 846
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"path": "index.css",
|
|
178
|
+
"contentType": "text/css; charset=utf-8",
|
|
179
|
+
"bytes": 6573,
|
|
180
|
+
"keccak256": "0x1783b9d52010f4d0f016b802b7f73142142bc1395605bf57525f896d3174c544",
|
|
181
|
+
"chunks": [
|
|
182
|
+
{
|
|
183
|
+
"address": "0xE04834b7ad6F2C6D01D29D10061c7468663723B4",
|
|
184
|
+
"transactionHash": "0x1d56306dd1c2590b0066a1f05cbd3216f3a9a3c745d41dd0667039e9032d9621",
|
|
185
|
+
"block": 25943836,
|
|
186
|
+
"payloadBytes": 6573
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"path": "app.js",
|
|
192
|
+
"contentType": "text/javascript; charset=utf-8",
|
|
193
|
+
"bytes": 35241,
|
|
194
|
+
"keccak256": "0x7add949f94f202fae190835642abec74bdeb4421b39ac7660934315be257f887",
|
|
195
|
+
"chunks": [
|
|
196
|
+
{
|
|
197
|
+
"address": "0x17Ca0269c87921A01F7Bc43fAE4CD8A64e321Fa1",
|
|
198
|
+
"transactionHash": "0x237ab2650a68328de72a2be7dc8025f3641daac852975c68f4dbda43a8aa32e7",
|
|
199
|
+
"block": 25943837,
|
|
200
|
+
"payloadBytes": 24000
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"address": "0x79FC47FA71ff18A95156b05b52b83fa3853e29Ae",
|
|
204
|
+
"transactionHash": "0x639bb81fb01a411f8a72e462da4138be25ac37e548024e7e5497a0e4a77005a1",
|
|
205
|
+
"block": 25943839,
|
|
206
|
+
"payloadBytes": 11241
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"path": "rolldown-runtime.js",
|
|
212
|
+
"contentType": "text/javascript; charset=utf-8",
|
|
213
|
+
"bytes": 716,
|
|
214
|
+
"keccak256": "0x7de63044a95dcac21b8884ab40985883e687488e6e2abfd5770266e2c537cfb2",
|
|
215
|
+
"chunks": [
|
|
216
|
+
{
|
|
217
|
+
"address": "0xC87924d955f41640De7e838383E3fFcB4f9f59f1",
|
|
218
|
+
"transactionHash": "0x559607532f4931140c941dedc8c5b8299e7592dcc711c16c0d2e68140b98a0da",
|
|
219
|
+
"block": 25943840,
|
|
220
|
+
"payloadBytes": 716
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"path": "peer-record.js",
|
|
226
|
+
"contentType": "text/javascript; charset=utf-8",
|
|
227
|
+
"bytes": 132713,
|
|
228
|
+
"keccak256": "0xe69fcbeb747bf15edf524ec758d6340157a4460ac14ff0a7fcf77b84e1eb2529",
|
|
229
|
+
"chunks": [
|
|
230
|
+
{
|
|
231
|
+
"address": "0x08cc5cF593d2AE209E1016D635D347687F5e4201",
|
|
232
|
+
"transactionHash": "0xdcfe31f4a8323cbacee59f5113e21cde61a483d17c3e9c738a72c7b8ae73a9c7",
|
|
233
|
+
"block": 25943841,
|
|
234
|
+
"payloadBytes": 24000
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"address": "0x2073DE6FEE2422589CC0660BAbab8E57c7B862A6",
|
|
238
|
+
"transactionHash": "0x7ad83d7ba1c5bdfca931f0746481bdef542f61ce0441d5eb3da643b25fc48f71",
|
|
239
|
+
"block": 25943842,
|
|
240
|
+
"payloadBytes": 24000
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"address": "0xf40Fa2695B29E464470197450A26a49ca0616ACC",
|
|
244
|
+
"transactionHash": "0x8f7e507bb4200328f767a8bbe1df226edacd689299acd3cbda71b689c8610231",
|
|
245
|
+
"block": 25943845,
|
|
246
|
+
"payloadBytes": 24000
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"address": "0x262Cecf0f23b8e36b1A1dbD6dc11BAa8909A3F74",
|
|
250
|
+
"transactionHash": "0x1e81082808835ad4d96710a1aa1a061d03858e921806fe2e0535f600d3f753a1",
|
|
251
|
+
"block": 25943846,
|
|
252
|
+
"payloadBytes": 24000
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"address": "0x78C083C8a9b70Dd1e0e4b040EC8c2C563aD5e013",
|
|
256
|
+
"transactionHash": "0x23fdc4a1ba66708098fb351a8f354f2f300e47430a1f4c2be387a5d194824e3d",
|
|
257
|
+
"block": 25943847,
|
|
258
|
+
"payloadBytes": 24000
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"address": "0x941DfA169654A59Dfbf63CFEe6E4E9a96fA64b11",
|
|
262
|
+
"transactionHash": "0xed4d4ecc202a606f49991f37ca35479dc751b210e748f5667406a3e735bf02d4",
|
|
263
|
+
"block": 25943848,
|
|
264
|
+
"payloadBytes": 12713
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"path": "peer-probe.js",
|
|
270
|
+
"contentType": "text/javascript; charset=utf-8",
|
|
271
|
+
"bytes": 291090,
|
|
272
|
+
"keccak256": "0xd52f2b97fec863c83fdffce1ad05e338e95a762e81cab8bacd99437c421ada7a",
|
|
273
|
+
"chunks": [
|
|
274
|
+
{
|
|
275
|
+
"address": "0x5BADF212c1Fe55e6b3bfBcB491B121C465093a10",
|
|
276
|
+
"transactionHash": "0xc6643cc41e982b3f42f8aa78e523bb0b9ebaf36cd9c4399862269ab04fd7e26c",
|
|
277
|
+
"block": 25943849,
|
|
278
|
+
"payloadBytes": 24000
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"address": "0xb1EF58696779Ae67Af58EFfF5ab0ac4fE506F846",
|
|
282
|
+
"transactionHash": "0x34ee601ecca1b9ee12adece40636c82572677ab9a6efebc01aa02e9e48241cf4",
|
|
283
|
+
"block": 25943850,
|
|
284
|
+
"payloadBytes": 24000
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"address": "0xCFc6c16826Da7c50A6598F2D0a6082875C1ae372",
|
|
288
|
+
"transactionHash": "0x0488161ae996d825498545ae6ac21e986ad1814f9fb2251f3b45c1bf777c4c16",
|
|
289
|
+
"block": 25943851,
|
|
290
|
+
"payloadBytes": 24000
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"address": "0xeAD2faDAc40662431Ce527226e5125AEa5613679",
|
|
294
|
+
"transactionHash": "0xdc6de04a68b92e398a2f206086676f1933a4e2c6bd8bc77e7c98bf31f4224be5",
|
|
295
|
+
"block": 25943852,
|
|
296
|
+
"payloadBytes": 24000
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"address": "0xa1Cd9225dc37a258eD42F122e6A654365244429b",
|
|
300
|
+
"transactionHash": "0x30efae542312c85314c435ab05ff0aba99b1f4892618826dc00248057ea13b22",
|
|
301
|
+
"block": 25943853,
|
|
302
|
+
"payloadBytes": 24000
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"address": "0xA05FEd13f2558AeAF8E9236De9712c389312F392",
|
|
306
|
+
"transactionHash": "0x05560e9a1a4a5b0ea3bf5f0770a6d100fbd0adcb6bd8938d14406edd145add45",
|
|
307
|
+
"block": 25943854,
|
|
308
|
+
"payloadBytes": 24000
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"address": "0x31cBAAb7694C0398493211B81946437083FEb760",
|
|
312
|
+
"transactionHash": "0xf416d4b05554bf0ef1e96d29b70b37a9c8babf5e4f42849062a3e441b29c3203",
|
|
313
|
+
"block": 25943855,
|
|
314
|
+
"payloadBytes": 24000
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"address": "0xa1Fb4Ae5988Cb9739A0Cf3b4fc7e6BF3E045ec04",
|
|
318
|
+
"transactionHash": "0x8978f08f465d954751266c0dc284bfd888b5ff4a9756d6c7fd2288ac86268378",
|
|
319
|
+
"block": 25943856,
|
|
320
|
+
"payloadBytes": 24000
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"address": "0x9E986048bf8B7C296d19cd8dF02CB0bfe8f73Ea4",
|
|
324
|
+
"transactionHash": "0xe1d9ddada722beb7a2148e2d558ff333773c5a4b878725baa00590bcd0b8ab76",
|
|
325
|
+
"block": 25943857,
|
|
326
|
+
"payloadBytes": 24000
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"address": "0xf568f232CB6154d9dD9B0c5fc47046e691266135",
|
|
330
|
+
"transactionHash": "0x3295e512fa016f8d4306421e7928be87f9c85f70ba9084fac441b5ce44127113",
|
|
331
|
+
"block": 25943859,
|
|
332
|
+
"payloadBytes": 24000
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"address": "0x27EE558daf98316D0D375Cc2c60906Cb71f57dE5",
|
|
336
|
+
"transactionHash": "0x7944f1dbfaf3022659b5ea1669f883df7f714edf36a690dbfe9da255959133dd",
|
|
337
|
+
"block": 25943860,
|
|
338
|
+
"payloadBytes": 24000
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"address": "0x9feD0e9da21FC0f1b79543E7b87042E457bDb545",
|
|
342
|
+
"transactionHash": "0x3637bb2e4bae51c619c5adc3c41249cde81cff2e108a1fa4fbce851b24474ac3",
|
|
343
|
+
"block": 25943861,
|
|
344
|
+
"payloadBytes": 24000
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"address": "0x26172ac10e736ada96e690baAeccBa1b04D47cC6",
|
|
348
|
+
"transactionHash": "0x80ca114d2f552195ce9e3ef1591616ff5cae5a8c26bb894680d7fb1612defe0b",
|
|
349
|
+
"block": 25943863,
|
|
350
|
+
"payloadBytes": 3090
|
|
351
|
+
}
|
|
352
|
+
]
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
}
|
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"contract": "
|
|
3
|
+
"contract": "ResurrectBeaconV1",
|
|
4
4
|
"network": "ethereum-mainnet",
|
|
5
5
|
"chainId": 1,
|
|
6
|
-
"address": "
|
|
7
|
-
"deploymentBlock":
|
|
8
|
-
"deploymentTimestamp": "2026-09-
|
|
9
|
-
"transactionHash": "
|
|
10
|
-
"deployer": "
|
|
11
|
-
"
|
|
6
|
+
"address": "0x136c191B5e6541532E42Ecd7C719C29D7ecdf468",
|
|
7
|
+
"deploymentBlock": 25943058,
|
|
8
|
+
"deploymentTimestamp": "2026-09-09T23:19:35Z",
|
|
9
|
+
"transactionHash": "0x8e7c2ddf815d44166d436fabd886a05bac6eab25ba5abf6faf9e93e3e179b8d6",
|
|
10
|
+
"deployer": "0x6E4a6b178Fea5FA7cE3051615C49F26b177E74F0",
|
|
11
|
+
"creationBytecodeHash": "0x449675c0d8b1c3ba38a1cd0c633ee043a9f328c14535ea04ff6d9e51845efa3a",
|
|
12
|
+
"runtimeBytecodeHash": "0x20999e7bf54d855e3bfedebfd7053d41f0c873ecde3b9d70a71ee6dcd086bce7",
|
|
12
13
|
"source": {
|
|
13
14
|
"repository": "https://github.com/cazala/resurrect",
|
|
14
|
-
"
|
|
15
|
-
"commit": "3298158d0e86959a05434495eb28335808e7964a",
|
|
16
|
-
"path": "contracts/src/ResurrectRegistryV1.sol"
|
|
15
|
+
"path": "contracts/src/ResurrectBeaconV1.sol"
|
|
17
16
|
},
|
|
18
17
|
"compiler": {
|
|
19
18
|
"language": "Solidity",
|
|
20
|
-
"version": "0.8.24",
|
|
19
|
+
"version": "0.8.24+commit.e11b9ed9",
|
|
21
20
|
"optimizer": true,
|
|
22
21
|
"optimizerRuns": 20000,
|
|
23
22
|
"bytecodeHash": "none",
|
|
24
|
-
"cborMetadata": false
|
|
23
|
+
"cborMetadata": false,
|
|
24
|
+
"evmVersion": "cancun"
|
|
25
25
|
},
|
|
26
26
|
"verification": {
|
|
27
27
|
"provider": "Sourcify",
|
|
28
28
|
"status": "match",
|
|
29
|
-
"verifiedAt": "2026-09-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
29
|
+
"verifiedAt": "2026-09-09T23:24:46Z",
|
|
30
|
+
"creationMatch": "match",
|
|
31
|
+
"runtimeMatch": "match",
|
|
32
|
+
"url": "https://repo.sourcify.dev/1/0x136c191B5e6541532E42Ecd7C719C29D7ecdf468",
|
|
33
|
+
"apiUrl": "https://sourcify.dev/server/v2/contract/1/0x136c191B5e6541532E42Ecd7C719C29D7ecdf468"
|
|
32
34
|
},
|
|
33
35
|
"explorers": {
|
|
34
36
|
"etherscan": {
|
|
35
37
|
"status": "verified",
|
|
36
|
-
"
|
|
37
|
-
"url": "https://etherscan.io/address/0x6F33c332e8251dcd307D85A27fCcAbd85d578910#code"
|
|
38
|
+
"url": "https://etherscan.io/address/0x136c191B5e6541532E42Ecd7C719C29D7ecdf468#code"
|
|
38
39
|
}
|
|
40
|
+
},
|
|
41
|
+
"audit": {
|
|
42
|
+
"provider": "OneDollarAudit",
|
|
43
|
+
"jobId": 904,
|
|
44
|
+
"completedAt": "2026-09-10T00:24:09Z",
|
|
45
|
+
"critical": 0,
|
|
46
|
+
"high": 0,
|
|
47
|
+
"medium": 0,
|
|
48
|
+
"low": 2,
|
|
49
|
+
"informational": 1,
|
|
50
|
+
"jobUrl": "https://www.onedollaraudit.com/audit/904",
|
|
51
|
+
"reportUrl": "https://bafkreid22gqqrzwo6b6scxqnmcmiinru3xzigz74xkere2573r6ivulzjq.ipfs.community.bgipfs.com/"
|
|
39
52
|
}
|
|
40
53
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@resurrect-protocol/contracts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Canonical immutable Solidity
|
|
5
|
-
"license": "
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Canonical immutable Solidity contracts, ABIs, and Ethereum deployments for Resurrect",
|
|
5
|
+
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/cazala/resurrect.git",
|
|
@@ -16,14 +16,17 @@
|
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
18
|
"exports": {
|
|
19
|
-
"./abi/
|
|
19
|
+
"./abi/ResurrectBeaconV1.json": "./abi/ResurrectBeaconV1.json",
|
|
20
|
+
"./abi/ResurrectOnchainSite.json": "./abi/ResurrectOnchainSite.json",
|
|
21
|
+
"./deployments/ethereum-mainnet-explorer.json": "./deployments/ethereum-mainnet-explorer.json",
|
|
20
22
|
"./deployments/ethereum-mainnet.json": "./deployments/ethereum-mainnet.json",
|
|
21
|
-
"./src/
|
|
23
|
+
"./src/ResurrectBeaconV1.sol": "./src/ResurrectBeaconV1.sol",
|
|
24
|
+
"./src/ResurrectOnchainSite.sol": "./src/ResurrectOnchainSite.sol"
|
|
22
25
|
},
|
|
23
26
|
"scripts": {
|
|
24
|
-
"build": "node -e \"const fs=require('node:fs');
|
|
25
|
-
"check": "node -e \"const fs=require('node:fs');
|
|
26
|
-
"test": "node -e \"const fs=require('node:fs');
|
|
27
|
+
"build": "node -e \"const fs=require('node:fs'); for (const file of ['abi/ResurrectBeaconV1.json','abi/ResurrectOnchainSite.json','deployments/ethereum-mainnet.json','deployments/ethereum-mainnet-explorer.json']) JSON.parse(fs.readFileSync(file))\"",
|
|
28
|
+
"check": "node -e \"const fs=require('node:fs'); for (const file of ['abi/ResurrectBeaconV1.json','abi/ResurrectOnchainSite.json','deployments/ethereum-mainnet.json','deployments/ethereum-mainnet-explorer.json']) JSON.parse(fs.readFileSync(file))\"",
|
|
29
|
+
"test": "node -e \"const fs=require('node:fs'); for (const file of ['abi/ResurrectBeaconV1.json','abi/ResurrectOnchainSite.json','deployments/ethereum-mainnet.json','deployments/ethereum-mainnet-explorer.json']) JSON.parse(fs.readFileSync(file))\""
|
|
27
30
|
},
|
|
28
31
|
"publishConfig": {
|
|
29
32
|
"access": "public",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.24;
|
|
3
|
+
|
|
4
|
+
/// @title Resurrect rendezvous beacon v1
|
|
5
|
+
/// @notice Permissionless, immutable, log-only transport for caller-supplied peer-record bytes.
|
|
6
|
+
/// @dev The contract does not verify signatures or bind namespace, recordType, ttl, peerRecord, or
|
|
7
|
+
/// msg.sender to one another. Consumers must perform those trust checks off-chain. This is not an
|
|
8
|
+
/// upgradeable proxy beacon and deliberately has no owner, storage, upgrade, pause, or withdrawal
|
|
9
|
+
/// path.
|
|
10
|
+
contract ResurrectBeaconV1 {
|
|
11
|
+
uint32 public constant VERSION = 1;
|
|
12
|
+
uint32 public constant MAX_TTL = 90 days;
|
|
13
|
+
uint32 public constant MAX_RECORD_BYTES = 4096;
|
|
14
|
+
|
|
15
|
+
error InvalidTTL(uint32 supplied);
|
|
16
|
+
error RecordTooLarge(uint256 supplied);
|
|
17
|
+
|
|
18
|
+
event PeerAnnounced(
|
|
19
|
+
bytes32 indexed namespace, uint32 indexed recordType, uint64 validUntil, bytes peerRecord
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
/// @notice Publishes a bounded-lifetime record for an application namespace.
|
|
23
|
+
/// @param namespace Application/network isolation identifier.
|
|
24
|
+
/// @param recordType Resurrect peer-record codec identifier.
|
|
25
|
+
/// @param ttl Lifetime in seconds, bounded by `MAX_TTL`.
|
|
26
|
+
/// @param peerRecord Raw peer-record bytes; this contract does not authenticate them.
|
|
27
|
+
function announce(bytes32 namespace, uint32 recordType, uint32 ttl, bytes calldata peerRecord)
|
|
28
|
+
external
|
|
29
|
+
{
|
|
30
|
+
if (ttl == 0 || ttl > MAX_TTL) revert InvalidTTL(ttl);
|
|
31
|
+
|
|
32
|
+
uint256 recordLength = peerRecord.length;
|
|
33
|
+
if (recordLength == 0 || recordLength > MAX_RECORD_BYTES) {
|
|
34
|
+
revert RecordTooLarge(recordLength);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
emit PeerAnnounced(namespace, recordType, uint64(block.timestamp) + uint64(ttl), peerRecord);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.24;
|
|
3
|
+
|
|
4
|
+
struct KeyValue {
|
|
5
|
+
string key;
|
|
6
|
+
string value;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface IDecentralizedApp {
|
|
10
|
+
function request(string[] memory resource, KeyValue[] memory params)
|
|
11
|
+
external
|
|
12
|
+
view
|
|
13
|
+
returns (uint16 statusCode, string memory body, KeyValue[] memory headers);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// @notice Writes immutable bytes into contract runtime code and reads them with EXTCODECOPY.
|
|
17
|
+
/// @dev Runtime byte zero is a STOP sentinel; the remaining bytes are the payload.
|
|
18
|
+
library ResurrectBytecodeStorage {
|
|
19
|
+
uint256 internal constant MAX_CHUNK_BYTES = 24_000;
|
|
20
|
+
|
|
21
|
+
error EmptyChunk();
|
|
22
|
+
error ChunkTooLarge(uint256 length);
|
|
23
|
+
error ChunkDeploymentFailed();
|
|
24
|
+
|
|
25
|
+
function write(bytes memory data) internal returns (address pointer) {
|
|
26
|
+
if (data.length == 0) revert EmptyChunk();
|
|
27
|
+
if (data.length > MAX_CHUNK_BYTES) revert ChunkTooLarge(data.length);
|
|
28
|
+
|
|
29
|
+
uint16 runtimeLength = uint16(data.length + 1);
|
|
30
|
+
bytes memory initCode =
|
|
31
|
+
abi.encodePacked(hex"61", bytes2(runtimeLength), hex"80600a5f395ff300", data);
|
|
32
|
+
assembly ("memory-safe") {
|
|
33
|
+
pointer := create(0, add(initCode, 0x20), mload(initCode))
|
|
34
|
+
}
|
|
35
|
+
if (pointer == address(0)) revert ChunkDeploymentFailed();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function payloadSize(address pointer) internal view returns (uint256 length) {
|
|
39
|
+
assembly ("memory-safe") {
|
|
40
|
+
length := extcodesize(pointer)
|
|
41
|
+
}
|
|
42
|
+
if (length == 0) return 0;
|
|
43
|
+
unchecked {
|
|
44
|
+
--length;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function copy(address pointer, bytes memory output, uint256 outputOffset) internal view {
|
|
49
|
+
uint256 length = payloadSize(pointer);
|
|
50
|
+
assembly ("memory-safe") {
|
|
51
|
+
extcodecopy(pointer, add(add(output, 0x20), outputOffset), 1, length)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// @notice Immutable ERC-5219 resource router for one Resurrect explorer build.
|
|
57
|
+
/// @dev No resource can be added, changed, or removed after construction.
|
|
58
|
+
contract ResurrectOnchainSite is IDecentralizedApp {
|
|
59
|
+
using ResurrectBytecodeStorage for address;
|
|
60
|
+
|
|
61
|
+
bytes32 public constant INDEX_PATH_HASH = keccak256("index.html");
|
|
62
|
+
bytes32 public immutable manifestHash;
|
|
63
|
+
|
|
64
|
+
struct Resource {
|
|
65
|
+
string contentType;
|
|
66
|
+
address[] chunks;
|
|
67
|
+
uint256 length;
|
|
68
|
+
bool exists;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
mapping(bytes32 pathHash => Resource resource) private resources;
|
|
72
|
+
|
|
73
|
+
error ArrayLengthMismatch();
|
|
74
|
+
error DuplicatePath(bytes32 pathHash);
|
|
75
|
+
error EmptyResource(bytes32 pathHash);
|
|
76
|
+
error InvalidChunk(bytes32 pathHash, address chunk);
|
|
77
|
+
error ResourceLengthMismatch(bytes32 pathHash, uint256 expected, uint256 actual);
|
|
78
|
+
error MissingIndex();
|
|
79
|
+
|
|
80
|
+
constructor(
|
|
81
|
+
bytes32[] memory pathHashes,
|
|
82
|
+
string[] memory contentTypes,
|
|
83
|
+
address[][] memory chunks,
|
|
84
|
+
uint256[] memory lengths,
|
|
85
|
+
bytes32 expectedManifestHash
|
|
86
|
+
) {
|
|
87
|
+
uint256 count = pathHashes.length;
|
|
88
|
+
if (
|
|
89
|
+
count == 0 || count != contentTypes.length || count != chunks.length
|
|
90
|
+
|| count != lengths.length
|
|
91
|
+
) revert ArrayLengthMismatch();
|
|
92
|
+
|
|
93
|
+
manifestHash = expectedManifestHash;
|
|
94
|
+
for (uint256 i; i < count; ++i) {
|
|
95
|
+
bytes32 pathHash = pathHashes[i];
|
|
96
|
+
Resource storage target = resources[pathHash];
|
|
97
|
+
if (target.exists) revert DuplicatePath(pathHash);
|
|
98
|
+
if (lengths[i] == 0 || chunks[i].length == 0) revert EmptyResource(pathHash);
|
|
99
|
+
|
|
100
|
+
target.contentType = contentTypes[i];
|
|
101
|
+
target.length = lengths[i];
|
|
102
|
+
target.exists = true;
|
|
103
|
+
uint256 actualLength;
|
|
104
|
+
for (uint256 j; j < chunks[i].length; ++j) {
|
|
105
|
+
address chunk = chunks[i][j];
|
|
106
|
+
uint256 chunkLength = chunk.payloadSize();
|
|
107
|
+
if (chunkLength == 0 || chunkLength > ResurrectBytecodeStorage.MAX_CHUNK_BYTES) {
|
|
108
|
+
revert InvalidChunk(pathHash, chunk);
|
|
109
|
+
}
|
|
110
|
+
actualLength += chunkLength;
|
|
111
|
+
target.chunks.push(chunk);
|
|
112
|
+
}
|
|
113
|
+
if (actualLength != lengths[i]) {
|
|
114
|
+
revert ResourceLengthMismatch(pathHash, lengths[i], actualLength);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (!resources[INDEX_PATH_HASH].exists) revert MissingIndex();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function resolveMode() external pure returns (bytes32 mode) {
|
|
121
|
+
return "5219";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function request(string[] memory resource, KeyValue[] memory)
|
|
125
|
+
external
|
|
126
|
+
view
|
|
127
|
+
override
|
|
128
|
+
returns (uint16 statusCode, string memory body, KeyValue[] memory headers)
|
|
129
|
+
{
|
|
130
|
+
bytes32 pathHash;
|
|
131
|
+
if (resource.length == 0) {
|
|
132
|
+
pathHash = INDEX_PATH_HASH;
|
|
133
|
+
} else if (resource.length == 1) {
|
|
134
|
+
pathHash = keccak256(bytes(resource[0]));
|
|
135
|
+
} else {
|
|
136
|
+
return _notFound();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
Resource storage selected = resources[pathHash];
|
|
140
|
+
if (!selected.exists) return _notFound();
|
|
141
|
+
|
|
142
|
+
bytes memory data = new bytes(selected.length);
|
|
143
|
+
uint256 offset;
|
|
144
|
+
for (uint256 i; i < selected.chunks.length; ++i) {
|
|
145
|
+
address chunk = selected.chunks[i];
|
|
146
|
+
chunk.copy(data, offset);
|
|
147
|
+
offset += chunk.payloadSize();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
headers = _headers(selected.contentType, true);
|
|
151
|
+
return (200, string(data), headers);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function resourceInfo(string calldata path)
|
|
155
|
+
external
|
|
156
|
+
view
|
|
157
|
+
returns (bool exists, string memory contentType, uint256 length, address[] memory chunks)
|
|
158
|
+
{
|
|
159
|
+
Resource storage selected = resources[keccak256(bytes(path))];
|
|
160
|
+
return (selected.exists, selected.contentType, selected.length, selected.chunks);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function _notFound()
|
|
164
|
+
private
|
|
165
|
+
pure
|
|
166
|
+
returns (uint16 statusCode, string memory body, KeyValue[] memory headers)
|
|
167
|
+
{
|
|
168
|
+
return (404, "not found\n", _headers("text/plain; charset=utf-8", false));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function _headers(string memory contentType, bool immutableResource)
|
|
172
|
+
private
|
|
173
|
+
pure
|
|
174
|
+
returns (KeyValue[] memory headers)
|
|
175
|
+
{
|
|
176
|
+
headers = new KeyValue[](2);
|
|
177
|
+
headers[0] = KeyValue("Content-Type", contentType);
|
|
178
|
+
headers[1] = KeyValue(
|
|
179
|
+
"Cache-Control", immutableResource ? "public, max-age=31536000, immutable" : "no-store"
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: CC0-1.0
|
|
2
|
-
pragma solidity 0.8.24;
|
|
3
|
-
|
|
4
|
-
/// @title Resurrect registry v1
|
|
5
|
-
/// @notice Permissionless, immutable, log-only rendezvous for signed peer records.
|
|
6
|
-
/// @dev This contract deliberately has no owner, storage, upgrade, pause, or withdrawal path.
|
|
7
|
-
contract ResurrectRegistryV1 {
|
|
8
|
-
uint32 public constant VERSION = 1;
|
|
9
|
-
uint32 public constant MAX_TTL = 90 days;
|
|
10
|
-
uint32 public constant MAX_RECORD_BYTES = 4096;
|
|
11
|
-
|
|
12
|
-
error InvalidTTL();
|
|
13
|
-
error RecordTooLarge();
|
|
14
|
-
|
|
15
|
-
event PeerAnnounced(
|
|
16
|
-
bytes32 indexed namespace, uint32 indexed recordType, uint64 validUntil, bytes peerRecord
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
/// @notice Publishes a bounded-lifetime, application-namespaced signed peer record.
|
|
20
|
-
/// @param namespace Application/network isolation identifier.
|
|
21
|
-
/// @param recordType Resurrect peer-record codec identifier.
|
|
22
|
-
/// @param ttl Lifetime in seconds, bounded by `MAX_TTL`.
|
|
23
|
-
/// @param peerRecord Raw self-authenticating peer-record bytes.
|
|
24
|
-
function announce(bytes32 namespace, uint32 recordType, uint32 ttl, bytes calldata peerRecord)
|
|
25
|
-
external
|
|
26
|
-
{
|
|
27
|
-
if (ttl == 0 || ttl > MAX_TTL) revert InvalidTTL();
|
|
28
|
-
if (peerRecord.length == 0 || peerRecord.length > MAX_RECORD_BYTES) {
|
|
29
|
-
revert RecordTooLarge();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
emit PeerAnnounced(namespace, recordType, uint64(block.timestamp) + uint64(ttl), peerRecord);
|
|
33
|
-
}
|
|
34
|
-
}
|