@trustvc/eip7702 1.0.0-beta.2 → 1.1.0-beta.2

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 CHANGED
@@ -138,16 +138,54 @@ npx hardhat run scripts/mintDocumentGasless.ts --network sepolia
138
138
 
139
139
  ## Environment variables
140
140
 
141
+ Deploy/registry/paymaster addresses are network-scoped — suffix the variable with `_SEPOLIA` or `_AMOY` (e.g. `FACTORY_ADDRESS_SEPOLIA`, `FACTORY_ADDRESS_AMOY`). `scripts/lib/network.ts` resolves the suffix from `--network <name>` (hardhat scripts) or the `NETWORK` env var (viem/permissionless scripts). See `.env.example` for the full annotated list.
142
+
143
+ ### Wallets & RPC
144
+
141
145
  | Variable | Description |
142
146
  | --- | --- |
143
- | `PRIVATE_KEY` | Deployer wallet private key |
147
+ | `PRIVATE_KEY` | Deployer/gas-payer wallet — pays for deployments, delegation txs, staking |
148
+ | `PRIVATE_KEY2` | Secondary wallet (optional — testing with a second account) |
149
+ | `OWNER_PRIVATE_KEY` | Platform owner / whitelisted user — signs UserOps, needs no ETH for gasless ops |
144
150
  | `SEPOLIA_RPC_URL` | Sepolia RPC endpoint |
151
+ | `AMOY_RPC_URL` | Polygon Amoy RPC endpoint |
145
152
  | `PIMLICO_API_KEY` | Pimlico bundler API key |
146
- | `TDOC_DEPLOYER_ADDRESS` | Deployed TDocDeployer address |
147
- | `PAYMASTER_IMPLEMENTATION` | PlatformPaymaster implementation address |
148
- | `FACTORY_ADDRESS` | PlatformAccountFactory address |
149
- | `PAYMASTER_ADDRESS` | Deployed paymaster clone address |
150
- | `EIP7702_IMPL_ADDRESS` | EIP7702Implementation address |
153
+ | `NETWORK` | `sepolia` \| `amoy` — target network for viem/permissionless scripts (default: `sepolia`) |
154
+ | `ENTRY_POINT` | EntryPoint v0.8 address (default: `0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108`, same on all supported chains) |
155
+
156
+ ### Deployed addresses (network-suffixed)
157
+
158
+ | Variable | Description |
159
+ | --- | --- |
160
+ | `EIP7702_IMPL_ADDRESS_<NETWORK>` | Deployed `EIP7702Implementation` address |
161
+ | `PAYMASTER_IMPLEMENTATION_<NETWORK>` | Deployed `PlatformPaymaster` implementation address |
162
+ | `FACTORY_ADDRESS_<NETWORK>` | Deployed `PlatformAccountFactory` address |
163
+ | `PAYMASTER_ADDRESS_<NETWORK>` | Deployed paymaster clone address |
164
+ | `TDOC_DEPLOYER_ADDRESS_<NETWORK>` | TrustVC `TDocDeployer` address (pre-deployed infra) |
165
+ | `TDOC_IMPLEMENTATION_<NETWORK>` | TDoc implementation to clone via `deployRegistry` |
166
+ | `REGISTRY_ADDRESS_<NETWORK>` | Registry deployed via `deployRegistryGasless.ts` |
167
+ | `TITLE_ESCROW_ADDRESS_<NETWORK>` | Title escrow captured via `mintDocumentGasless.ts` |
168
+
169
+ ### Gasless script inputs
170
+
171
+ | Variable | Description |
172
+ | --- | --- |
173
+ | `TOKEN_NAME` / `TOKEN_SYMBOL` | Name/symbol for the TradeTrust token registry (`deployRegistryGasless.ts`) |
174
+ | `TOKEN_ID` | Document token ID as `uint256` (`mintDocumentGasless.ts`) |
175
+ | `BENEFICIARY_ADDRESS` / `HOLDER_ADDRESS` | Document beneficiary/holder (`mintDocumentGasless.ts`) |
176
+ | `REMARK` | Optional remark bytes/text attached to the document |
177
+ | `NOMINEE_ADDR` / `NEW_HOLDER_ADDR` | Used by the `scripts/trFunctions/*` title-escrow helpers |
178
+
179
+ ### Optional deploy/stake overrides
180
+
181
+ | Variable | Description |
182
+ | --- | --- |
183
+ | `PLATFORM_ADDRESS` | Paymaster owner EOA for `deployPlatformPaymaster.ts` (default: deployer) |
184
+ | `DAILY_LIMIT_ETH` | Per-user daily gas limit in ETH (default: `0` = unlimited) |
185
+ | `DEPLOY_SALT` | Hex `bytes32` CREATE2 salt (default: random) |
186
+ | `STAKE_AMOUNT_ETH` | ETH locked as EntryPoint stake (default: `0.01`) |
187
+ | `DEPOSIT_AMOUNT_ETH` | ETH deposited into the gas pool (default: `0.05`) |
188
+ | `UNSTAKE_DELAY_SEC` | Stake lock period in seconds (default: `86400` = 1 day) |
151
189
 
152
190
  ## Tech stack
153
191
 
@@ -9,7 +9,10 @@ contract PlatformAccountFactory is Ownable {
9
9
  address public tdocDeployer;
10
10
  address public paymasterImplementation;
11
11
 
12
- event PlatformOnboarded(address indexed platformAddress, address indexed paymaster);
12
+ event PlatformOnboarded(
13
+ address indexed platformAddress,
14
+ address indexed paymaster
15
+ );
13
16
  event TdocDeployerUpdated(address indexed newDeployer);
14
17
  event ImplementationUpdated(address indexed newImplementation);
15
18
 
@@ -17,6 +20,8 @@ contract PlatformAccountFactory is Ownable {
17
20
  address _tdocDeployer,
18
21
  address _paymasterImplementation
19
22
  ) Ownable(msg.sender) {
23
+ require(_tdocDeployer != address(0), "Zero address");
24
+ require(_paymasterImplementation != address(0), "Zero address");
20
25
  tdocDeployer = _tdocDeployer;
21
26
  paymasterImplementation = _paymasterImplementation;
22
27
  }
@@ -39,12 +44,23 @@ contract PlatformAccountFactory is Ownable {
39
44
  bytes32 salt
40
45
  ) external returns (address paymaster) {
41
46
  paymaster = Clones.cloneDeterministic(paymasterImplementation, salt);
42
- PlatformPaymaster(payable(paymaster)).initialize(platformAddress, dailyLimit, tdocDeployer);
47
+ PlatformPaymaster(payable(paymaster)).initialize(
48
+ platformAddress,
49
+ dailyLimit,
50
+ tdocDeployer
51
+ );
43
52
  emit PlatformOnboarded(platformAddress, paymaster);
44
53
  }
45
54
 
46
55
  // Address is determined solely by implementation + salt (not by constructor args).
47
- function computePaymasterAddress(bytes32 salt) external view returns (address) {
48
- return Clones.predictDeterministicAddress(paymasterImplementation, salt, address(this));
56
+ function computePaymasterAddress(
57
+ bytes32 salt
58
+ ) external view returns (address) {
59
+ return
60
+ Clones.predictDeterministicAddress(
61
+ paymasterImplementation,
62
+ salt,
63
+ address(this)
64
+ );
49
65
  }
50
66
  }
@@ -49,6 +49,9 @@ contract PlatformPaymaster is BasePaymaster {
49
49
  );
50
50
 
51
51
  bytes32 private constant DEFAULT_ADMIN_ROLE = bytes32(0);
52
+ bytes32 private constant RESTORER_ROLE = keccak256("RESTORER_ROLE");
53
+ bytes32 private constant ACCEPTER_ROLE = keccak256("ACCEPTER_ROLE");
54
+ bytes32 private constant MINTER_ROLE = keccak256("MINTER_ROLE");
52
55
 
53
56
  ITDocDeployer public tdocDeployer;
54
57
 
@@ -141,13 +144,11 @@ contract PlatformPaymaster is BasePaymaster {
141
144
  bytes memory params = abi.encode(name, symbol, address(this));
142
145
  deployed = tdocDeployer.deploy(implementation, params);
143
146
 
144
- // Hand admin to the calling EOA
145
147
  IAccessControl(deployed).grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
148
+ IAccessControl(deployed).grantRole(RESTORER_ROLE, msg.sender);
149
+ IAccessControl(deployed).grantRole(ACCEPTER_ROLE, msg.sender);
150
+ IAccessControl(deployed).grantRole(MINTER_ROLE, msg.sender);
146
151
 
147
- // Paymaster keeps only the operational roles it needs
148
- // (MINTER_ROLE, RESTORER_ROLE, ACCEPTER_ROLE were granted to address(this) via initialize)
149
-
150
- // Relinquish admin — EOA is now sole admin
151
152
  IAccessControl(deployed).renounceRole(
152
153
  DEFAULT_ADMIN_ROLE,
153
154
  address(this)
@@ -169,6 +170,12 @@ contract PlatformPaymaster is BasePaymaster {
169
170
  bytes calldata remark
170
171
  ) external returns (address titleEscrow) {
171
172
  require(authorizedRegistries[registry], "registry not authorized");
173
+ require(
174
+ authorizedCallers[msg.sender] ||
175
+ userWhitelist[msg.sender] > 0 ||
176
+ msg.sender == owner(),
177
+ "caller not authorized"
178
+ );
172
179
 
173
180
  titleEscrow = ITradeTrustToken(registry).mint(
174
181
  beneficiary,
@@ -290,7 +297,18 @@ contract PlatformPaymaster is BasePaymaster {
290
297
  }
291
298
 
292
299
  if (innerSel == MINT_DOCUMENT_SEL) {
293
- // mintDocument: registry enforces MINTER_ROLE — no extra whitelist needed
300
+ if (
301
+ !authorizedCallers[sender] &&
302
+ userWhitelist[sender] == 0 &&
303
+ sender != owner()
304
+ ) {
305
+ emit UserOpRejected(sender, "caller not authorized");
306
+ return ("", _packValidationData(true, 0, 0));
307
+ }
308
+ if (dailyLimit > 0 && dailySpend[sender] + maxCost > dailyLimit) {
309
+ emit UserOpRejected(sender, "daily limit exceeded");
310
+ return ("", _packValidationData(true, 0, 0));
311
+ }
294
312
  return (
295
313
  abi.encode(sender, maxCost, false),
296
314
  _packValidationData(false, 0, 0)
package/dist/index.d.mts CHANGED
@@ -1139,11 +1139,17 @@ declare namespace index$1 {
1139
1139
 
1140
1140
  declare const ChainId: {
1141
1141
  readonly Sepolia: 11155111;
1142
+ readonly Amoy: 80002;
1142
1143
  };
1143
1144
  /** Deployed contract addresses indexed by chainId */
1144
1145
  declare const contractAddress: {
1146
+ readonly PaymasterImplementation: {
1147
+ readonly 11155111: "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f";
1148
+ readonly 80002: "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8";
1149
+ };
1145
1150
  readonly PlatformAccountFactory: {
1146
- readonly 11155111: "0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff";
1151
+ readonly 11155111: "0x1fe801f6af6e9a6c76431db08b121a7de70bc895";
1152
+ readonly 80002: "0x2762abf6fa22314ebcab41dd4666836038d29341";
1147
1153
  };
1148
1154
  };
1149
1155
 
package/dist/index.d.ts CHANGED
@@ -1139,11 +1139,17 @@ declare namespace index$1 {
1139
1139
 
1140
1140
  declare const ChainId: {
1141
1141
  readonly Sepolia: 11155111;
1142
+ readonly Amoy: 80002;
1142
1143
  };
1143
1144
  /** Deployed contract addresses indexed by chainId */
1144
1145
  declare const contractAddress: {
1146
+ readonly PaymasterImplementation: {
1147
+ readonly 11155111: "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f";
1148
+ readonly 80002: "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8";
1149
+ };
1145
1150
  readonly PlatformAccountFactory: {
1146
- readonly 11155111: "0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff";
1151
+ readonly 11155111: "0x1fe801f6af6e9a6c76431db08b121a7de70bc895";
1152
+ readonly 80002: "0x2762abf6fa22314ebcab41dd4666836038d29341";
1147
1153
  };
1148
1154
  };
1149
1155
 
package/dist/index.js CHANGED
@@ -1491,11 +1491,17 @@ __export(constants_exports, {
1491
1491
  contractAddress: () => contractAddress
1492
1492
  });
1493
1493
  var ChainId = {
1494
- Sepolia: 11155111
1494
+ Sepolia: 11155111,
1495
+ Amoy: 80002
1495
1496
  };
1496
1497
  var contractAddress = {
1498
+ PaymasterImplementation: {
1499
+ [ChainId.Sepolia]: "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f",
1500
+ [ChainId.Amoy]: "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8"
1501
+ },
1497
1502
  PlatformAccountFactory: {
1498
- [ChainId.Sepolia]: "0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff"
1503
+ [ChainId.Sepolia]: "0x1fe801f6af6e9a6c76431db08b121a7de70bc895",
1504
+ [ChainId.Amoy]: "0x2762abf6fa22314ebcab41dd4666836038d29341"
1499
1505
  }
1500
1506
  };
1501
1507
 
package/dist/index.mjs CHANGED
@@ -1489,11 +1489,17 @@ __export(constants_exports, {
1489
1489
  contractAddress: () => contractAddress
1490
1490
  });
1491
1491
  var ChainId = {
1492
- Sepolia: 11155111
1492
+ Sepolia: 11155111,
1493
+ Amoy: 80002
1493
1494
  };
1494
1495
  var contractAddress = {
1496
+ PaymasterImplementation: {
1497
+ [ChainId.Sepolia]: "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f",
1498
+ [ChainId.Amoy]: "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8"
1499
+ },
1495
1500
  PlatformAccountFactory: {
1496
- [ChainId.Sepolia]: "0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff"
1501
+ [ChainId.Sepolia]: "0x1fe801f6af6e9a6c76431db08b121a7de70bc895",
1502
+ [ChainId.Amoy]: "0x2762abf6fa22314ebcab41dd4666836038d29341"
1497
1503
  }
1498
1504
  };
1499
1505
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trustvc/eip7702",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.1.0-beta.2",
4
4
  "description": "EIP-7702 smart account, platform paymaster, and factory contracts for TrustVC",
5
5
  "author": "DexTech",
6
6
  "license": "MIT",