@pvium/p2id-core 0.1.1 → 0.1.3
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 +2 -0
- package/contracts/P2IDVault.sol +119 -140
- package/contracts/PviumIdentity.sol +23 -36
- package/contracts/PviumP2IDPolicy.sol +4 -7
- package/contracts/PviumP2IDVaultProxy.sol +169 -0
- package/contracts/PviumP2IdVaultFactory.sol +142 -28
- package/contracts/PviumVerifier.sol +13 -21
- package/contracts/interfaces/IP2IDPolicy.sol +5 -21
- package/contracts/interfaces/IP2IDVault.sol +24 -17
- package/contracts/interfaces/IP2IDVaultProxy.sol +38 -0
- package/contracts/interfaces/IP2IDVerifier.sol +9 -13
- package/contracts/interfaces/IP2IdVaultFactory.sol +34 -7
- package/contracts/interfaces/IPviumIdentity.sol +5 -7
- package/contracts/lib/P2IDHash.sol +5 -5
- package/dist/cjs/p2idConstants.js +2 -2
- package/dist/esm/p2idConstants.d.ts +2 -2
- package/dist/esm/p2idConstants.js +2 -2
- package/package.json +2 -2
|
@@ -6,22 +6,16 @@ import {P2IDHash} from "./lib/P2IDHash.sol";
|
|
|
6
6
|
import {PviumIdentity} from "./PviumIdentity.sol";
|
|
7
7
|
|
|
8
8
|
/// @title PviumVerifier
|
|
9
|
-
/// @notice
|
|
10
|
-
///
|
|
11
|
-
/// given, that the registered attestation signer has signed that commitment.
|
|
9
|
+
/// @notice Resolves an EVM wallet from a PviumIdentity attestation and checks an optional
|
|
10
|
+
/// constraint signature against the registered constraint signers.
|
|
12
11
|
/// @dev proof = abi.encode(bytes zkProof, bytes32[] publicInputs). The wallet returned is the
|
|
13
12
|
/// EVM address the circuit read out of the Privy-signed token (public input 1), cross-checked
|
|
14
13
|
/// here against the proof's walletHash with the same formula. A constraint is satisfied by
|
|
15
14
|
/// a registered signer's EIP-712 signature over `Constraint(bytes32 commitment)` in this
|
|
16
|
-
/// contract's domain (name "PviumVerifier", version "1", chain id, this address)
|
|
17
|
-
///
|
|
18
|
-
///
|
|
19
|
-
///
|
|
20
|
-
/// the wallet, so a compromised signer or owner can release screened funds to their rightful
|
|
21
|
-
/// payee early but cannot redirect them. An owner of address(0) freezes the set.
|
|
22
|
-
/// What a commitment means is up to the funder; for a screening attestation it should
|
|
23
|
-
/// commit to the payee as well as the policy, plus a salt (see screeningCommitment),
|
|
24
|
-
/// otherwise one signature releases every deposit under that policy for every payee.
|
|
15
|
+
/// contract's domain (name "PviumVerifier", version "1", chain id, this address).
|
|
16
|
+
/// The PviumIdentity address is immutable; its accepted key set can change separately.
|
|
17
|
+
/// Constraint signatures authorize a commitment, while the attestation supplies the wallet.
|
|
18
|
+
/// This contract does not interpret the commitment's contents or enforce signature single-use.
|
|
25
19
|
contract PviumVerifier is IP2IDVerifier {
|
|
26
20
|
bytes32 private constant EIP712_DOMAIN_TYPEHASH =
|
|
27
21
|
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
|
|
@@ -51,7 +45,7 @@ contract PviumVerifier is IP2IDVerifier {
|
|
|
51
45
|
error NotPendingOwner();
|
|
52
46
|
error InvalidSigner();
|
|
53
47
|
|
|
54
|
-
/// @param _owner
|
|
48
|
+
/// @param _owner Constraint-signer administrator; address(0) disables owner-only calls.
|
|
55
49
|
/// @param _signers Initial constraint signers (may be empty: constraints unsupported until one is added).
|
|
56
50
|
constructor(PviumIdentity _pviumIdentity, address _owner, address[] memory _signers) {
|
|
57
51
|
pviumIdentity = _pviumIdentity;
|
|
@@ -62,8 +56,7 @@ contract PviumVerifier is IP2IDVerifier {
|
|
|
62
56
|
_cachedDomainSeparator = _domainSeparator(block.chainid);
|
|
63
57
|
}
|
|
64
58
|
|
|
65
|
-
/// @notice
|
|
66
|
-
/// now on, including for deposits already funded; those wait for a registered signer.
|
|
59
|
+
/// @notice Set a constraint signer's membership. Signatures are checked against current membership.
|
|
67
60
|
function setConstraintSigner(address signer, bool allowed) external onlyOwner {
|
|
68
61
|
_setSigner(signer, allowed);
|
|
69
62
|
}
|
|
@@ -80,7 +73,7 @@ contract PviumVerifier is IP2IDVerifier {
|
|
|
80
73
|
pendingOwner = address(0);
|
|
81
74
|
}
|
|
82
75
|
|
|
83
|
-
/// @notice EIP-712 domain separator; recomputed
|
|
76
|
+
/// @notice EIP-712 domain separator; recomputed when block.chainid differs from its deployment value.
|
|
84
77
|
function DOMAIN_SEPARATOR() public view returns (bytes32) {
|
|
85
78
|
return block.chainid == _cachedChainId ? _cachedDomainSeparator : _domainSeparator(block.chainid);
|
|
86
79
|
}
|
|
@@ -97,7 +90,7 @@ contract PviumVerifier is IP2IDVerifier {
|
|
|
97
90
|
) external view returns (address wallet, uint64 iat) {
|
|
98
91
|
(bytes memory zkProof, bytes32[] memory publicInputs) = abi.decode(proof, (bytes, bytes32[]));
|
|
99
92
|
|
|
100
|
-
//
|
|
93
|
+
// Verify against PviumIdentity's current accepted signer set.
|
|
101
94
|
PviumIdentity.Attestation memory a = pviumIdentity.verifyAttestation(zkProof, publicInputs);
|
|
102
95
|
if (a.identityHash != identityHash) revert IdentityMismatch();
|
|
103
96
|
if (a.wallet == address(0)) revert NoEvmWallet();
|
|
@@ -111,8 +104,7 @@ contract PviumVerifier is IP2IDVerifier {
|
|
|
111
104
|
}
|
|
112
105
|
|
|
113
106
|
/// @inheritdoc IP2IDVerifier
|
|
114
|
-
/// @dev
|
|
115
|
-
/// contract's key revocations count.
|
|
107
|
+
/// @dev Forward the identity key-set revision; constraint-signer changes do not increment it.
|
|
116
108
|
function revision() external view returns (uint64) {
|
|
117
109
|
return pviumIdentity.keySetRevision();
|
|
118
110
|
}
|
|
@@ -127,8 +119,8 @@ contract PviumVerifier is IP2IDVerifier {
|
|
|
127
119
|
return keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(CONSTRAINT_TYPEHASH, commitment))));
|
|
128
120
|
}
|
|
129
121
|
|
|
130
|
-
/// @notice
|
|
131
|
-
///
|
|
122
|
+
/// @notice Hash policyHash, identityHash and caller-supplied salt using abi.encode.
|
|
123
|
+
/// Does not generate a salt or enforce uniqueness.
|
|
132
124
|
function screeningCommitment(bytes32 policyHash, bytes32 identityHash, bytes32 salt) public pure returns (bytes32) {
|
|
133
125
|
return keccak256(abi.encode(policyHash, identityHash, salt));
|
|
134
126
|
}
|
|
@@ -2,26 +2,11 @@
|
|
|
2
2
|
pragma solidity ^0.8.27;
|
|
3
3
|
|
|
4
4
|
/// @title IP2IDPolicy
|
|
5
|
-
/// @notice
|
|
6
|
-
///
|
|
7
|
-
///
|
|
8
|
-
/// a timelock; every vault consults the factory's current policy on each call.
|
|
9
|
-
///
|
|
10
|
-
/// What a policy decides, and the limits the vault enforces on it:
|
|
11
|
-
/// - which verifiers deposits may be funded under and claimed through. Gating is the one
|
|
12
|
-
/// thing a policy can use to stop claims (by disallowing a verifier), which freezes
|
|
13
|
-
/// claims under it but never moves funds; refunds never consult the policy.
|
|
14
|
-
/// - the protocol fee on payouts, in basis points. The vault caps it at its own
|
|
15
|
-
/// MAX_FEE_BPS, fixes a deposit's rate when the deposit is made, never charges it on
|
|
16
|
-
/// refunds, and treats a failing quote as no fee.
|
|
17
|
-
/// - how accrued fees are distributed. Fees accrue in each vault per (verifier, token);
|
|
18
|
-
/// anyone can have a vault hand them to the policy (withdrawFees), which pulls them and
|
|
19
|
-
/// splits them however it chooses, e.g. between a verifier's operator and the protocol.
|
|
20
|
-
///
|
|
21
|
-
/// Launch policy: an owner-managed verifier allowlist and no fee. Permissionless,
|
|
22
|
-
/// stake-based verifier registration and fees are later policies.
|
|
5
|
+
/// @notice Verifier approval, fee quotation and fee distribution callbacks used by P2IDVault.
|
|
6
|
+
/// @dev P2IDVault caps fee quotes, stores rates on funded deposits and quotes untracked funds at
|
|
7
|
+
/// sweep time. It skips policy approval for claims through the current default verifier.
|
|
23
8
|
interface IP2IDPolicy {
|
|
24
|
-
/// @notice
|
|
9
|
+
/// @notice Approval used for funding and for claims through a non-default verifier.
|
|
25
10
|
function isVerifierAllowed(address verifier) external view returns (bool);
|
|
26
11
|
|
|
27
12
|
/// @notice Fee on paying out `token` claimed through `verifier`, in basis points. Quoted when a
|
|
@@ -31,8 +16,7 @@ interface IP2IDPolicy {
|
|
|
31
16
|
/// @notice Called by a vault holding fees earned through `verifier`. For an ERC-20 the vault
|
|
32
17
|
/// first approves this policy for exactly `amount`: pull the tokens (transferFrom the
|
|
33
18
|
/// caller) and distribute them; whatever is not pulled stays accrued in the vault, and
|
|
34
|
-
/// the allowance is reset afterwards.
|
|
35
|
-
/// self-verifying: a caller that is not a vault can only give away its own tokens.
|
|
19
|
+
/// the allowance is reset afterwards.
|
|
36
20
|
/// For the native coin (token == address(0)) the vault sends `amount` as msg.value
|
|
37
21
|
/// instead, and all of it counts as distributed.
|
|
38
22
|
function distributeFee(address verifier, address token, uint256 amount) external payable;
|
|
@@ -4,10 +4,8 @@ pragma solidity ^0.8.27;
|
|
|
4
4
|
import {IP2IDVerifier} from "./IP2IDVerifier.sol";
|
|
5
5
|
|
|
6
6
|
/// @title IP2IDVault
|
|
7
|
-
/// @notice
|
|
8
|
-
///
|
|
9
|
-
/// Every deposit names the verifier whose proofs can release it; the factory's policy
|
|
10
|
-
/// decides which verifiers are allowed and what (capped) fee applies.
|
|
7
|
+
/// @notice Deposit funding, claims, refunds and accounting for one identity commitment.
|
|
8
|
+
/// Token address(0) denotes native coin. Each deposit records its verifier and fee rate.
|
|
11
9
|
interface IP2IDVault {
|
|
12
10
|
/// @dev Field order packs into 5 storage slots:
|
|
13
11
|
/// [funder, fundedAt, consumed] [token, refundWindow] [verifier, feeBps] [amount] [constraint].
|
|
@@ -25,8 +23,7 @@ interface IP2IDVault {
|
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
// ------------------------------------------------------------------ events
|
|
28
|
-
//
|
|
29
|
-
// Sweeps also emit one aggregate event with the net amount paid and the fee.
|
|
26
|
+
// Funding emits Funded; consumption emits Refunded or Claimed. Sweeps emit aggregate amounts.
|
|
30
27
|
|
|
31
28
|
/// @notice A deposit was recorded via fund()/fundWith()/fundFor().
|
|
32
29
|
/// @param ref Opaque application reference; zero means absent. Emitted only, not stored or enforced as unique.
|
|
@@ -35,15 +32,15 @@ interface IP2IDVault {
|
|
|
35
32
|
event Refunded(uint256 indexed depositId, address indexed funder, address indexed token, uint256 amount);
|
|
36
33
|
/// @notice A deposit was paid out by a sweep: `amount` gross, of which `fee` accrued as a fee.
|
|
37
34
|
event Claimed(uint256 indexed depositId, address indexed to, uint256 amount, uint256 fee);
|
|
38
|
-
/// @notice
|
|
35
|
+
/// @notice The owner cache was set or revalidated under the verifier's current revision.
|
|
39
36
|
event OwnerRefreshed(address indexed verifier, address indexed owner, uint64 iat);
|
|
40
|
-
/// @notice Default
|
|
37
|
+
/// @notice Default sweep result, including eligible untracked funds; amount is net of fee and may be zero.
|
|
41
38
|
event Swept(address indexed verifier, address indexed token, uint256 amount, uint256 fee, address indexed to, uint256 depositsConsumed);
|
|
42
39
|
/// @notice Funds from a constrained bucket were paid to the wallet the proof resolved to (`amount` net of `fee`).
|
|
43
40
|
event SweptBucket(address indexed verifier, bytes32 indexed constraint, address indexed token, uint256 amount, uint256 fee, address to, uint256 depositsConsumed);
|
|
44
41
|
/// @notice A fee accrued for `verifier`; it stays in the vault until withdrawFees() hands it to the policy.
|
|
45
42
|
event FeeAccrued(address indexed verifier, address indexed token, uint256 amount);
|
|
46
|
-
/// @notice
|
|
43
|
+
/// @notice Amount deducted from accrued fees after policy distribution, via token pull or native transfer.
|
|
47
44
|
event FeesDistributed(address indexed verifier, address indexed token, uint256 amount, address policy);
|
|
48
45
|
|
|
49
46
|
// setup (factory only, once)
|
|
@@ -56,7 +53,7 @@ interface IP2IDVault {
|
|
|
56
53
|
/// @notice Fund under any verifier the factory's policy allows.
|
|
57
54
|
/// @param ref Opaque application reference emitted in Funded; bytes32(0) for none.
|
|
58
55
|
function fundWith(address verifier, address token, uint256 amount, bytes32 constraint, uint64 refundWindow, bytes32 ref) external payable returns (uint256 depositId);
|
|
59
|
-
/// @notice Factory-only: record a deposit
|
|
56
|
+
/// @notice Factory-only: record a deposit for `funder`; pull ERC-20 from the factory or receive native msg.value.
|
|
60
57
|
/// @param ref Opaque application reference emitted in Funded; bytes32(0) for none.
|
|
61
58
|
function fundFor(address funder, address verifier, address token, uint256 amount, bytes32 constraint, uint64 refundWindow, bytes32 ref) external payable returns (uint256 depositId);
|
|
62
59
|
function refund(uint256 depositId) external;
|
|
@@ -66,9 +63,16 @@ interface IP2IDVault {
|
|
|
66
63
|
/// if the proof is newer than anything seen under it, and retires older proofs.
|
|
67
64
|
function refreshProof(address verifier, bytes calldata proof) external;
|
|
68
65
|
function refreshProofAndSweep(address verifier, bytes calldata proof, address token, uint256 depositCountLimit) external returns (uint256 amount, uint256 consumed);
|
|
66
|
+
/// @notice Apply a proof the vault's own proxy has already verified (msg.sender must be this
|
|
67
|
+
/// address): the freshness, revision and owner-cache rules of refreshProof without
|
|
68
|
+
/// re-verifying. Reverts unless `wallet` is the recorded owner under `verifier` afterwards.
|
|
69
|
+
/// Returns its own selector as acknowledgement so the proxy rejects empty fallbacks.
|
|
70
|
+
/// The acknowledgement checks compatibility; implementations remain trusted to apply the result.
|
|
71
|
+
function acceptOwnerProof(address verifier, address wallet, uint64 iat) external returns (bytes4);
|
|
69
72
|
|
|
70
73
|
// claiming (amounts returned are net of fees)
|
|
71
|
-
/// @notice Sweep
|
|
74
|
+
/// @notice Sweep a page of the verifier's default bucket to its cached owner. Eligible untracked
|
|
75
|
+
/// funds are included for the current default verifier when its cache meets the cross-default floor.
|
|
72
76
|
function sweep(address verifier, address token, uint256 depositCountLimit) external returns (uint256 amount, uint256 consumed);
|
|
73
77
|
function sweepUntracked(address token) external returns (uint256 amount);
|
|
74
78
|
function sweepDeposits(address verifier, address token, uint256[] calldata depositIds) external returns (uint256 amount);
|
|
@@ -83,9 +87,11 @@ interface IP2IDVault {
|
|
|
83
87
|
/// @notice P2ID vault interface version implemented by this contract.
|
|
84
88
|
function p2idVersion() external pure returns (string memory);
|
|
85
89
|
function MAX_FEE_BPS() external view returns (uint16);
|
|
90
|
+
/// @notice Record cap for cursor-based sweeps; a zero or above-cap depositCountLimit uses this value.
|
|
91
|
+
function MAX_SWEEP_PAGE() external view returns (uint256);
|
|
86
92
|
/// @notice address(0): the token address standing for the native coin.
|
|
87
93
|
function NATIVE() external view returns (address);
|
|
88
|
-
/// @notice
|
|
94
|
+
/// @notice Namespace value supplied at initialization; not used to recompute this vault's address.
|
|
89
95
|
function nsHash() external view returns (bytes32);
|
|
90
96
|
function factory() external view returns (address);
|
|
91
97
|
function policy() external view returns (address);
|
|
@@ -96,17 +102,18 @@ interface IP2IDVault {
|
|
|
96
102
|
function untrackedProofIat() external view returns (uint64);
|
|
97
103
|
function saltCommitment() external view returns (bytes32);
|
|
98
104
|
function depositCount() external view returns (uint256);
|
|
99
|
-
|
|
105
|
+
/// @notice A page of the bucket's deposit ids: up to `limit` from `offset` (limit 0 = all from `offset`).
|
|
106
|
+
function bucketDepositIds(address verifier, bytes32 constraint, address token, uint256 offset, uint256 limit) external view returns (uint256[] memory);
|
|
100
107
|
function bucketDepositCount(address verifier, bytes32 constraint, address token) external view returns (uint256);
|
|
101
|
-
/// @notice
|
|
102
|
-
///
|
|
103
|
-
/// at most one of their deposits. Funders must make constraints unique, e.g. by salting.
|
|
108
|
+
/// @notice Deposit recorded for a nonzero constraint and funder in this vault. The record persists
|
|
109
|
+
/// after a refund or claim and prevents the same funder from reusing that constraint here.
|
|
104
110
|
function constraintDeposit(bytes32 constraint, address funder) external view returns (bool used, uint256 depositId);
|
|
105
111
|
function bucketTotal(address verifier, bytes32 constraint, address token) external view returns (uint256);
|
|
106
112
|
function trackedTotal(address token) external view returns (uint256);
|
|
107
113
|
function feesOwed(address verifier, address token) external view returns (uint256);
|
|
108
114
|
function feesOwedTotal(address token) external view returns (uint256);
|
|
109
|
-
/// @notice
|
|
115
|
+
/// @notice Total default-bucket amount plus eligible untracked funds, before fees.
|
|
116
|
+
/// Does not apply the sweep page limit or validate default-bucket claimability.
|
|
110
117
|
function sweepable(address verifier, address token) external view returns (uint256);
|
|
111
118
|
function untrackedBalance(address token) external view returns (uint256);
|
|
112
119
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.27;
|
|
3
|
+
|
|
4
|
+
/// @title IP2IDVaultProxy
|
|
5
|
+
/// @notice A P2ID proxy with creation code fixed for its deployed factory. Its upgradeTo entry
|
|
6
|
+
/// point requires an identity proof and a registered target. Delegated implementations
|
|
7
|
+
/// are trusted with all proxy storage, including the implementation slot.
|
|
8
|
+
interface IP2IDVaultProxy {
|
|
9
|
+
/// @notice ERC-1967 upgrade event.
|
|
10
|
+
event Upgraded(address indexed implementation);
|
|
11
|
+
|
|
12
|
+
/// @notice The factory that deployed this proxy and whose registry bounds its implementations.
|
|
13
|
+
function factory() external view returns (address);
|
|
14
|
+
/// @notice The implementation used for delegated calls; proxy-defined selectors take precedence.
|
|
15
|
+
function implementation() external view returns (address);
|
|
16
|
+
/// @notice The wallet and issue time of the proof behind the last upgrade (zero before the first).
|
|
17
|
+
/// Later upgrades need a proof at least this recent; an equal time only for the same wallet.
|
|
18
|
+
/// Delegated code can overwrite this record; upgradeTo ignores a record beyond its future-time bound.
|
|
19
|
+
function lastUpgrade() external view returns (address wallet, uint64 iat);
|
|
20
|
+
/// @notice Move this vault to `newImplementation`, which the factory must have registered.
|
|
21
|
+
/// `proof` is verified through the factory's default verifier for `identityHash` (the
|
|
22
|
+
/// identity this address was derived from); the wallet it resolves to must be the caller,
|
|
23
|
+
/// and its issue time must not exceed block.timestamp + 15 minutes or fall below lastUpgrade.
|
|
24
|
+
/// It must also meet the current implementation's latestProofIat for that verifier and
|
|
25
|
+
/// untrackedProofIat; failed, malformed or excessively future-dated floor reads count as zero.
|
|
26
|
+
/// This call writes the implementation slot and lastUpgrade record, then calls
|
|
27
|
+
/// acceptOwnerProof through the new implementation without verifying the proof again.
|
|
28
|
+
/// Hook failure reverts the entire upgrade. P2IDVault's hook requires the proven wallet
|
|
29
|
+
/// to be the resulting cached owner, rejecting conflicting equal-time wallet proofs.
|
|
30
|
+
/// The proxy requires the hook selector as a canonical 32-byte ABI acknowledgement;
|
|
31
|
+
/// absent, malformed or incorrect acknowledgements revert the entire upgrade.
|
|
32
|
+
/// After the hook, the implementation must still match the target, owner(verifier)
|
|
33
|
+
/// must report the proven wallet, and latestProofIat(verifier) must be at least iat.
|
|
34
|
+
/// Nested upgradeTo calls revert while an upgrade is running.
|
|
35
|
+
/// @dev Getters run through delegated code and cannot establish that an implementation is safe.
|
|
36
|
+
/// This entry point performs no separate initialization or storage-migration call.
|
|
37
|
+
function upgradeTo(bytes32 identityHash, address newImplementation, bytes calldata proof) external;
|
|
38
|
+
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.27;
|
|
3
3
|
|
|
4
4
|
/// @title IP2IDVerifier
|
|
5
|
-
/// @notice
|
|
6
|
-
/// identity resolves to. Optionally also verify a funding constraint.
|
|
5
|
+
/// @notice Resolve an identity proof to a wallet and issue time, with optional constraint evidence.
|
|
7
6
|
interface IP2IDVerifier {
|
|
8
7
|
/// @notice A funding constraint and the evidence that it is satisfied.
|
|
9
8
|
/// @param commitment bytes32(0) = no constraint; otherwise the commitment a deposit was funded with.
|
|
@@ -15,9 +14,7 @@ interface IP2IDVerifier {
|
|
|
15
14
|
bytes signature;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
/// @param identityHash
|
|
19
|
-
/// commitment). Proofs are public once used on-chain, so the caller MUST
|
|
20
|
-
/// pin the identity rather than trust whatever the submitted proof proves.
|
|
17
|
+
/// @param identityHash Expected identity commitment that the implementation must match against the proof.
|
|
21
18
|
/// @param proof Opaque identity proof; the implementation defines the encoding.
|
|
22
19
|
/// @param constraint Skipped when `constraint.commitment == bytes32(0)`.
|
|
23
20
|
/// @return wallet Wallet associated with the proven identity (never address(0)).
|
|
@@ -30,15 +27,14 @@ interface IP2IDVerifier {
|
|
|
30
27
|
Constraint calldata constraint
|
|
31
28
|
) external view returns (address wallet, uint64 iat);
|
|
32
29
|
|
|
33
|
-
/// @notice Whether this verifier
|
|
34
|
-
///
|
|
35
|
-
///
|
|
30
|
+
/// @notice Whether this verifier currently supports nonzero constraints. P2IDVault requires
|
|
31
|
+
/// a successful true response when funding a constrained deposit; this does not establish
|
|
32
|
+
/// that any particular commitment can be satisfied.
|
|
36
33
|
function supportsConstraints() external view returns (bool);
|
|
37
34
|
|
|
38
|
-
/// @notice
|
|
39
|
-
///
|
|
40
|
-
///
|
|
41
|
-
///
|
|
42
|
-
/// nothing this verifier trusts can ever be revoked.
|
|
35
|
+
/// @notice Cache revision. Implementations must increment it when previously accepted identity
|
|
36
|
+
/// proofs may no longer be trusted, or return a constant if trust cannot be revoked.
|
|
37
|
+
/// @dev P2IDVault rejects cached-owner claims when this differs from the stored revision, and
|
|
38
|
+
/// rejects cached-owner claims and proof updates when the revision cannot be read.
|
|
43
39
|
function revision() external view returns (uint64);
|
|
44
40
|
}
|
|
@@ -2,30 +2,57 @@
|
|
|
2
2
|
pragma solidity ^0.8.27;
|
|
3
3
|
|
|
4
4
|
/// @title IP2IdVaultFactory
|
|
5
|
-
/// @notice
|
|
6
|
-
/// identity hash, and points every vault at the current policy and default verifier.
|
|
5
|
+
/// @notice Vault proxy deployment, address derivation, funding and shared configuration views.
|
|
7
6
|
interface IP2IdVaultFactory {
|
|
8
7
|
event VaultDeployed(bytes32 indexed identityHash, address indexed vault);
|
|
8
|
+
event ImplementationProposed(address indexed implementation, uint64 eta);
|
|
9
|
+
event ImplementationProposalCancelled(address indexed implementation);
|
|
10
|
+
event ImplementationRegistered(address indexed implementation);
|
|
11
|
+
event ImplementationDeployed(address indexed implementation, bytes32 creationCodeHash);
|
|
12
|
+
event ImplementationDefaultProposed(address indexed implementation, bool makeDefault, uint64 eta);
|
|
13
|
+
event DefaultImplementationActivated(address indexed implementation);
|
|
14
|
+
event ImplementationRevoked(address indexed implementation);
|
|
9
15
|
|
|
10
16
|
/// @notice P2ID factory interface version implemented by this contract.
|
|
11
17
|
function p2idVersion() external pure returns (string memory);
|
|
12
18
|
|
|
13
|
-
// ----
|
|
14
|
-
/// @notice
|
|
19
|
+
// ---- shared configuration ----
|
|
20
|
+
/// @notice Policy address used for verifier approval, fee quotes and fee distribution.
|
|
15
21
|
function policy() external view returns (address);
|
|
16
22
|
/// @notice Verifier used when a payer does not choose one, and the one bare transfers are claimed through.
|
|
17
23
|
function defaultVerifier() external view returns (address);
|
|
18
24
|
|
|
25
|
+
// ---- vault implementations ----
|
|
26
|
+
/// @notice The implementation every newly deployed vault proxy starts on.
|
|
27
|
+
function baseImplementation() external view returns (address);
|
|
28
|
+
/// @notice Whether the implementation is registered as an upgrade target; other upgrade checks also apply.
|
|
29
|
+
function isRegisteredImplementation(address implementation) external view returns (bool);
|
|
30
|
+
|
|
31
|
+
function initialImplementation() external view returns (address);
|
|
32
|
+
function implementationFor(bytes32 creationCodeHash) external view returns (address);
|
|
33
|
+
/// @notice Deploy full creation code and propose registration; makeDefault applies after the delay.
|
|
34
|
+
function deployVaultImplementation(bytes memory creationCode, bool makeDefault) external returns (address);
|
|
35
|
+
function proposeDefaultImplementation(address implementation) external;
|
|
36
|
+
|
|
37
|
+
// ---- address derivation constants ----
|
|
38
|
+
/// @notice Namespace value supplied to the factory constructor and passed to vault initialization.
|
|
39
|
+
function nsHash() external view returns (bytes32);
|
|
40
|
+
/// @notice Proxy creation-code hash used with this factory's address and an identityHash for CREATE2 derivation.
|
|
41
|
+
function initCodeHash() external pure returns (bytes32);
|
|
42
|
+
/// @notice Refund-window bounds passed to new vaults during initialization.
|
|
43
|
+
function minRefundWindow() external view returns (uint64);
|
|
44
|
+
function maxRefundWindow() external view returns (uint64);
|
|
45
|
+
|
|
19
46
|
// ---- vaults ----
|
|
20
47
|
/// @notice The vault address for `identityHash`, deployed or not:
|
|
21
|
-
/// `keccak256(0xff
|
|
48
|
+
/// Low 160 bits of `keccak256(0xff || factory || identityHash || initCodeHash())`.
|
|
22
49
|
function vaultFor(bytes32 identityHash) external view returns (address);
|
|
23
50
|
function isDeployed(bytes32 identityHash) external view returns (bool);
|
|
24
51
|
/// @notice Deploy the vault for `identityHash`; returns the existing one if already deployed.
|
|
25
52
|
function deploy(bytes32 identityHash) external returns (address vault);
|
|
26
53
|
/// @notice Deploy if needed, then fund under the default verifier on the caller's behalf
|
|
27
|
-
/// (caller
|
|
28
|
-
///
|
|
54
|
+
/// (caller is recorded as funder). ERC-20: approve this factory for the requested amount.
|
|
55
|
+
/// Native coin: token = address(0), send `amount` as msg.value.
|
|
29
56
|
/// @param ref Opaque application reference forwarded to the vault's Funded event; bytes32(0) for none.
|
|
30
57
|
function fund(
|
|
31
58
|
bytes32 identityHash,
|
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
pragma solidity ^0.8.27;
|
|
3
3
|
|
|
4
4
|
/// @title IPviumIdentity
|
|
5
|
-
/// @notice
|
|
6
|
-
///
|
|
7
|
-
/// signed by one of the accepted keys, and binds exactly the values given. The return value is
|
|
8
|
-
/// when Privy issued that token (unix seconds); freshness policy is the caller's.
|
|
5
|
+
/// @notice Attestation verification and signer/version views exposed by PviumIdentity.
|
|
6
|
+
/// verifyIdentity checks the supplied identity type, identity hash and wallet hash.
|
|
9
7
|
interface IPviumIdentity {
|
|
10
8
|
/// @notice Circuit version this deployment verifies. Attestations state theirs; use the matching deployment.
|
|
11
9
|
function circuitVersion() external view returns (uint16);
|
|
12
|
-
/// @notice Whether
|
|
10
|
+
/// @notice Whether this P-256 key belongs to the deployment's current accepted signer set.
|
|
13
11
|
function isSignerKey(uint256 x, uint256 y) external view returns (bool);
|
|
14
12
|
|
|
15
13
|
/// @notice Verify that the proof binds exactly this identity and this wallet.
|
|
16
|
-
/// @dev
|
|
17
|
-
///
|
|
14
|
+
/// @dev The expected identity and wallet are supplied as hashes. The function does not impose
|
|
15
|
+
/// an age limit on the attestation.
|
|
18
16
|
/// @param identityType Identity type id: 0 email, 3 twitter, 5 github, … (see P2IDHash)
|
|
19
17
|
/// @param identityHash P2IDHash.identityHash(identityType, value)
|
|
20
18
|
/// @param walletHash P2IDHash.walletHash(wallet): an address, or a string for a non-EVM wallet
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
pragma solidity ^0.8.27;
|
|
3
3
|
|
|
4
4
|
/// @title P2IDHash
|
|
5
|
-
/// @notice
|
|
5
|
+
/// @notice Identity commitment:
|
|
6
6
|
/// sha256("p2id.identity.v1" || identityType || normalize(value)).
|
|
7
|
-
///
|
|
8
|
-
///
|
|
7
|
+
/// Normalization ASCII-lowercases non-phone, non-wallet values. Wallet values are
|
|
8
|
+
/// lowercased only when they start with lowercase `0x`; other wallet strings are unchanged.
|
|
9
9
|
library P2IDHash {
|
|
10
10
|
bytes internal constant PREFIX = "p2id.identity.v1";
|
|
11
11
|
uint8 internal constant PHONE = 1;
|
|
@@ -27,7 +27,7 @@ library P2IDHash {
|
|
|
27
27
|
return sha256(abi.encodePacked(PREFIX, WALLET, toLowerHex(wallet)));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/// @notice
|
|
30
|
+
/// @notice Wallet-string commitment using type 12, with identityHash's normalization and length checks.
|
|
31
31
|
function walletHash(string memory wallet) internal pure returns (bytes32) {
|
|
32
32
|
return identityHash(WALLET, bytes(wallet));
|
|
33
33
|
}
|
|
@@ -48,7 +48,7 @@ library P2IDHash {
|
|
|
48
48
|
return out;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
/// @dev "0x"
|
|
51
|
+
/// @dev Encode an address as "0x" followed by 40 lowercase hexadecimal characters.
|
|
52
52
|
function toLowerHex(address a) internal pure returns (bytes memory out) {
|
|
53
53
|
bytes16 digits = "0123456789abcdef";
|
|
54
54
|
out = new bytes(42);
|
|
@@ -5,10 +5,10 @@ exports.P2ID_SCHEME = exports.P2ID_SCHEMES = void 0;
|
|
|
5
5
|
exports.P2ID_SCHEMES = {
|
|
6
6
|
"pvium.vault.v1": {
|
|
7
7
|
"identityDomain": "p2id.identity.v1",
|
|
8
|
-
"vaultInitCodeHash": "
|
|
8
|
+
"vaultInitCodeHash": "0x4c76d638c6e156d8a95617576f1dcac6189257696607110346ba4f5fe2932ca6",
|
|
9
9
|
"factories": {
|
|
10
10
|
"production": null,
|
|
11
|
-
"sandbox": "
|
|
11
|
+
"sandbox": "0x5d173035d5Ae0b67a521FbFE72bDe43C96a0080A"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
};
|
|
@@ -18,10 +18,10 @@ export interface P2IDScheme {
|
|
|
18
18
|
export declare const P2ID_SCHEMES: {
|
|
19
19
|
readonly "pvium.vault.v1": {
|
|
20
20
|
readonly identityDomain: "p2id.identity.v1";
|
|
21
|
-
readonly vaultInitCodeHash: "
|
|
21
|
+
readonly vaultInitCodeHash: "0x4c76d638c6e156d8a95617576f1dcac6189257696607110346ba4f5fe2932ca6";
|
|
22
22
|
readonly factories: {
|
|
23
23
|
readonly production: null;
|
|
24
|
-
readonly sandbox: "
|
|
24
|
+
readonly sandbox: "0x5d173035d5Ae0b67a521FbFE72bDe43C96a0080A";
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
27
|
};
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
export const P2ID_SCHEMES = {
|
|
3
3
|
"pvium.vault.v1": {
|
|
4
4
|
"identityDomain": "p2id.identity.v1",
|
|
5
|
-
"vaultInitCodeHash": "
|
|
5
|
+
"vaultInitCodeHash": "0x4c76d638c6e156d8a95617576f1dcac6189257696607110346ba4f5fe2932ca6",
|
|
6
6
|
"factories": {
|
|
7
7
|
"production": null,
|
|
8
|
-
"sandbox": "
|
|
8
|
+
"sandbox": "0x5d173035d5Ae0b67a521FbFE72bDe43C96a0080A"
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pvium/p2id-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "P2ID protocol core: identity types and hashing, chain-agnostic P2ID address derivation, and the Solidity sources",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
|
26
|
-
"url": "git+https://github.com/pvium/
|
|
26
|
+
"url": "git+https://github.com/pvium/p2id.git"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"build": "sh scripts/sync-contracts.sh && node scripts/embed-p2id.mjs && tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json && node scripts/finalize-dist.mjs",
|