@bananapus/address-registry-v6 0.0.16 → 0.0.18
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 +48 -29
- package/ARCHITECTURE.md +69 -42
- package/AUDIT_INSTRUCTIONS.md +44 -125
- package/CHANGELOG.md +39 -0
- package/README.md +77 -65
- package/RISKS.md +47 -14
- package/SKILLS.md +28 -147
- package/STYLE_GUIDE.md +56 -18
- package/USER_JOURNEYS.md +66 -69
- package/package.json +2 -2
- package/references/operations.md +14 -0
- package/references/runtime.md +19 -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
|
@@ -1,48 +1,67 @@
|
|
|
1
1
|
# Administration
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## At A Glance
|
|
4
|
+
|
|
5
|
+
| Item | Details |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| Scope | Permissionless provenance registration for CREATE and CREATE2 addresses |
|
|
8
|
+
| Control posture | Fully permissionless and adminless |
|
|
9
|
+
| Highest-risk actions | Incorrect first registration or bad derivation assumptions in offchain tooling |
|
|
10
|
+
| Recovery posture | No in-place recovery; replacement contract is the only fix for logic mistakes |
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
|
|
14
|
+
`nana-address-registry-v6` has no admin surface. It is a permissionless first-write provenance registry.
|
|
15
|
+
|
|
16
|
+
## Control Model
|
|
17
|
+
|
|
18
|
+
- No owner
|
|
19
|
+
- No governance
|
|
20
|
+
- No pause
|
|
21
|
+
- No upgrade
|
|
22
|
+
- Registration is permissionless and correctness comes from deterministic address derivation
|
|
4
23
|
|
|
5
24
|
## Roles
|
|
6
25
|
|
|
7
|
-
|
|
26
|
+
| Role | How Assigned | Scope | Notes |
|
|
27
|
+
| --- | --- | --- | --- |
|
|
28
|
+
| Anyone | No assignment | Global | Can register an address if they provide correct CREATE or CREATE2 inputs |
|
|
29
|
+
|
|
30
|
+
## Privileged Surfaces
|
|
8
31
|
|
|
9
|
-
|
|
32
|
+
There are no privileged functions. `registerAddress(...)` is permissionless for both CREATE and CREATE2 registration paths.
|
|
10
33
|
|
|
11
|
-
|
|
34
|
+
## Immutable And One-Way
|
|
12
35
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| `registerAddress(address deployer, uint256 nonce)` | None | N/A | Global | Computes a `create` address from deployer + nonce and stores the deployer mapping |
|
|
16
|
-
| `registerAddress(address deployer, bytes32 salt, bytes bytecode)` | None | N/A | Global | Computes a `create2` address from deployer + salt + bytecode and stores the deployer mapping |
|
|
17
|
-
| `deployerOf(address)` | None | N/A | Global | View function — returns the registered deployer for a given address |
|
|
36
|
+
- Registration is first-write only.
|
|
37
|
+
- There is no overwrite or delete path for `deployerOf[address]`.
|
|
18
38
|
|
|
19
|
-
|
|
39
|
+
## Operational Notes
|
|
20
40
|
|
|
21
|
-
|
|
41
|
+
- Treat registration as provenance, not endorsement.
|
|
42
|
+
- Register addresses from trustworthy operational pipelines because bad first registration is sticky even though anyone can submit the correct derivation inputs.
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
- **No caller verification.** The registry does not check whether `msg.sender` is the deployer. It only verifies that the computed address is valid by storing the mapping.
|
|
25
|
-
- **Overwritable.** A second registration for the same computed address overwrites the previous deployer mapping. Last writer wins.
|
|
26
|
-
- **Permanent storage, no removal.** There is no `unregister` or `removeAddress` function. Entries can be overwritten but never deleted.
|
|
27
|
-
- **No approval or queue.** Registrations take effect immediately in the same transaction.
|
|
44
|
+
## Machine Notes
|
|
28
45
|
|
|
29
|
-
|
|
46
|
+
- Do not treat registration as a safety certification or allowlist signal.
|
|
47
|
+
- `src/JBAddressRegistry.sol` is the only control-relevant runtime file; there is no hidden owner path.
|
|
48
|
+
- If offchain derivation and onchain registration disagree, stop and resolve the derivation logic rather than assuming overwrite is possible.
|
|
30
49
|
|
|
31
|
-
|
|
50
|
+
## Recovery
|
|
32
51
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- **Overwrite risk.** Since registrations are overwritable, a client that caches `deployerOf(addr)` at time T may see a different result at time T+1 if someone re-registers the same address with a different deployer/nonce or deployer/salt/bytecode combination. Clients should re-check at time of use rather than caching indefinitely.
|
|
36
|
-
- **No validation of deployment.** The registry computes the expected address from the inputs but does not verify that a contract actually exists at that address. A registration can be created for an address that has not yet been deployed (or will never be deployed).
|
|
52
|
+
- There is no admin recovery surface.
|
|
53
|
+
- If derivation logic were ever wrong, the contract would need replacement rather than intervention.
|
|
37
54
|
|
|
38
55
|
## Admin Boundaries
|
|
39
56
|
|
|
40
|
-
|
|
57
|
+
- Nobody can curate allowlists, edit entries, or block registration.
|
|
58
|
+
- Nobody can use this registry to certify code safety.
|
|
41
59
|
|
|
42
|
-
|
|
43
|
-
- **No upgrade path.** The contract is not proxied or upgradeable.
|
|
44
|
-
- **No fee extraction.** The contract holds no funds and collects no fees.
|
|
45
|
-
- **No blocklist.** No address can be prevented from registering.
|
|
46
|
-
- **No migration.** There is no way to transfer state to a new registry contract.
|
|
60
|
+
## Source Map
|
|
47
61
|
|
|
48
|
-
|
|
62
|
+
- `src/JBAddressRegistry.sol`
|
|
63
|
+
- `src/interfaces/IJBAddressRegistry.sol`
|
|
64
|
+
- `script/Deploy.s.sol`
|
|
65
|
+
- `script/helpers/AddressRegistryDeploymentLib.sol`
|
|
66
|
+
- `test/JBAddressRegistry_Fork.t.sol`
|
|
67
|
+
- `test/regression/NonceTruncation.t.sol`
|
package/ARCHITECTURE.md
CHANGED
|
@@ -1,57 +1,84 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Architecture
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`nana-address-registry-v6` is a narrow provenance primitive. It records which deployer could have created a contract address by recomputing CREATE or CREATE2 derivation inputs and storing the verified result on-chain.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## System Overview
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The repo is intentionally small. `JBAddressRegistry` accepts deterministic deployment inputs, reconstructs the resulting address, and records the deployer if that address has not already been registered. It does not judge code safety, manage upgrades, or gate deployments.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
src/
|
|
13
|
-
├── JBAddressRegistry.sol — Registry: registerAddress (create/create2), deployerOf mapping
|
|
14
|
-
└── interfaces/
|
|
15
|
-
└── IJBAddressRegistry.sol — Interface
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Key Operations
|
|
19
|
-
|
|
20
|
-
### Registration (create)
|
|
21
|
-
```
|
|
22
|
-
Deployer → JBAddressRegistry.registerAddress(deployer, nonce)
|
|
23
|
-
→ Compute address via RLP encoding of [deployer, nonce]
|
|
24
|
-
→ Store deployerOf[computedAddress] = deployer
|
|
25
|
-
→ Emit AddressRegistered
|
|
26
|
-
```
|
|
11
|
+
## Core Invariants
|
|
27
12
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
→ Store deployerOf[computedAddress] = deployer
|
|
33
|
-
→ Emit AddressRegistered
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Verification
|
|
37
|
-
```
|
|
38
|
-
Frontend → JBAddressRegistry.deployerOf(hookAddress)
|
|
39
|
-
→ Returns deployer address (or address(0) if unregistered)
|
|
40
|
-
→ Frontend checks deployer against trusted deployer list
|
|
41
|
-
```
|
|
13
|
+
- Registration is permissionless because correctness comes from deterministic derivation, not caller authority.
|
|
14
|
+
- A contract address can only be registered once.
|
|
15
|
+
- Registration must fail until runtime code actually exists at the derived address.
|
|
16
|
+
- CREATE and CREATE2 derivation must match EVM rules exactly.
|
|
42
17
|
|
|
43
|
-
##
|
|
18
|
+
## Modules
|
|
44
19
|
|
|
45
|
-
|
|
20
|
+
| Module | Responsibility | Notes |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `JBAddressRegistry` | Address derivation and first-write provenance storage | Main contract |
|
|
23
|
+
| `IJBAddressRegistry` | Minimal lookup and registration interface | External surface |
|
|
46
24
|
|
|
47
|
-
|
|
25
|
+
## Trust Boundaries
|
|
48
26
|
|
|
49
|
-
|
|
27
|
+
- The registry attests to deterministic provenance, not code quality.
|
|
28
|
+
- It does not manage ownership, upgrades, or allowlists.
|
|
29
|
+
- External systems may trust its recorded provenance, so derivation correctness is the whole product.
|
|
50
30
|
|
|
51
|
-
|
|
31
|
+
## Critical Flows
|
|
52
32
|
|
|
53
|
-
|
|
33
|
+
### Register
|
|
54
34
|
|
|
55
|
-
|
|
35
|
+
```text
|
|
36
|
+
caller
|
|
37
|
+
-> supplies deployer plus CREATE nonce or CREATE2 salt and bytecode
|
|
38
|
+
-> registry recomputes the target address
|
|
39
|
+
-> registry records the deployer if the address was previously unregistered
|
|
40
|
+
```
|
|
56
41
|
|
|
57
|
-
|
|
42
|
+
## Accounting Model
|
|
43
|
+
|
|
44
|
+
No economic accounting lives here. The only critical state is `deployerOf[address]`.
|
|
45
|
+
|
|
46
|
+
## Security Model
|
|
47
|
+
|
|
48
|
+
- The risk is concentrated in a small amount of address-derivation logic.
|
|
49
|
+
- The registry records the derived deployer, not the transaction caller. Mixing those concepts would turn provenance into an authority bug.
|
|
50
|
+
- Overengineering is more dangerous than minimal, auditable derivation code.
|
|
51
|
+
|
|
52
|
+
## Safe Change Guide
|
|
53
|
+
|
|
54
|
+
- Treat derivation code like cryptographic plumbing.
|
|
55
|
+
- Keep the undeployed-address check and first-write-only rule intact; they are part of the provenance guarantee, not optional hygiene.
|
|
56
|
+
- If nonce handling or bytecode hashing changes, keep CREATE and CREATE2 tests aligned.
|
|
57
|
+
- Do not expand the repo into an allowlist or trust-oracle system.
|
|
58
|
+
|
|
59
|
+
## Canonical Checks
|
|
60
|
+
|
|
61
|
+
- CREATE and CREATE2 derivation correctness:
|
|
62
|
+
`test/JBAddressRegistry.t.sol`
|
|
63
|
+
- edge-path validation and first-write behavior:
|
|
64
|
+
`test/JBAddressRegistryEdge.t.sol`
|
|
65
|
+
- pre-registration, frontrun, and undeployed-code defenses:
|
|
66
|
+
`test/audit/CodexFrontRunRegistrationDoS.t.sol`
|
|
67
|
+
- provenance abuse and zero-deployer edge cases:
|
|
68
|
+
`test/audit/CodexUnauthorizedRegistrar.t.sol`
|
|
69
|
+
`test/audit/ZeroDeployerRegistration.t.sol`
|
|
70
|
+
|
|
71
|
+
## Source Map
|
|
72
|
+
|
|
73
|
+
- `src/JBAddressRegistry.sol`
|
|
74
|
+
- `src/interfaces/IJBAddressRegistry.sol`
|
|
75
|
+
- `test/JBAddressRegistry.t.sol`
|
|
76
|
+
- `test/JBAddressRegistryEdge.t.sol`
|
|
77
|
+
- `test/audit/CodexFrontRunRegistrationDoS.t.sol`
|
|
78
|
+
- `test/audit/CodexUnauthorizedRegistrar.t.sol`
|
|
79
|
+
- `test/audit/ZeroDeployerRegistration.t.sol`
|
|
80
|
+
- `test/regression/NonceTruncation.t.sol`
|
|
81
|
+
- `script/Deploy.s.sol`
|
|
82
|
+
- `script/helpers/AddressRegistryDeploymentLib.sol`
|
|
83
|
+
- `references/runtime.md`
|
|
84
|
+
- `references/operations.md`
|
package/AUDIT_INSTRUCTIONS.md
CHANGED
|
@@ -1,147 +1,66 @@
|
|
|
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
|
+
## Audit 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:
|
|
15
|
+
In scope:
|
|
16
|
+
- `src/JBAddressRegistry.sol`
|
|
17
|
+
- `src/interfaces/IJBAddressRegistry.sol`
|
|
18
|
+
- all deployment helpers in `script/`
|
|
92
19
|
|
|
93
|
-
|
|
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).
|
|
20
|
+
## Start Here
|
|
98
21
|
|
|
99
|
-
|
|
22
|
+
1. `src/JBAddressRegistry.sol`
|
|
23
|
+
2. `script/Deploy.s.sol`
|
|
100
24
|
|
|
101
|
-
|
|
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).
|
|
25
|
+
## Security Model
|
|
105
26
|
|
|
106
|
-
|
|
27
|
+
The registry maps deployed addresses to the deployer that created them. Downstream repos use it to:
|
|
28
|
+
- validate provenance for clones or deterministically deployed instances
|
|
29
|
+
- discover whether a contract came from an approved deployer path
|
|
107
30
|
|
|
108
|
-
|
|
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.
|
|
31
|
+
## Roles And Privileges
|
|
112
32
|
|
|
113
|
-
|
|
33
|
+
| Role | Powers | How constrained |
|
|
34
|
+
|------|--------|-----------------|
|
|
35
|
+
| Deployer | Register contracts as its outputs | Must prove authentic deployment provenance |
|
|
36
|
+
| Registry reader | Trust provenance for privileged decisions | Must not observe spoofable or mutable history |
|
|
114
37
|
|
|
115
|
-
|
|
116
|
-
- `registerAddress` has bounded gas cost regardless of inputs.
|
|
117
|
-
- The `bytecode` parameter in the `create2` overload is hashed in memory. For very large bytecode, this could consume significant memory gas but cannot cause an OOG in the registry itself (the caller pays).
|
|
38
|
+
## Integration Assumptions
|
|
118
39
|
|
|
119
|
-
|
|
40
|
+
| Dependency | Assumption | What breaks if wrong |
|
|
41
|
+
|------------|------------|----------------------|
|
|
42
|
+
| Approved deployers | Produce the addresses they claim | Downstream provenance gates become meaningless |
|
|
120
43
|
|
|
121
|
-
|
|
122
|
-
2. **create2 correctness**: For any `(deployer, salt, bytecode)` triple, the computed address matches what the EVM would produce for a `create2` deployment.
|
|
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.
|
|
44
|
+
## Critical Invariants
|
|
125
45
|
|
|
126
|
-
|
|
46
|
+
1. Provenance cannot be forged
|
|
47
|
+
Only the actual deployer path the registry intends to trust may create a successful registration for a contract.
|
|
127
48
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
npm install
|
|
131
|
-
forge build
|
|
132
|
-
forge test
|
|
49
|
+
2. One contract maps to one authoritative deployer record
|
|
50
|
+
No aliasing or overwrite path should let a later caller replace provenance unexpectedly.
|
|
133
51
|
|
|
134
|
-
|
|
135
|
-
|
|
52
|
+
3. Registration metadata is stable
|
|
53
|
+
Nonce, salt, or address truncation must not allow collisions or stale reads.
|
|
136
54
|
|
|
137
|
-
|
|
138
|
-
forge test --match-path test/regression/NonceTruncation.t.sol -vvv
|
|
55
|
+
## Attack Surfaces
|
|
139
56
|
|
|
140
|
-
|
|
141
|
-
|
|
57
|
+
- registration entrypoints that rely on deployer provenance
|
|
58
|
+
- overwrite and replay paths
|
|
59
|
+
- deterministic deployment assumptions
|
|
60
|
+
- zero-address or malformed registration attempts
|
|
142
61
|
|
|
143
|
-
|
|
144
|
-
forge test --match-path test/audit/ExploitPoC.t.sol -vvv
|
|
145
|
-
```
|
|
62
|
+
## Verification
|
|
146
63
|
|
|
147
|
-
|
|
64
|
+
- `npm install`
|
|
65
|
+
- `forge build`
|
|
66
|
+
- `forge test`
|
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,111 @@
|
|
|
1
1
|
# Juicebox Address Registry
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@bananapus/address-registry-v6` is a permissionless registry that records deployer provenance for contracts when callers provide matching `create` or `create2` deployment inputs. 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
|
+
User journeys: [USER_JOURNEYS.md](./USER_JOURNEYS.md)
|
|
7
|
+
Skills: [SKILLS.md](./SKILLS.md)
|
|
8
|
+
Risks: [RISKS.md](./RISKS.md)
|
|
9
|
+
Administration: [ADMINISTRATION.md](./ADMINISTRATION.md)
|
|
10
|
+
Audit instructions: [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md)
|
|
6
11
|
|
|
7
|
-
##
|
|
12
|
+
## Overview
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
The registry supports both `create` and `create2` style deployments:
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```
|
|
16
|
+
- for `create`, it reconstructs the deployed address from the deployer and nonce
|
|
17
|
+
- for `create2`, it reconstructs the deployed address from the deployer, salt, and deployment bytecode
|
|
14
18
|
|
|
15
|
-
|
|
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 |
|
|
19
|
+
Because the address is computed deterministically, registrations do not require access control. Anyone can submit the correct deployment inputs, and the registry records the deployer for the computed address after confirming code already exists there.
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
Use this repo when deployer provenance matters. Do not confuse it with an allowlist, audit registry, or trust oracle.
|
|
27
22
|
|
|
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. |
|
|
23
|
+
If the question is "is this hook safe?" this repo can only tell you who deployed it, not whether the code is good.
|
|
31
24
|
|
|
32
|
-
|
|
25
|
+
## Key Contract
|
|
33
26
|
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
| `
|
|
27
|
+
| Contract | Role |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| `JBAddressRegistry` | Standalone registry that stores `deployerOf[address]` and exposes overloaded `registerAddress` entrypoints. |
|
|
37
30
|
|
|
38
|
-
|
|
31
|
+
## Mental Model
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
The registry is intentionally narrow:
|
|
41
34
|
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
1. reconstruct an address from deployment inputs
|
|
36
|
+
2. bind that address to a deployer once
|
|
37
|
+
3. expose the result for other systems and clients
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
Anything beyond that is out of scope by design.
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
## Read These Files First
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
1. `src/JBAddressRegistry.sol`
|
|
44
|
+
2. `test/JBAddressRegistry.t.sol`
|
|
45
|
+
3. `test/JBAddressRegistryEdge.t.sol`
|
|
46
|
+
4. `test/audit/CodexFrontRunRegistrationDoS.t.sol`
|
|
52
47
|
|
|
53
|
-
|
|
54
|
-
registry.registerAddress(deployer, salt, bytecode);
|
|
48
|
+
## Integration Traps
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
- provenance is only meaningful if callers also know what the deployer is supposed to be trusted for
|
|
51
|
+
- permissionless registration is intentional, so integrations should verify the computed inputs rather than assuming caller authority
|
|
52
|
+
- `create` nonce reconstruction and `create2` salt-bytecode reconstruction are different trust paths and should be reasoned about separately
|
|
53
|
+
|
|
54
|
+
## Where State Lives
|
|
59
55
|
|
|
60
|
-
|
|
56
|
+
- deployer provenance lives in `JBAddressRegistry`
|
|
57
|
+
- deployment truth still lives outside this repo in the target chain history and bytecode inputs
|
|
61
58
|
|
|
62
|
-
|
|
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. |
|
|
59
|
+
## High-Signal Tests
|
|
65
60
|
|
|
66
|
-
|
|
61
|
+
1. `test/JBAddressRegistry.t.sol`
|
|
62
|
+
2. `test/JBAddressRegistryEdge.t.sol`
|
|
63
|
+
3. `test/audit/CodexUnauthorizedRegistrar.t.sol`
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install @bananapus/address-registry-v6
|
|
69
|
+
```
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
## Development
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
```bash
|
|
74
|
+
npm install
|
|
75
|
+
forge build
|
|
76
|
+
forge test
|
|
77
|
+
```
|
|
73
78
|
|
|
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.
|
|
79
|
+
Useful scripts:
|
|
77
80
|
|
|
78
|
-
|
|
81
|
+
- `npm run test:fork`
|
|
82
|
+
- `npm run deploy:mainnets`
|
|
83
|
+
- `npm run deploy:testnets`
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
## Deployment Notes
|
|
81
86
|
|
|
82
|
-
|
|
87
|
+
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
88
|
|
|
84
|
-
##
|
|
89
|
+
## Repository Layout
|
|
85
90
|
|
|
86
|
-
```
|
|
87
|
-
|
|
91
|
+
```text
|
|
92
|
+
src/
|
|
93
|
+
JBAddressRegistry.sol
|
|
94
|
+
interfaces/
|
|
95
|
+
test/
|
|
96
|
+
unit, edge, fork, audit, and regression coverage
|
|
97
|
+
script/
|
|
98
|
+
Deploy.s.sol
|
|
99
|
+
helpers/
|
|
88
100
|
```
|
|
89
101
|
|
|
90
|
-
##
|
|
102
|
+
## Risks And Notes
|
|
103
|
+
|
|
104
|
+
- provenance is not the same thing as safety; a known deployer can still deploy unsafe code
|
|
105
|
+
- registrations are first-write only, so bad operational processes around initial registration can be sticky
|
|
106
|
+
- the `create` address path relies on nonce reconstruction and intentionally rejects unrealistic nonce ranges
|
|
107
|
+
|
|
108
|
+
## For AI Agents
|
|
91
109
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
| `forge build` | Compile contracts |
|
|
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 |
|
|
110
|
+
- Describe this repo as a provenance registry, not as an allowlist or safety oracle.
|
|
111
|
+
- Read the edge and audit tests before making claims about frontrunning or unauthorized registration.
|