@bananapus/address-registry-v6 0.0.16 → 0.0.17
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/ADMINISTRATION.md +26 -0
- package/ARCHITECTURE.md +30 -39
- package/AUDIT_INSTRUCTIONS.md +35 -130
- package/CHANGELOG.md +39 -0
- package/README.md +48 -70
- package/RISKS.md +18 -1
- package/SKILLS.md +26 -147
- package/STYLE_GUIDE.md +56 -18
- package/USER_JOURNEYS.md +29 -81
- package/package.json +2 -2
- package/references/operations.md +12 -0
- package/references/runtime.md +17 -0
- package/src/JBAddressRegistry.sol +12 -0
- package/test/JBAddressRegistryEdge.t.sol +62 -20
- package/test/audit/CodexFrontRunRegistrationDoS.t.sol +76 -0
- package/test/regression/NonceTruncation.t.sol +44 -1
- package/CHANGE_LOG.md +0 -130
package/ADMINISTRATION.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
Admin privileges and their scope in nana-address-registry-v6.
|
|
4
4
|
|
|
5
|
+
## At A Glance
|
|
6
|
+
|
|
7
|
+
| Item | Details |
|
|
8
|
+
|------|---------|
|
|
9
|
+
| Scope | Permissionless deployer registration and lookup only. There is no privileged admin surface. |
|
|
10
|
+
| Operators | Anyone can register address/deployer relationships; clients decide which deployers they trust. |
|
|
11
|
+
| Highest-risk actions | Relying on stale cached registry data or treating registry entries as trust endorsements instead of raw claims. |
|
|
12
|
+
| Recovery posture | Registry entries can be overwritten but not deleted. Operational recovery is client-side: re-check entries, maintain trusted deployer lists, or migrate consumers to a new registry. |
|
|
13
|
+
|
|
14
|
+
## Routine Operations
|
|
15
|
+
|
|
16
|
+
- Re-check `deployerOf()` at time of use instead of caching it indefinitely.
|
|
17
|
+
- Pair registry lookups with a separate trusted-deployer allowlist in clients or indexing infrastructure.
|
|
18
|
+
- Treat every registration as permissionless input, not proof that the caller was authorized by the deployer.
|
|
19
|
+
|
|
20
|
+
## One-Way Or High-Risk Actions
|
|
21
|
+
|
|
22
|
+
- There is no pause, owner override, or deletion path.
|
|
23
|
+
- A later registration can overwrite an earlier mapping for the same computed address.
|
|
24
|
+
- The registry does not verify that code is deployed at the registered address.
|
|
25
|
+
|
|
26
|
+
## Recovery Notes
|
|
27
|
+
|
|
28
|
+
- If client trust assumptions change, fix the client or indexer. The contract itself cannot block or roll back bad registrations.
|
|
29
|
+
- If the ecosystem needs different trust guarantees, the recovery path is a new registry design and client migration, not an admin action here.
|
|
30
|
+
|
|
5
31
|
## Roles
|
|
6
32
|
|
|
7
33
|
None. `JBAddressRegistry` has no owner, no admin, and no access control. The contract does not inherit from `Ownable`, `AccessControl`, or any permissioned pattern.
|
package/ARCHITECTURE.md
CHANGED
|
@@ -1,57 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Architecture
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`nana-address-registry-v6` is a tiny trust-attestation primitive. It records who deployed a contract by recomputing the deployed address from CREATE or CREATE2 inputs and storing the verified deployer on-chain.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Boundaries
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- The repo does not assess contract safety.
|
|
10
|
+
- It does not manage upgrades, ownership, or deployment permissions.
|
|
11
|
+
- It only answers one question: "which deployer could have created this address?"
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
src/
|
|
13
|
-
├── JBAddressRegistry.sol — Registry: registerAddress (create/create2), deployerOf mapping
|
|
14
|
-
└── interfaces/
|
|
15
|
-
└── IJBAddressRegistry.sol — Interface
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Key Operations
|
|
13
|
+
## Main Components
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
→ Store deployerOf[computedAddress] = deployer
|
|
25
|
-
→ Emit AddressRegistered
|
|
26
|
-
```
|
|
15
|
+
| Component | Responsibility |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `JBAddressRegistry` | Verifies deterministic address derivation and stores `deployerOf[address]` |
|
|
18
|
+
| `IJBAddressRegistry` | Minimal public interface for registration and lookup |
|
|
27
19
|
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
Deployer → JBAddressRegistry.registerAddress(deployer, salt, bytecode)
|
|
31
|
-
→ Compute address via keccak256(0xff ++ deployer ++ salt ++ keccak256(bytecode))
|
|
32
|
-
→ Store deployerOf[computedAddress] = deployer
|
|
33
|
-
→ Emit AddressRegistered
|
|
34
|
-
```
|
|
20
|
+
## Runtime Model
|
|
35
21
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
22
|
+
```text
|
|
23
|
+
caller
|
|
24
|
+
-> provides deployer plus CREATE nonce or CREATE2 salt+bytecode
|
|
25
|
+
-> registry recomputes the target address
|
|
26
|
+
-> registry stores the deployer for that address if it was not already registered
|
|
41
27
|
```
|
|
42
28
|
|
|
43
|
-
##
|
|
29
|
+
## Critical Invariants
|
|
44
30
|
|
|
45
|
-
|
|
31
|
+
- Registration is permissionless because correctness comes from deterministic address derivation, not caller authority.
|
|
32
|
+
- Re-registration must stay impossible.
|
|
33
|
+
- CREATE and CREATE2 derivations must match EVM address derivation exactly; this repo is useless if the reconstruction is even slightly wrong.
|
|
46
34
|
|
|
47
|
-
|
|
35
|
+
## Where Complexity Lives
|
|
48
36
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
**Anyone can call `registerAddress`.** Registration is not restricted to the deployer itself. Any account that knows the deployer address and nonce (or salt + bytecode) can register a contract. This is safe because the mapping is deterministic — providing incorrect inputs simply computes a different address, not a false registration for the target contract.
|
|
37
|
+
- Almost all of the risk is concentrated in a tiny amount of derivation logic.
|
|
38
|
+
- The repo is simple enough that overengineering is a bigger risk than underengineering.
|
|
52
39
|
|
|
53
40
|
## Dependencies
|
|
54
41
|
|
|
55
|
-
-
|
|
42
|
+
- None that matter semantically beyond Solidity's address derivation rules
|
|
43
|
+
|
|
44
|
+
## Safe Change Guide
|
|
56
45
|
|
|
57
|
-
|
|
46
|
+
- Treat derivation logic as cryptographic plumbing. Prefer no change over clever change.
|
|
47
|
+
- If you touch nonce handling or bytecode hashing, add or retain tests for both CREATE and CREATE2 paths.
|
|
48
|
+
- Do not turn this registry into a trust oracle. Keep the scope narrow.
|
package/AUDIT_INSTRUCTIONS.md
CHANGED
|
@@ -1,147 +1,52 @@
|
|
|
1
|
-
# Audit Instructions
|
|
1
|
+
# Audit Instructions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This repo is a small registry, but it participates in deployer verification across the ecosystem. Treat incorrect registration as a security boundary failure.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Objective
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
| via-IR | not enabled |
|
|
13
|
-
| Fuzz runs | 4,096 |
|
|
14
|
-
| Invariant runs | 1,024 (depth 100) |
|
|
15
|
-
|
|
16
|
-
Source: [`foundry.toml`](./foundry.toml)
|
|
17
|
-
|
|
18
|
-
## Previous Audit Findings
|
|
19
|
-
|
|
20
|
-
A Nemesis automated audit was conducted on 2026-03-17. Results are in [`.audit/findings/nemesis-verified.md`](./.audit/findings/nemesis-verified.md). Summary:
|
|
21
|
-
|
|
22
|
-
| ID | Severity | Title | Status |
|
|
23
|
-
|----|----------|-------|--------|
|
|
24
|
-
| NM-001 | LOW | Deployment library project name mismatch (`"nana-address-registry"` vs `"nana-address-registry-v6"`) | Open (deployment script only, no runtime impact) |
|
|
25
|
-
|
|
26
|
-
The core contract (`JBAddressRegistry`) was verified sound -- RLP encoding is correct across all 10 nonce ranges, CREATE2 computation matches EIP-1014. No CRITICAL, HIGH, or MEDIUM findings were identified.
|
|
27
|
-
|
|
28
|
-
No prior formal audit with finding IDs from an external security firm has been conducted.
|
|
7
|
+
Find issues that:
|
|
8
|
+
- let callers register contracts under the wrong deployer
|
|
9
|
+
- break determinism or uniqueness assumptions around registration
|
|
10
|
+
- let a malicious deployer spoof provenance for contracts it did not create
|
|
11
|
+
- create stale or truncation-related collisions in recorded mappings
|
|
29
12
|
|
|
30
13
|
## Scope
|
|
31
14
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
src/
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
**Out of scope:** Test files, deployment scripts, forge-std.
|
|
39
|
-
|
|
40
|
-
## Architecture
|
|
41
|
-
|
|
42
|
-
### JBAddressRegistry
|
|
43
|
-
|
|
44
|
-
A standalone, stateless-logic contract with a single storage mapping:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
mapping(address addr => address deployer) public deployerOf;
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Two public `registerAddress` overloads accept deployer parameters, compute the deterministic address, and store the mapping. No validation is performed beyond address computation and a nonce range check.
|
|
51
|
-
|
|
52
|
-
### Registration (create)
|
|
53
|
-
|
|
54
|
-
`registerAddress(address deployer, uint256 nonce)`:
|
|
55
|
-
1. Calls `_addressFrom(deployer, nonce)` to compute the `create` address via RLP encoding
|
|
56
|
-
2. Stores `deployerOf[computedAddress] = deployer`
|
|
57
|
-
3. Emits `AddressRegistered(computedAddress, deployer, msg.sender)`
|
|
58
|
-
|
|
59
|
-
### Registration (create2)
|
|
60
|
-
|
|
61
|
-
`registerAddress(address deployer, bytes32 salt, bytes calldata bytecode)`:
|
|
62
|
-
1. Computes `address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(bytecode))))))`
|
|
63
|
-
2. Stores `deployerOf[computedAddress] = deployer`
|
|
64
|
-
3. Emits `AddressRegistered(computedAddress, deployer, msg.sender)`
|
|
65
|
-
|
|
66
|
-
### RLP Encoding (_addressFrom)
|
|
67
|
-
|
|
68
|
-
The internal `_addressFrom(address origin, uint256 nonce)` function implements RLP encoding of `[origin, nonce]` for `create` address computation. It handles 10 nonce ranges covering `0` through `type(uint64).max`:
|
|
69
|
-
|
|
70
|
-
| Nonce Range | RLP Prefix Byte | Nonce Length Prefix |
|
|
71
|
-
|-------------|----------------|---------------------|
|
|
72
|
-
| `0` | `0xd6` | `0x80` (empty byte) |
|
|
73
|
-
| `1 - 0x7f` | `0xd6` | (none, raw byte) |
|
|
74
|
-
| `0x80 - 0xff` | `0xd7` | `0x81` |
|
|
75
|
-
| `0x100 - 0xffff` | `0xd8` | `0x82` |
|
|
76
|
-
| `0x10000 - 0xffffff` | `0xd9` | `0x83` |
|
|
77
|
-
| `0x1000000 - 0xffffffff` | `0xda` | `0x84` |
|
|
78
|
-
| `0x100000000 - 0xffffffffff` | `0xdb` | `0x85` |
|
|
79
|
-
| `0x10000000000 - 0xffffffffffff` | `0xdc` | `0x86` |
|
|
80
|
-
| `0x1000000000000 - 0xffffffffffffff` | `0xdd` | `0x87` |
|
|
81
|
-
| `0x100000000000000 - 0xffffffffffffffff` | `0xde` | `0x88` |
|
|
82
|
-
|
|
83
|
-
The final address is extracted from `keccak256(rlp_data)` via inline assembly: `mstore(0, hash); addr := mload(0)`.
|
|
84
|
-
|
|
85
|
-
Nonces above `type(uint64).max` revert with `JBAddressRegistry_NonceTooLarge`.
|
|
86
|
-
|
|
87
|
-
## Priority Audit Areas
|
|
88
|
-
|
|
89
|
-
### 1. RLP Encoding Correctness (Highest Priority)
|
|
90
|
-
|
|
91
|
-
The `_addressFrom` function is the only non-trivial logic in the contract. Verify:
|
|
92
|
-
|
|
93
|
-
- **Every nonce range boundary is correct.** The if/else chain must produce correct RLP for every boundary value: `0`, `1`, `0x7f`, `0x80`, `0xff`, `0x100`, `0xffff`, `0x10000`, etc., up to `type(uint64).max`. An off-by-one at any boundary would silently produce wrong addresses.
|
|
94
|
-
- **RLP prefix bytes are correct.** The first byte (`0xd6`-`0xde`) encodes the total length of the list. Verify each prefix matches the actual encoded data length (20-byte address + nonce encoding + overhead).
|
|
95
|
-
- **Nonce encoding is correct.** For nonce `0`, the RLP encoding is `0x80` (empty byte string), not `0x00`. For nonces `1-0x7f`, the nonce IS the RLP encoding (single byte). For `0x80+`, a length prefix is prepended.
|
|
96
|
-
- **Assembly address extraction.** The final `mstore(0, hash); addr := mload(0)` extracts the low 160 bits of the keccak256 hash. Verify this is equivalent to `address(uint160(uint256(hash)))`.
|
|
97
|
-
- **Comparison with reference implementations.** Cross-check against the Ethereum Yellow Paper, OpenZeppelin's `Create2` library, and the linked StackExchange reference (https://ethereum.stackexchange.com/a/87840/68134).
|
|
98
|
-
|
|
99
|
-
### 2. create2 Address Computation
|
|
100
|
-
|
|
101
|
-
The `create2` overload uses `abi.encodePacked(bytes1(0xff), deployer, salt, keccak256(bytecode))`. Verify:
|
|
102
|
-
- This matches the EIP-1014 specification exactly.
|
|
103
|
-
- The `bytes calldata bytecode` parameter is hashed correctly (constructor arguments must be included by the caller; the contract does not append them).
|
|
104
|
-
- No length ambiguity in the packed encoding (each component has fixed size: 1 + 20 + 32 + 32 = 85 bytes).
|
|
105
|
-
|
|
106
|
-
### 3. Overwrite Behavior
|
|
107
|
-
|
|
108
|
-
`_registerAddress` unconditionally overwrites `deployerOf[addr]`. Verify:
|
|
109
|
-
- A re-registration with the same parameters produces the same result (idempotent).
|
|
110
|
-
- A re-registration with different parameters that happen to compute the same address (collision) would overwrite. Since address collisions require a keccak256 collision, this is cryptographically infeasible -- but confirm there is no cheaper attack vector.
|
|
111
|
-
- The `caller` field in the `AddressRegistered` event correctly reflects `msg.sender`, not the `deployer` parameter.
|
|
15
|
+
In scope:
|
|
16
|
+
- `src/JBAddressRegistry.sol`
|
|
17
|
+
- `src/interfaces/IJBAddressRegistry.sol`
|
|
18
|
+
- deployment scripts in `script/`
|
|
112
19
|
|
|
113
|
-
|
|
20
|
+
## System Model
|
|
114
21
|
|
|
115
|
-
The
|
|
116
|
-
-
|
|
117
|
-
-
|
|
22
|
+
The registry maps deployed addresses to the deployer that created them. Downstream repos use it to:
|
|
23
|
+
- validate provenance for clones or deterministically deployed instances
|
|
24
|
+
- discover whether a contract came from an approved deployer path
|
|
118
25
|
|
|
119
|
-
## Invariants
|
|
26
|
+
## Critical Invariants
|
|
120
27
|
|
|
121
|
-
1.
|
|
122
|
-
|
|
123
|
-
3. **No side effects**: `registerAddress` only modifies `deployerOf[computedAddress]` and emits one event. No other state is touched.
|
|
124
|
-
4. **Nonce boundary completeness**: Every valid nonce (0 through `type(uint64).max`) produces a correct RLP encoding. No nonce in this range falls through without being encoded.
|
|
28
|
+
1. Provenance cannot be forged
|
|
29
|
+
Only the actual deployer path the registry intends to trust may create a successful registration for a contract.
|
|
125
30
|
|
|
126
|
-
|
|
31
|
+
2. One contract maps to one authoritative deployer record
|
|
32
|
+
No aliasing or overwrite path should let a later caller replace provenance unexpectedly.
|
|
127
33
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
npm install
|
|
131
|
-
forge build
|
|
132
|
-
forge test
|
|
34
|
+
3. Registration metadata is stable
|
|
35
|
+
Nonce, salt, or address truncation must not allow collisions or stale reads.
|
|
133
36
|
|
|
134
|
-
|
|
135
|
-
forge test --match-contract JBAddressRegistryEdge -vvv
|
|
37
|
+
## Threat Model
|
|
136
38
|
|
|
137
|
-
|
|
138
|
-
|
|
39
|
+
Prioritize:
|
|
40
|
+
- zero-address or malformed registration attempts
|
|
41
|
+
- deterministic deployment edge cases
|
|
42
|
+
- overwrite or replay behavior
|
|
43
|
+
- any assumption that `msg.sender` is sufficient proof without deployment linkage
|
|
139
44
|
|
|
140
|
-
|
|
141
|
-
forge test --match-contract Fork -vvv
|
|
45
|
+
## Build And Verification
|
|
142
46
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
47
|
+
Standard workflow:
|
|
48
|
+
- `npm install`
|
|
49
|
+
- `forge build`
|
|
50
|
+
- `forge test`
|
|
146
51
|
|
|
147
|
-
|
|
52
|
+
Tests already focus on zero deployers and nonce-truncation regressions. A meaningful finding here should show downstream trust in the registry becoming misplaced, not just a cosmetic mismatch.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This file describes the verified change from `nana-address-registry-v5` to the current `nana-address-registry-v6` repo.
|
|
6
|
+
|
|
7
|
+
## Current v6 surface
|
|
8
|
+
|
|
9
|
+
- `JBAddressRegistry`
|
|
10
|
+
- `IJBAddressRegistry`
|
|
11
|
+
|
|
12
|
+
## Summary
|
|
13
|
+
|
|
14
|
+
- Nonce handling is safer than in v5. The registry now guards against oversized nonces instead of silently producing the wrong derived address once the old encoding assumptions stopped holding.
|
|
15
|
+
- Zero-address deployers are explicitly rejected.
|
|
16
|
+
- The external surface remains intentionally small. This repo changed behavior more than shape.
|
|
17
|
+
- The repo moved from the v5 Solidity baseline to `0.8.28`.
|
|
18
|
+
|
|
19
|
+
## Verified deltas
|
|
20
|
+
|
|
21
|
+
- `_addressFrom(...)` now supports RLP nonce encoding through `uint64` instead of stopping at the old `uint32` path.
|
|
22
|
+
- `JBAddressRegistry_NonceTooLarge(uint256)` is thrown above that supported range.
|
|
23
|
+
- `JBAddressRegistry_ZeroDeployer()` is thrown when trying to register against `address(0)`.
|
|
24
|
+
- Duplicate registration now explicitly reverts with `JBAddressRegistry_AlreadyRegistered(address)`.
|
|
25
|
+
|
|
26
|
+
## Breaking ABI changes
|
|
27
|
+
|
|
28
|
+
- There is no meaningful function-selector migration here.
|
|
29
|
+
- The practical ABI-visible change is new custom errors that callers and tooling may need to decode.
|
|
30
|
+
|
|
31
|
+
## Indexer impact
|
|
32
|
+
|
|
33
|
+
- Event shape is effectively unchanged.
|
|
34
|
+
- The real migration concern is stricter revert behavior for previously tolerated bad inputs.
|
|
35
|
+
|
|
36
|
+
## Migration notes
|
|
37
|
+
|
|
38
|
+
- If you treated this repo as ABI-stable, that is mostly still true, but behavior around bad inputs is stricter.
|
|
39
|
+
- Recheck any tool that depended on silent high-nonce behavior. v6 makes that path explicit instead of permissive.
|
package/README.md
CHANGED
|
@@ -1,99 +1,77 @@
|
|
|
1
1
|
# Juicebox Address Registry
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@bananapus/address-registry-v6` is a permissionless registry that records which deployer created a contract. It is meant to make deployer provenance visible on-chain, especially for hooks and helper contracts that users may need to trust before interacting with them.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Overview
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The registry supports both `create` and `create2` style deployments:
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
| Network | Chain ID |
|
|
16
|
-
|---------|----------|
|
|
17
|
-
| Ethereum | 1 |
|
|
18
|
-
| Optimism | 10 |
|
|
19
|
-
| Arbitrum | 42161 |
|
|
20
|
-
| Base | 8453 |
|
|
21
|
-
| Ethereum Sepolia | 11155111 |
|
|
22
|
-
| Optimism Sepolia | 11155420 |
|
|
23
|
-
| Arbitrum Sepolia | 421614 |
|
|
24
|
-
| Base Sepolia | 84532 |
|
|
25
|
-
|
|
26
|
-
## Architecture
|
|
11
|
+
- for `create`, it reconstructs the deployed address from the deployer and nonce
|
|
12
|
+
- for `create2`, it reconstructs the deployed address from the deployer, salt, and deployment bytecode
|
|
27
13
|
|
|
28
|
-
|
|
29
|
-
|----------|-------------|
|
|
30
|
-
| `JBAddressRegistry` | Standalone registry. Computes deployed addresses deterministically from deployer parameters and stores the deployer in `deployerOf`. No constructor arguments, no access control, no external dependencies. |
|
|
14
|
+
Because the address is computed deterministically, registrations do not require access control. Anyone can submit the correct deployment inputs, and the registry records the verified deployer for the computed address.
|
|
31
15
|
|
|
32
|
-
|
|
16
|
+
Use this repo when deployer provenance matters. Do not confuse it with an allowlist, audit registry, or trust oracle.
|
|
33
17
|
|
|
34
|
-
|
|
35
|
-
|------|-------------|
|
|
36
|
-
| `IJBAddressRegistry` | Interface exposing `deployerOf`, both `registerAddress` overloads, and the `AddressRegistered` event. |
|
|
18
|
+
If the question is "is this hook safe?" this repo can only tell you who deployed it, not whether the code is good.
|
|
37
19
|
|
|
38
|
-
|
|
20
|
+
## Key Contract
|
|
39
21
|
|
|
40
|
-
|
|
22
|
+
| Contract | Role |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `JBAddressRegistry` | Standalone registry that stores `deployerOf[address]` and exposes overloaded `registerAddress` entrypoints. |
|
|
41
25
|
|
|
42
|
-
|
|
43
|
-
- **`create2` deployments**: Provide the deployer address, the `create2` salt, and the full deployment bytecode (creation code + encoded constructor arguments). The registry computes `keccak256(0xff ++ deployer ++ salt ++ keccak256(bytecode))`.
|
|
26
|
+
## Mental Model
|
|
44
27
|
|
|
45
|
-
|
|
28
|
+
The registry is intentionally narrow:
|
|
46
29
|
|
|
47
|
-
|
|
30
|
+
1. reconstruct an address from deployment inputs
|
|
31
|
+
2. bind that address to a deployer once
|
|
32
|
+
3. expose the result for other systems and clients
|
|
48
33
|
|
|
49
|
-
|
|
50
|
-
// Register a contract deployed via create.
|
|
51
|
-
registry.registerAddress(deployer, nonce);
|
|
34
|
+
Anything beyond that is out of scope by design.
|
|
52
35
|
|
|
53
|
-
|
|
54
|
-
registry.registerAddress(deployer, salt, bytecode);
|
|
36
|
+
## Install
|
|
55
37
|
|
|
56
|
-
|
|
57
|
-
|
|
38
|
+
```bash
|
|
39
|
+
npm install @bananapus/address-registry-v6
|
|
58
40
|
```
|
|
59
41
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
| Event | Fields | Emitted When |
|
|
63
|
-
|-------|--------|-------------|
|
|
64
|
-
| `AddressRegistered` | `address indexed addr`, `address indexed deployer`, `address caller` | A contract address is registered via either `registerAddress` overload. `caller` is `msg.sender`, which may differ from the deployer. |
|
|
65
|
-
|
|
66
|
-
### Risks
|
|
42
|
+
## Development
|
|
67
43
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
44
|
+
```bash
|
|
45
|
+
npm install
|
|
46
|
+
forge build
|
|
47
|
+
forge test
|
|
48
|
+
```
|
|
73
49
|
|
|
74
|
-
|
|
75
|
-
- Re-registration is prevented: registering the same computed address again reverts with `JBAddressRegistry_AlreadyRegistered`. Only the first registration is accepted.
|
|
76
|
-
- Registration is permissionless -- anyone can call `registerAddress`, not just the deployer. Security relies entirely on deterministic address computation.
|
|
50
|
+
Useful scripts:
|
|
77
51
|
|
|
78
|
-
|
|
52
|
+
- `npm run test:fork`
|
|
53
|
+
- `npm run deploy:mainnets`
|
|
54
|
+
- `npm run deploy:testnets`
|
|
79
55
|
|
|
80
|
-
|
|
56
|
+
## Deployment Notes
|
|
81
57
|
|
|
82
|
-
|
|
58
|
+
The deploy script uses Sphinx for deterministic deployment. This package is intentionally small and independent because many other repos use it to record clone factories and helper deployments.
|
|
83
59
|
|
|
84
|
-
##
|
|
60
|
+
## Repository Layout
|
|
85
61
|
|
|
86
|
-
```
|
|
87
|
-
|
|
62
|
+
```text
|
|
63
|
+
src/
|
|
64
|
+
JBAddressRegistry.sol
|
|
65
|
+
interfaces/
|
|
66
|
+
test/
|
|
67
|
+
unit, edge, fork, audit, and regression coverage
|
|
68
|
+
script/
|
|
69
|
+
Deploy.s.sol
|
|
70
|
+
helpers/
|
|
88
71
|
```
|
|
89
72
|
|
|
90
|
-
##
|
|
73
|
+
## Risks And Notes
|
|
91
74
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
| `forge test` | Run unit tests |
|
|
96
|
-
| `FOUNDRY_PROFILE=CI forge test` | Run fork tests (requires `RPC_ETHEREUM_MAINNET` env var) |
|
|
97
|
-
| `forge coverage --match-path "./src/*.sol" --report lcov --report summary` | Generate coverage report |
|
|
98
|
-
| `npm run deploy:mainnets` | Propose mainnet deployment via Sphinx |
|
|
99
|
-
| `npm run deploy:testnets` | Propose testnet deployment via Sphinx |
|
|
75
|
+
- provenance is not the same thing as safety; a known deployer can still deploy unsafe code
|
|
76
|
+
- registrations are first-write only, so bad operational processes around initial registration can be sticky
|
|
77
|
+
- the `create` address path relies on nonce reconstruction and intentionally rejects unrealistic nonce ranges
|
package/RISKS.md
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Juicebox Address Registry Risk Register
|
|
2
|
+
|
|
3
|
+
This file focuses on the registry's core promise: recording claimed deployer linkage for deterministically derived contracts. The main risks are misuse, incorrect assumptions about what registration means, and collisions between social trust and on-chain truth.
|
|
4
|
+
|
|
5
|
+
## How to use this file
|
|
6
|
+
|
|
7
|
+
- Read `Priority risks` first; the biggest risks here are almost all interpretive, not balance-sheet failures.
|
|
8
|
+
- Use the detailed sections to distinguish what the registry proves from what users may incorrectly infer from it.
|
|
9
|
+
- Treat `Invariants to Verify` as the minimal safety envelope for deterministic registration.
|
|
10
|
+
|
|
11
|
+
## Priority risks
|
|
12
|
+
|
|
13
|
+
| Priority | Risk | Why it matters | Primary controls |
|
|
14
|
+
|----------|------|----------------|------------------|
|
|
15
|
+
| P1 | Over-trusting registration as approval | The registry proves deployer linkage, not code safety or ecosystem endorsement. Users can still trust malicious deployments. | Clear docs, UI labeling, and strict separation between proof of origin and proof of safety. |
|
|
16
|
+
| P1 | Incorrect deployment-parameter assumptions | Deterministic verification is only as good as the deployment parameters supplied. Wrong assumptions create false negatives or confusing operator workflows. | Strong test coverage around CREATE and CREATE2 derivation and explicit documentation. |
|
|
17
|
+
| P2 | Registry completeness assumptions | Useful contracts may remain unregistered; absence from the registry is not proof of absence or malice. | Operational guidance for clients and integrators to treat registration as additive evidence only. |
|
|
18
|
+
|
|
2
19
|
|
|
3
20
|
## 1. Trust Assumptions
|
|
4
21
|
|