-
Notifications
You must be signed in to change notification settings - Fork 0
feat: clone-based paymaster factory with initialize pattern #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
aff13bb
a243980
8beccb4
e3119b3
1336871
9846b7c
e28142a
f11a859
0edc40f
d4e9342
453c0ff
cadbfe6
a81aba0
36e5450
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,9 @@ on: | |
| - main | ||
| - dev | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| env: | ||
| NODE_ENV: ci | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,16 @@ | ||
| export const ChainId = { | ||
| Sepolia: 11155111, | ||
| Amoy: 80002, | ||
| } as const; | ||
|
|
||
| /** Deployed contract addresses indexed by chainId */ | ||
| export const contractAddress = { | ||
| PaymasterImplementation: { | ||
| [ChainId.Sepolia]: "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f", | ||
| [ChainId.Amoy]: "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8", | ||
| }, | ||
| PlatformAccountFactory: { | ||
| [ChainId.Sepolia]: "0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff", | ||
| [ChainId.Sepolia]: "0x1fe801f6af6e9a6c76431db08b121a7de70bc895", | ||
| [ChainId.Amoy]: "0x2762abf6fa22314ebcab41dd4666836038d29341", | ||
| }, | ||
| } as const; | ||
| } as const; | ||
|
Comment on lines
+8
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
: "${SEPOLIA_RPC_URL:?Set SEPOLIA_RPC_URL}"
: "${AMOY_RPC_URL:?Set AMOY_RPC_URL}"
check_code() {
local rpc_url="$1"
local address="$2"
local label="$3"
local result
result="$(curl -fsS "$rpc_url" \
-H 'content-type: application/json' \
--data "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getCode\",\"params\":[\"$address\",\"latest\"]}" \
| jq -r '.result')"
test "$result" != "0x" || {
echo "No bytecode for $label at $address" >&2
exit 1
}
echo "Verified bytecode: $label"
}
check_code "$SEPOLIA_RPC_URL" "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f" "Sepolia PaymasterImplementation"
check_code "$SEPOLIA_RPC_URL" "0x1fe801f6af6e9a6c76431db08b121a7de70bc895" "Sepolia PlatformAccountFactory"
check_code "$AMOY_RPC_URL" "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8" "Amoy PaymasterImplementation"
check_code "$AMOY_RPC_URL" "0x2762abf6fa22314ebcab41dd4666836038d29341" "Amoy PlatformAccountFactory"Repository: TrustVC/7702SmartAccount Length of output: 213 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- relevant repository files ---'
git ls-files | rg '(^|/)(src/constants/index\.ts|package\.json|README|.*artifact.*|.*deployment.*|.*deploy.*|.*factory.*|.*paymaster.*)' | head -200
printf '%s\n' '--- constants file ---'
cat -n src/constants/index.ts
printf '%s\n' '--- public RPC bytecode checks ---'
check_code() {
local rpc_url="$1"
local address="$2"
local label="$3"
local response result
response="$(curl -fsS --max-time 20 "$rpc_url" \
-H 'content-type: application/json' \
--data "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getCode\",\"params\":[\"$address\",\"latest\"]}")"
result="$(printf '%s' "$response" | jq -r '.result // empty')"
if [ -z "$result" ]; then
printf '%s: RPC error: %s\n' "$label" "$response" >&2
return 1
fi
if [ "$result" = "0x" ]; then
printf '%s: no bytecode at %s\n' "$label" "$address"
return 1
fi
printf '%s: bytecode present (%s bytes)\n' "$label" "$(( (${`#result`} - 2) / 2 ))"
}
check_code "https://ethereum-sepolia-rpc.publicnode.com" \
"0x5ca5652025ca77d13323ed4887b4cbee6098dd8f" "Sepolia PaymasterImplementation"
check_code "https://ethereum-sepolia-rpc.publicnode.com" \
"0x1fe801f6af6e9a6c76431db08b121a7de70bc895" "Sepolia PlatformAccountFactory"
check_code "https://polygon-amoy-bor-rpc.publicnode.com" \
"0xf47d58D3adc642DaD23966698A7A60b8b34D72f8" "Amoy PaymasterImplementation"
check_code "https://polygon-amoy-bor-rpc.publicnode.com" \
"0x2762abf6fa22314ebcab41dd4666836038d29341" "Amoy PlatformAccountFactory"Repository: TrustVC/7702SmartAccount Length of output: 1760 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- deployment metadata ---'
cat ignition/deployments/chain-11155111/deployed_addresses.json
printf '%s\n' '--- factory artifact metadata ---'
jq '{contractName, sourceName, bytecodeLength:(.bytecode|length), deployedBytecodeLength:(.deployedBytecode|length), deployedBytecodeHash:(.deployedBytecode|sha256)}' \
ignition/deployments/chain-11155111/artifacts/FactoryModule#PlatformAccountFactory.json
printf '%s\n' '--- contract and deployment references ---'
git ls-files | rg '\.(sol|ts|json)$' | sort | head -300
rg -n 'PaymasterImplementation|PlatformAccountFactory|5ca565|f47d58|1fe801|2762ab|deployedBytecode|bytecode' \
--glob '!package-lock.json' --glob '!yarn.lock' .
printf '%s\n' '--- deployed runtime bytecode hashes from public RPCs ---'
get_code() {
local rpc_url="$1"
local address="$2"
curl -fsS --max-time 20 "$rpc_url" \
-H 'content-type: application/json' \
--data "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getCode\",\"params\":[\"$address\",\"latest\"]}" \
| jq -r '.result'
}
for item in \
"https://ethereum-sepolia-rpc.publicnode.com 0x5ca5652025ca77d13323ed4887b4cbee6098dd8f Sepolia-PaymasterImplementation" \
"https://ethereum-sepolia-rpc.publicnode.com 0x1fe801f6af6e9a6c76431db08b121a7de70bc895 Sepolia-PlatformAccountFactory" \
"https://polygon-amoy-bor-rpc.publicnode.com 0xf47d58D3adc642DaD23966698A7A60b8b34D72f8 Amoy-PaymasterImplementation" \
"https://polygon-amoy-bor-rpc.publicnode.com 0x2762abf6fa22314ebcab41dd4666836038d29341 Amoy-PlatformAccountFactory"
do
set -- $item
code="$(get_code "$1" "$2")"
printf '%s length=%s sha256=' "$3" "${`#code`}"
printf '%s' "$code" | sha256sum | cut -d' ' -f1
doneRepository: TrustVC/7702SmartAccount Length of output: 736 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- factory artifact metadata ---'
jq '{contractName, sourceName, bytecodeLength:(.bytecode|length), deployedBytecodeLength:(.deployedBytecode|length)}' \
'ignition/deployments/chain-11155111/artifacts/FactoryModule#PlatformAccountFactory.json'
printf '%s\n' '--- deployment and address references ---'
rg -n 'PaymasterImplementation|PlatformAccountFactory|5ca565|f47d58|1fe801|2762ab|deployedBytecode|bytecode' \
--glob '!package-lock.json' --glob '!yarn.lock' .
printf '%s\n' '--- deployed runtime bytecode hashes from public RPCs ---'
python3 - <<'PY'
import hashlib
import json
import ssl
import urllib.request
checks = [
("https://ethereum-sepolia-rpc.publicnode.com", "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f", "Sepolia PaymasterImplementation"),
("https://ethereum-sepolia-rpc.publicnode.com", "0x1fe801f6af6e9a6c76431db08b121a7de70bc895", "Sepolia PlatformAccountFactory"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8", "Amoy PaymasterImplementation"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0x2762abf6fa22314ebcab41dd4666836038d29341", "Amoy PlatformAccountFactory"),
]
ctx = ssl.create_default_context()
for rpc, address, label in checks:
body = json.dumps({
"jsonrpc": "2.0",
"id": 1,
"method": "eth_getCode",
"params": [address, "latest"],
}).encode()
request = urllib.request.Request(
rpc, data=body, headers={"content-type": "application/json"}
)
with urllib.request.urlopen(request, timeout=20, context=ctx) as response:
result = json.load(response)["result"]
print(f"{label}: length={len(result)} sha256={hashlib.sha256(result.encode()).hexdigest()}")
PYRepository: TrustVC/7702SmartAccount Length of output: 50381 🏁 Script executed: #!/bin/bash
set -euo pipefail
log=/tmp/coderabbit-shell-logs/shell-output-vXf3te
printf '%s\n' '--- command errors ---'
rg -n -i 'error|failed|exception|timeout|urlopen|traceback|rpc' "$log" | head -100 || true
printf '%s\n' '--- concise artifact metadata ---'
python3 - <<'PY'
import json
from pathlib import Path
path = Path("ignition/deployments/chain-11155111/artifacts/FactoryModule#PlatformAccountFactory.json")
data = json.loads(path.read_text())
for key in ("contractName", "sourceName", "bytecode", "deployedBytecode"):
value = data.get(key)
if isinstance(value, str):
print(f"{key}: length={len(value)}")
else:
print(f"{key}: {value}")
PY
printf '%s\n' '--- deployment/address references excluding uploaded bytecode ---'
rg -n 'PaymasterImplementation|PlatformAccountFactory|5ca565|f47d58|1fe801|2762ab|deployedBytecode|bytecode' \
src scripts ignition README.md package.json 2>/dev/null | head -200 || true
printf '%s\n' '--- deployed runtime bytecode lengths and hashes ---'
python3 - <<'PY'
import hashlib, json, ssl, urllib.request
checks = [
("https://ethereum-sepolia-rpc.publicnode.com", "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f", "Sepolia PaymasterImplementation"),
("https://ethereum-sepolia-rpc.publicnode.com", "0x1fe801f6af6e9a6c76431db08b121a7de70bc895", "Sepolia PlatformAccountFactory"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8", "Amoy PaymasterImplementation"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0x2762abf6fa22314ebcab41dd4666836038d29341", "Amoy PlatformAccountFactory"),
]
for rpc, address, label in checks:
body = json.dumps({"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":[address,"latest"]}).encode()
req = urllib.request.Request(rpc, data=body, headers={"content-type":"application/json"})
try:
with urllib.request.urlopen(req, timeout=20) as response:
result = json.load(response).get("result")
print(f"{label}: length={len(result)} sha256={hashlib.sha256(result.encode()).hexdigest()}")
except Exception as exc:
print(f"{label}: request failed: {exc}")
PYRepository: TrustVC/7702SmartAccount Length of output: 50381 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
import hashlib
import json
import urllib.request
from pathlib import Path
artifact_path = Path("ignition/deployments/chain-11155111/artifacts/FactoryModule#PlatformAccountFactory.json")
artifact = json.loads(artifact_path.read_text())
print("artifact keys:", ",".join(sorted(artifact.keys())))
for key in ("bytecode", "deployedBytecode"):
value = artifact.get(key, "")
print(f"artifact {key}: chars={len(value)} bytes={(len(value)-2)//2 if value.startswith('0x') else 'n/a'} sha256={hashlib.sha256(value.encode()).hexdigest()}")
checks = [
("https://ethereum-sepolia-rpc.publicnode.com", "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f", "Sepolia PaymasterImplementation"),
("https://ethereum-sepolia-rpc.publicnode.com", "0x1fe801f6af6e9a6c76431db08b121a7de70bc895", "Sepolia PlatformAccountFactory"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8", "Amoy PaymasterImplementation"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0x2762abf6fa22314ebcab41dd4666836038d29341", "Amoy PlatformAccountFactory"),
]
for rpc, address, label in checks:
body = json.dumps({"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":[address,"latest"]}).encode()
req = urllib.request.Request(rpc, data=body, headers={"content-type":"application/json"})
with urllib.request.urlopen(req, timeout=20) as response:
result = json.load(response)["result"]
print(f"{label}: chars={len(result)} bytes={(len(result)-2)//2} sha256={hashlib.sha256(result.encode()).hexdigest()}")
if "PlatformAccountFactory" in label:
deployed = artifact.get("deployedBytecode", "")
print(f"{label}: exact_artifact_match={result.lower() == deployed.lower()}")
print(f"{label}: artifact_in_chain_code={deployed.lower().removeprefix('0x') in result.lower()}")
PYRepository: TrustVC/7702SmartAccount Length of output: 2802 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
import hashlib
import json
import subprocess
from pathlib import Path
artifact = json.loads(Path("ignition/deployments/chain-11155111/artifacts/FactoryModule#PlatformAccountFactory.json").read_text())
expected = artifact["deployedBytecode"].lower()
checks = [
("https://ethereum-sepolia-rpc.publicnode.com", "0x5ca5652025ca77d13323ed4887b4cbee6098dd8f", "Sepolia PaymasterImplementation"),
("https://ethereum-sepolia-rpc.publicnode.com", "0x1fe801f6af6e9a6c76431db08b121a7de70bc895", "Sepolia configured PlatformAccountFactory"),
("https://ethereum-sepolia-rpc.publicnode.com", "0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff", "Sepolia deployment-metadata PlatformAccountFactory"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0xf47d58D3adc642DaD23966698A7A60b8b34D72f8", "Amoy PaymasterImplementation"),
("https://polygon-amoy-bor-rpc.publicnode.com", "0x2762abf6fa22314ebcab41dd4666836038d29341", "Amoy configured PlatformAccountFactory"),
]
for rpc, address, label in checks:
payload = json.dumps({
"jsonrpc": "2.0",
"id": 1,
"method": "eth_getCode",
"params": [address, "latest"],
})
raw = subprocess.check_output([
"curl", "-ksS", "--max-time", "20", rpc,
"-H", "content-type: application/json",
"--data", payload,
], text=True)
code = json.loads(raw)["result"].lower()
print(f"{label}: bytes={(len(code)-2)//2} sha256={hashlib.sha256(code.encode()).hexdigest()}")
if "PlatformAccountFactory" in label:
print(f"{label}: exact_artifact_match={code == expected}")
PYRepository: TrustVC/7702SmartAccount Length of output: 994 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- artifact identity and immutable references ---'
python3 - <<'PY'
import json
from pathlib import Path
p = Path("ignition/deployments/chain-11155111/artifacts/FactoryModule#PlatformAccountFactory.json")
a = json.loads(p.read_text())
for key in ("contractName", "sourceName", "linkReferences", "deployedLinkReferences", "immutableReferences"):
print(f"{key}: {a.get(key)}")
for key in ("bytecode", "deployedBytecode"):
v = a[key]
print(f"{key}: prefix={v[:100]} suffix={v[-100:]}")
PY
printf '%s\n' '--- deployment scripts and source references ---'
sed -n '1,220p' scripts/deployFactory.ts
sed -n '1,220p' scripts/deployImplementation.ts
rg -n 'PlatformAccountFactory|PaymasterImplementation|contractAddress|deploy' scripts src README.md \
--glob '*.ts' --glob '*.md' | head -200
printf '%s\n' '--- concise runtime prefixes ---'
python3 - <<'PY'
import json, subprocess
checks = [
("https://ethereum-sepolia-rpc.publicnode.com","0x1fe801f6af6e9a6c76431db08b121a7de70bc895","Sepolia configured factory"),
("https://ethereum-sepolia-rpc.publicnode.com","0x5dcDf7fA6Ab8323F67FD66E89b6CeD4564f9F4Ff","Sepolia metadata factory"),
("https://polygon-amoy-bor-rpc.publicnode.com","0x2762abf6fa22314ebcab41dd4666836038d29341","Amoy configured factory"),
]
for rpc, addr, label in checks:
payload=json.dumps({"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":[addr,"latest"]})
out=subprocess.check_output(["curl","-ksS","--max-time","20",rpc,"-H","content-type: application/json","--data",payload],text=True)
code=json.loads(out)["result"]
print(f"{label}: prefix={code[:100]} suffix={code[-100:]}")
PYRepository: TrustVC/7702SmartAccount Length of output: 18768 Correct the Both configured factory addresses contain bytecode, but their 2,934-byte runtime does not match the repository’s 🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: TrustVC/7702SmartAccount
Length of output: 3736
🏁 Script executed:
Repository: TrustVC/7702SmartAccount
Length of output: 50383
🏁 Script executed:
Repository: TrustVC/7702SmartAccount
Length of output: 50381
🌐 Web query:
EIP-1559 transaction validity max_fee_per_gas max_priority_fee_per_gas priority fee greater than max fee💡 Result:
For EIP-1559 (Type 2) transactions on the Ethereum network, it is a strict validity requirement that the max_fee_per_gas must be greater than or equal to the max_priority_fee_per_gas [1][2][3]. Specifically, the protocol enforces the following validation constraint [1][3]: assert transaction.max_fee_per_gas >= transaction.max_priority_fee_per_gas If a transaction is submitted where max_priority_fee_per_gas exceeds max_fee_per_gas, it is considered invalid and will be rejected by the network [4][5]. The fundamental roles of these parameters are: 1. max_fee_per_gas: The absolute maximum fee per unit of gas the user is willing to pay (covering both the base fee and the priority fee) [1][6]. 2. max_priority_fee_per_gas: The maximum tip the user is willing to pay to the validator [1][6]. Because the total cost to the user is the sum of the protocol-defined base fee and the priority fee (capped by the max_fee_per_gas), the transaction must be structured such that the total maximum budget is at least as large as the priority component [1][7][3]. Additionally, for a transaction to be valid, the max_fee_per_gas must also be greater than or equal to the current block's base fee [1][3]. If the sum of the base fee and the desired priority fee exceeds the max_fee_per_gas, the priority fee is effectively capped at (max_fee_per_gas - base_fee_per_gas) to ensure the transaction remains within the user's specified maximum budget [7][3].
Citations:
🏁 Script executed:
Repository: TrustVC/7702SmartAccount
Length of output: 50381
🌐 Web query:
EIP-1559 validity condition max_fee_per_gas max_priority_fee_per_gas transaction rejected💡 Result:
Under EIP-1559, a transaction is considered invalid and will be rejected by the network if it fails to meet specific fee-related criteria [1][2]. The primary validity conditions concerning gas fees are as follows: 1. Max Fee vs. Base Fee: The transaction's max_fee_per_gas must be greater than or equal to the block's current base_fee_per_gas [1][3]. If max_fee_per_gas is less than the base fee, the transaction is rejected because the sender is not willing to pay the minimum required to include the transaction in the block [1][4]. 2. Max Fee vs. Priority Fee: The transaction's max_fee_per_gas must be greater than or equal to its max_priority_fee_per_gas [1][5][6]. The protocol requires this because the max fee represents the total amount the sender is willing to pay, which must cover both the priority fee (tip) and the base fee [1][4]. 3. Impossibly Large Values: Both max_fee_per_gas and max_priority_fee_per_gas must be less than 2^256 [1][2]. Values that exceed this limit are considered invalid [1][7]. 4. Sufficient Balance: Beyond the fee parameters, the sender's account balance must be sufficient to cover the "upfront cost" of the transaction [2][7]. This is calculated based on the gas_limit multiplied by the max_fee_per_gas, ensuring the sender can afford the transaction regardless of the actual base fee at the time of inclusion [2][5][7]. In practice, if a transaction meets these basic validity requirements, the effective gas price paid is determined by the formula: min(max_priority_fee_per_gas, max_fee_per_gas - base_fee_per_gas) + base_fee_per_gas [1][2]. This ensures that the user never pays more than their specified max_fee_per_gas [8][4].
Citations:
Reject invalid Amoy fee overrides.
When
AMOY_MAX_PRIORITY_FEE_GWEIexceedsAMOY_MAX_FEE_GWEI, the EIP-1559 transaction is invalid. Throw before submitting the deployment transaction.🤖 Prompt for AI Agents