1. Deploy and verify PasskeyAccount
Deploy PasskeyAccountFactory contract
Edit the .env.deployment
file by copying from .env.deployment.example
and then run the following command.
source .env.deployment
PASSKEY_ACCOUNT_FACTORY_ADDRESS=$( forge create --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} --use ${COMPILER_VERSION} " src/account/${ACCOUNT_ABSTRACTION_VERSION} /PasskeyAccountFactory.sol:PasskeyAccountFactory" --constructor-args ${ENTRYPOINT_ADDRESS} ${P256_VERIFIER_ADDRESS} | sed -nr ' s/^Deployed to: (0x[0-9a-zA-Z]{40})[.]*$/\1/p' )
Verify PasskeyAccountFactory contract
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address,address)" ${ENTRYPOINT_ADDRESS} ${P256_VERIFIER_ADDRESS} ) ${PASSKEY_ACCOUNT_FACTORY_ADDRESS} " src/account/${ACCOUNT_ABSTRACTION_VERSION} /PasskeyAccountFactory.sol:PasskeyAccountFactory"
Start verifying contract ` 0x4d21849008fa59F36971A2611746F080b9B79220` deployed on sepolia
Submitting verification for [src/account/PasskeyAccountFactory.sol:PasskeyAccountFactory] 0x4d21849008fa59F36971A2611746F080b9B79220.
Submitted contract for verification:
Response: ` OK`
GUID: ` tqw8mnuhqwuigkkp9vwzgu89qespbkma6umeszbmjlvcjmvj1i`
URL: https://sepolia.etherscan.io/address/0x4d21849008fa59f36971a2611746f080b9b79220
Contract verification status:
Response: ` OK`
Details: ` Pass - Verified`
Contract successfully verified
Verify PasskeyAccount implementation contract
PASSKEY_ACCOUNT_IMPLEMENTATION_ADDRESS=$( cast call --rpc-url ${NODE_RPC_URL} ${PASSKEY_ACCOUNT_FACTORY_ADDRESS} " accountImplementation()" | sed -r ' s/^[.]*(0x)([0]{24})?([0-9a-zA-Z]{40})[.]*$/\1\3/g' )
P256_VERIFIER_ADDRESS=$( cast call --rpc-url ${NODE_RPC_URL} ${PASSKEY_ACCOUNT_FACTORY_ADDRESS} " p256Verifier()" | sed -r ' s/^[.]*(0x)([0]{24})?([0-9a-zA-Z]{40})[.]*$/\1\3/g' )
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address,address)" ${ENTRYPOINT_ADDRESS} ${P256_VERIFIER_ADDRESS} ) ${PASSKEY_ACCOUNT_IMPLEMENTATION_ADDRESS} " src/account/${ACCOUNT_ABSTRACTION_VERSION} /PasskeyAccount.sol:PasskeyAccount"
Deploy PasskeyAccount contract via PasskeyAccountFactory
cast send --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} ${PASSKEY_ACCOUNT_FACTORY_ADDRESS} " createAccount(string calldata credId,uint256 pubKeyX,uint256 pubKeyY,uint256 salt)" ${PASSKEY_CREDENTIAL_ID} ${PASSKEY_X} ${PASSKEY_Y} ${SALT}
Verify PasskeyAccount contract
PASSKEY_ACCOUNT_ADDRESS=$( cast call --rpc-url ${NODE_RPC_URL} ${PASSKEY_ACCOUNT_FACTORY_ADDRESS} " getAddress(string calldata credId,uint256 pubKeyX,uint256 pubKeyY,uint256 salt)" ${PASSKEY_CREDENTIAL_ID} ${PASSKEY_X} ${PASSKEY_Y} ${SALT} | sed -r ' s/^[.]*(0x)([0]{24})?([0-9a-zA-Z]{40})[.]*$/\1\3/g' )
echo " Verification contract: ${PASSKEY_ACCOUNT_ADDRESS} " && echo " Implementation contract: ${PASSKEY_ACCOUNT_IMPLEMENTATION_ADDRESS} "
Verification contract: 0x5c5d3afdaafdfb4ad974a28eda9bbf4c91c043a6
Implementation contract: 0xb22adc80082e3ad52b64138f5677c9f5f46dad1c
Click Is this a proxy?
and Verify
. Ensure the displayed implementation contract matches the sample output. Click Save
to complete PasskeyAccount verification.
If necessary, you can also verify PasskeyAccount (ERC1967Proxy) contract.
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address,bytes)" ${PASSKEY_ACCOUNT_IMPLEMENTATION_ADDRESS} $( cast calldata " initialize(string,uint256,uint256)" ${PASSKEY_CREDENTIAL_ID} ${PASSKEY_X} ${PASSKEY_Y} ) ) ${PASSKEY_ACCOUNT_ADDRESS} " lib/openzeppelin-contracts/${OPENZEPPELIN_CONTRACTS_VERSION} /contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy"
2. Deploy and verify SimpleAccount
Deploy SimpleAccountFactory contract
Edit the .env.deployment
file by copying from .env.deployment.example
and then run the following command.
source .env.deployment
SIMPLE_ACCOUNT_FACTORY_ADDRESS=$( forge create --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} --use ${COMPILER_VERSION} " lib/account-abstraction/${ACCOUNT_ABSTRACTION_VERSION} /contracts/samples/SimpleAccountFactory.sol:SimpleAccountFactory" --constructor-args ${ENTRYPOINT_ADDRESS} | sed -nr ' s/^Deployed to: (0x[0-9a-zA-Z]{40})[.]*$/\1/p' )
Verify SimpleAccountFactory contract
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address)" ${ENTRYPOINT_ADDRESS} ) ${SIMPLE_ACCOUNT_FACTORY_ADDRESS} " lib/account-abstraction/${ACCOUNT_ABSTRACTION_VERSION} /contracts/samples/SimpleAccountFactory.sol:SimpleAccountFactory"
Verify SimpleAccount implementation contract
SIMPLE_ACCOUNT_IMPLEMENTATION_ADDRESS=$( cast call --rpc-url ${NODE_RPC_URL} ${SIMPLE_ACCOUNT_FACTORY_ADDRESS} " accountImplementation()" | sed -r ' s/^[.]*(0x)([0]{24})?([0-9a-zA-Z]{40})[.]*$/\1\3/g' )
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address)" ${ENTRYPOINT_ADDRESS} ) ${SIMPLE_ACCOUNT_IMPLEMENTATION_ADDRESS} " lib/account-abstraction/${ACCOUNT_ABSTRACTION_VERSION} /contracts/samples/SimpleAccount.sol:SimpleAccount"
Deploy SimpleAccount contract via SimpleAccountFactory
cast send --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} ${SIMPLE_ACCOUNT_FACTORY_ADDRESS} " createAccount(address owner,uint256 salt)" ${SIMPLE_ACCOUNT_OWNER_ADDRESS} ${SALT}
Verify SimpleAccount contract
SIMPLE_ACCOUNT_ADDRESS=$( cast call --rpc-url ${NODE_RPC_URL} ${SIMPLE_ACCOUNT_FACTORY_ADDRESS} " getAddress(address owner,uint256 salt)" ${SIMPLE_ACCOUNT_OWNER_ADDRESS} ${SALT} | sed -r ' s/^[.]*(0x)([0]{24})?([0-9a-zA-Z]{40})[.]*$/\1\3/g' )
echo " Verification contract: ${SIMPLE_ACCOUNT_ADDRESS} " && echo " Implementation contract: ${SIMPLE_ACCOUNT_IMPLEMENTATION_ADDRESS} "
Copy the displayed verification contract address and visit the contract page on Etherscan.
Click Is this a proxy?
and Verify
. Ensure the displayed implementation contract matches the sample output. Click Save
to complete SimpleAccount verification.
If necessary, you can also verify SimpleAccount (ERC1967Proxy) contract.
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address,bytes)" ${SIMPLE_ACCOUNT_IMPLEMENTATION_ADDRESS} $( cast calldata " initialize(address)" ${SIMPLE_ACCOUNT_OWNER_ADDRESS} ) ) ${SIMPLE_ACCOUNT_ADDRESS} " lib/openzeppelin-contracts/${OPENZEPPELIN_CONTRACTS_VERSION} /contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy"
3. Deploy and verify VerifyingPaymaster
Deploy VerifyingPaymaster contract
Edit the .env.deployment
file by copying from .env.deployment.example
and then run the following command.
source .env.deployment
VERIFYING_PAYMASTER_ADDRESS=$( forge create --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} --use ${COMPILER_VERSION} " lib/account-abstraction/${ACCOUNT_ABSTRACTION_VERSION} /contracts/samples/VerifyingPaymaster.sol:VerifyingPaymaster" --constructor-args ${ENTRYPOINT_ADDRESS} ${VERIFYING_PAYMASTER_OWNER_ADDRESS} | sed -nr ' s/^Deployed to: (0x[0-9a-zA-Z]{40})[.]*$/\1/p' )
Verify VerifyingPaymaster contract
forge verify-contract --watch --chain ${CHAIN_ID} --verifier " etherscan" --etherscan-api-key ${ETHERSCAN_API_KEY} --compiler-version ${COMPILER_VERSION} --constructor-args $( cast abi-encode " constructor(address,address)" ${ENTRYPOINT_ADDRESS} ${VERIFYING_PAYMASTER_OWNER_ADDRESS} ) ${VERIFYING_PAYMASTER_ADDRESS} " lib/account-abstraction/${ACCOUNT_ABSTRACTION_VERSION} /contracts/samples/VerifyingPaymaster.sol:VerifyingPaymaster"
Deposit to EntryPoint and stake to Bundler for VerifyingPaymaster
VALUE=0.3ether
# Deposit for VerifyingPaymaster
cast send --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} ${ENTRYPOINT_ADDRESS} --value ${VALUE} " depositTo(address account)" ${VERIFYING_PAYMASTER_ADDRESS}
# Check VerifyingPaymaster deposit amount.
cast from-wei $( cast to-dec $( cast call --rpc-url ${NODE_RPC_URL} ${ENTRYPOINT_ADDRESS} " balanceOf(address account)" ${VERIFYING_PAYMASTER_ADDRESS} ) )
# Stake for VerifyingPaymaster
cast send --rpc-url ${NODE_RPC_URL} --private-key ${DEPLOYER_PRIVATE_KEY} ${VERIFYING_PAYMASTER_ADDRESS} --value ${VALUE} " addStake(uint32 unstakeDelaySec)" 86401