Skip to content

Commit aa6a6a8

Browse files
authored
Merge branch 'main' into 4337-guardian
2 parents 8bdc87a + c0fd7da commit aa6a6a8

File tree

28 files changed

+1544
-679
lines changed

28 files changed

+1544
-679
lines changed

cspell-config/cspell-packages.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
hexlify
33
viem
44
wagmi
5+
siwe
56
cbor
67
levischuck
78
ofetch

examples/demo-app/scripts/deploy-msa-anvil.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ fi
7474

7575
echo ""
7676
echo "✅ Deployment complete!"
77+
echo " MockPaymaster: $PAYMASTER"
7778
echo " EOAKeyValidator: $EOA_VALIDATOR"
7879
echo " SessionKeyValidator: $SESSION_VALIDATOR"
7980
echo " WebAuthnValidator: $WEBAUTHN_VALIDATOR"
8081
echo " GuardianExecutor: $GUARDIAN_EXECUTOR"
8182
echo " ModularSmartAccount impl: $ACCOUNT_IMPL"
8283
echo " UpgradeableBeacon: $BEACON"
8384
echo " MSAFactory: $FACTORY"
84-
echo " MockPaymaster: $PAYMASTER"
8585

8686
# Create contracts-anvil.json
8787
echo ""

packages/auth-server-api/.env.example

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ DEPLOYER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf
1010

1111
# Blockchain Configuration
1212
RPC_URL=http://127.0.0.1:8545
13-
BUNDLER_URL=http://127.0.0.1:4337
13+
14+
# Rate Limiting Configuration
15+
RATE_LIMIT_DEPLOY_MAX=20
16+
RATE_LIMIT_DEPLOY_WINDOW_MS=3600000 # 1 hour
1417

1518
# Contract Addresses (OPTIONAL - will fall back to src/contracts.json if not provided)
1619
# You can provide these via environment variables OR update src/contracts.json
@@ -19,3 +22,12 @@ BUNDLER_URL=http://127.0.0.1:4337
1922
# EOA_VALIDATOR_ADDRESS=0x...
2023
# WEBAUTHN_VALIDATOR_ADDRESS=0x...
2124
# SESSION_VALIDATOR_ADDRESS=0x...
25+
26+
# Prividium Mode Configuration (OPTIONAL)
27+
# When enabled, requires user authentication via Prividium and routes deployments through Prividium RPC proxy
28+
# PRIVIDIUM_MODE=true
29+
# PRIVIDIUM_RPC_PROXY_BASE_URL=https://rpc.prividium.io
30+
# PRIVIDIUM_PERMISSIONS_BASE_URL=https://permissions.prividium.io
31+
# PRIVIDIUM_ADMIN_PRIVATE_KEY=0x... # Private key of a user with 'admin' role in Prividium
32+
# PRIVIDIUM_TEMPLATE_KEY=sso-smart-account # Template key for whitelisting deployed contracts
33+
# SSO_AUTH_SERVER_BASE_URL=https://sso.example.com # Base URL of the SSO auth server frontend (used as SIWE domain for admin authorization)

packages/auth-server-api/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,46 @@ API responsible for deploying SSO smart accounts.
77
- `POST /api/deploy-account` - Deploy a new smart account with passkey
88
authentication
99
- `GET /api/health` - Health check endpoint
10+
11+
## Prividium Mode Setup
12+
13+
When Prividium mode is enabled, the auth server requires user authentication via
14+
Prividium and routes all deployments through the Prividium RPC proxy.
15+
16+
### Configuration
17+
18+
Set the following environment variables to enable Prividium mode:
19+
20+
```env
21+
PRIVIDIUM_MODE=true
22+
PRIVIDIUM_RPC_PROXY_BASE_URL=https://rpc.prividium.io
23+
PRIVIDIUM_PERMISSIONS_BASE_URL=https://permissions.prividium.io
24+
PRIVIDIUM_ADMIN_PRIVATE_KEY=0x... # Private key of a user with 'admin' role in Prividium
25+
PRIVIDIUM_TEMPLATE_KEY=sso-smart-account # Template key for whitelisting deployed contracts
26+
SSO_AUTH_SERVER_BASE_URL=https://sso.example.com # Base URL of the SSO auth server frontend (used as SIWE domain for admin authorization)
27+
```
28+
29+
### Prividium Admin Panel Setup
30+
31+
1. Create a **Contract Permission Template** in the Prividium admin panel with
32+
the key `sso-smart-account` (or the value you set for
33+
`PRIVIDIUM_TEMPLATE_KEY`)
34+
2. Configure the template with the required permissions listed below
35+
36+
### Contract ABI
37+
38+
The SSO smart account contract ABI is available at:
39+
[`packages/erc4337-contracts/out/ModularSmartAccount.sol/ModularSmartAccount.json`](../erc4337-contracts/out/ModularSmartAccount.sol/ModularSmartAccount.json)
40+
after compiling the contracts.
41+
42+
### Required Permissions
43+
44+
Configure the following method permissions in your contract template:
45+
46+
| Function | Permission Level | Access Details |
47+
| ----------------- | ---------------- | -------------- |
48+
| `ENTRY_POINT_V08` | All Users | |
49+
| `accountId` | All Users | |
50+
| `domainSeparator` | All Users | |
51+
| `eip712Domain` | All Users | |
52+
| `entryPoint` | All Users | |

packages/auth-server-api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"cors": "^2.8.5",
1515
"dotenv": "^16.4.7",
1616
"express": "^4.21.2",
17+
"express-rate-limit": "^7.5.0",
1718
"viem": "2.30.0",
1819
"zksync-sso-4337": "workspace:*",
1920
"zod": "^3.24.1"

packages/auth-server-api/src/app.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import cors from "cors";
22
import express, { type NextFunction, type Request, type Response } from "express";
33

4-
import { env } from "./config.js";
4+
import { env, prividiumConfig } from "./config.js";
55
import { deployAccountHandler } from "./handlers/deploy-account.js";
6+
import { prividiumAuthMiddleware } from "./middleware/prividium-auth.js";
7+
import { deployLimiter } from "./middleware/rate-limit.js";
68

79
// Initialize Express app
810
const app = express();
@@ -33,8 +35,8 @@ app.get("/api/health", (_req: Request, res: Response) => {
3335
res.json({ status: "ok", timestamp: new Date().toISOString() });
3436
});
3537

36-
// Deploy account endpoint
37-
app.post("/api/deploy-account", deployAccountHandler);
38+
// Deploy account endpoint (rate limiting first, then auth, then handler)
39+
app.post("/api/deploy-account", deployLimiter, prividiumAuthMiddleware(prividiumConfig), deployAccountHandler);
3840

3941
// Global error handler
4042
// eslint-disable-next-line @typescript-eslint/no-unused-vars

packages/auth-server-api/src/config.ts

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,21 @@ const envSchema = z.object({
3535
CORS_ORIGINS: z.string().default("http://localhost:3002,http://localhost:3003,http://localhost:3004,http://localhost:3005,http://localhost:3000"),
3636
DEPLOYER_PRIVATE_KEY: z.string().default("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"),
3737
RPC_URL: z.string().default("http://127.0.0.1:8545"),
38-
BUNDLER_URL: z.string().default("http://127.0.0.1:4337"),
3938
FACTORY_ADDRESS: z.string().optional(),
4039
EOA_VALIDATOR_ADDRESS: z.string().optional(),
4140
WEBAUTHN_VALIDATOR_ADDRESS: z.string().optional(),
4241
SESSION_VALIDATOR_ADDRESS: z.string().optional(),
4342
GUARDIAN_EXECUTOR_ADDRESS: z.string().optional(),
43+
// Prividium Mode Configuration
44+
PRIVIDIUM_MODE: z.string().transform((v) => v === "true").default("false"),
45+
PRIVIDIUM_PERMISSIONS_BASE_URL: z.string().optional(),
46+
PRIVIDIUM_RPC_PROXY_BASE_URL: z.string().optional(),
47+
PRIVIDIUM_ADMIN_PRIVATE_KEY: z.string().optional(),
48+
PRIVIDIUM_TEMPLATE_KEY: z.string().optional(),
49+
SSO_AUTH_SERVER_BASE_URL: z.string().optional(),
50+
// Rate Limiting Configuration
51+
RATE_LIMIT_DEPLOY_MAX: z.string().default("20"),
52+
RATE_LIMIT_DEPLOY_WINDOW_MS: z.string().default("3600000"), // 1 hour
4453
});
4554

4655
// Parse and validate environment variables
@@ -52,6 +61,21 @@ try {
5261
process.exit(1);
5362
}
5463

64+
// Validate Prividium configuration when enabled
65+
if (env.PRIVIDIUM_MODE) {
66+
const missingPrividiumVars: string[] = [];
67+
if (!env.PRIVIDIUM_PERMISSIONS_BASE_URL) missingPrividiumVars.push("PRIVIDIUM_PERMISSIONS_BASE_URL");
68+
if (!env.PRIVIDIUM_RPC_PROXY_BASE_URL) missingPrividiumVars.push("PRIVIDIUM_RPC_PROXY_BASE_URL");
69+
if (!env.PRIVIDIUM_ADMIN_PRIVATE_KEY) missingPrividiumVars.push("PRIVIDIUM_ADMIN_PRIVATE_KEY");
70+
if (!env.PRIVIDIUM_TEMPLATE_KEY) missingPrividiumVars.push("PRIVIDIUM_TEMPLATE_KEY");
71+
if (!env.SSO_AUTH_SERVER_BASE_URL) missingPrividiumVars.push("SSO_AUTH_SERVER_BASE_URL");
72+
73+
if (missingPrividiumVars.length > 0) {
74+
console.error("PRIVIDIUM_MODE is enabled but missing required configuration:", missingPrividiumVars.join(", "));
75+
process.exit(1);
76+
}
77+
}
78+
5579
// Use env vars if provided, otherwise fall back to contracts.json
5680
const FACTORY_ADDRESS = env.FACTORY_ADDRESS || contractsFromFile.factory;
5781
const EOA_VALIDATOR_ADDRESS = env.EOA_VALIDATOR_ADDRESS || contractsFromFile.eoaValidator;
@@ -92,7 +116,21 @@ const zksyncOsTestnet = defineChain({
92116
},
93117
},
94118
});
95-
const SUPPORTED_CHAINS: Chain[] = [localhost, zksyncOsTestnet];
119+
const zksyncOsLocal = defineChain({
120+
id: 6565,
121+
name: "ZKsyncOS Local",
122+
nativeCurrency: {
123+
name: "Ether",
124+
symbol: "ETH",
125+
decimals: 18,
126+
},
127+
rpcUrls: {
128+
default: {
129+
http: ["http://localhost:5050"],
130+
},
131+
},
132+
});
133+
const SUPPORTED_CHAINS: Chain[] = [localhost, zksyncOsTestnet, zksyncOsLocal];
96134

97135
function getChain(chainId: number): Chain {
98136
const chain = SUPPORTED_CHAINS.find((c) => c.id === chainId);
@@ -102,4 +140,29 @@ function getChain(chainId: number): Chain {
102140
return chain;
103141
}
104142

105-
export { env, EOA_VALIDATOR_ADDRESS, FACTORY_ADDRESS, getChain, GUARDIAN_EXECUTOR_ADDRESS, SESSION_VALIDATOR_ADDRESS, SUPPORTED_CHAINS, WEBAUTHN_VALIDATOR_ADDRESS };
143+
// Prividium configuration object for services
144+
export interface PrividiumConfig {
145+
enabled: boolean;
146+
permissionsApiUrl: string;
147+
proxyUrl: string;
148+
adminPrivateKey: string;
149+
templateKey: string;
150+
ssoAuthServerBaseUrl: string;
151+
}
152+
153+
const prividiumConfig: PrividiumConfig = {
154+
enabled: env.PRIVIDIUM_MODE,
155+
permissionsApiUrl: env.PRIVIDIUM_PERMISSIONS_BASE_URL || "",
156+
proxyUrl: env.PRIVIDIUM_RPC_PROXY_BASE_URL ? `${env.PRIVIDIUM_RPC_PROXY_BASE_URL}/rpc` : "",
157+
adminPrivateKey: env.PRIVIDIUM_ADMIN_PRIVATE_KEY || "",
158+
templateKey: env.PRIVIDIUM_TEMPLATE_KEY || "",
159+
ssoAuthServerBaseUrl: env.SSO_AUTH_SERVER_BASE_URL || "",
160+
};
161+
162+
// Rate limiting configuration
163+
const rateLimitConfig = {
164+
deployMax: parseInt(env.RATE_LIMIT_DEPLOY_MAX, 10),
165+
deployWindowMs: parseInt(env.RATE_LIMIT_DEPLOY_WINDOW_MS, 10),
166+
};
167+
168+
export { env, EOA_VALIDATOR_ADDRESS, FACTORY_ADDRESS, getChain, GUARDIAN_EXECUTOR_ADDRESS, prividiumConfig, rateLimitConfig, SESSION_VALIDATOR_ADDRESS, SUPPORTED_CHAINS, WEBAUTHN_VALIDATOR_ADDRESS };

0 commit comments

Comments
 (0)