From 62002e32d71535f3dc784949b909c9f5119d8118 Mon Sep 17 00:00:00 2001 From: lienhage Date: Fri, 22 Sep 2023 16:05:16 +0800 Subject: [PATCH] add stake logic for versa factory --- contracts/VersaAccountFactory.sol | 21 ++++++++++++++-- deploy/deployAll.ts | 40 ++++++++++++++++++++++++------- deploy/helper/config.ts | 1 + deploy/helper/deployer.ts | 9 ++++++- deploy/helper/verifier.ts | 19 +++++++++------ deploy/versaAccountFactory.ts | 2 ++ deploy/versaSingleton.ts | 2 +- test/VersaFactory.test.ts | 4 +++- test/VersaWallet.test.ts | 4 +++- test/utils.ts | 4 +++- 10 files changed, 84 insertions(+), 22 deletions(-) diff --git a/contracts/VersaAccountFactory.sol b/contracts/VersaAccountFactory.sol index 60eaf2b..1b7f2af 100644 --- a/contracts/VersaAccountFactory.sol +++ b/contracts/VersaAccountFactory.sol @@ -2,19 +2,24 @@ pragma solidity ^0.8.19; import "@openzeppelin/contracts/utils/Create2.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; import "@safe-contracts/contracts/proxies/SafeProxyFactory.sol"; +import "@aa-template/contracts/interfaces/IEntryPoint.sol"; import "./VersaWallet.sol"; /** * A wrapper factory contract to deploy Versa account proxy. */ -contract VersaAccountFactory is SafeProxyFactory { +contract VersaAccountFactory is SafeProxyFactory, Ownable { address public immutable versaSingleton; address public immutable defaultFallbackHandler; + IEntryPoint public immutable entryPoint; - constructor(address _versaSingleton, address _fallbackHandler) { + constructor(address _versaSingleton, address _fallbackHandler, address _entryPoint, address _owner) { versaSingleton = _versaSingleton; defaultFallbackHandler = _fallbackHandler; + entryPoint = IEntryPoint(_entryPoint); + transferOwnership(_owner); } function createAccount( @@ -110,4 +115,16 @@ contract VersaAccountFactory is SafeProxyFactory { bytes memory deploymentData = abi.encodePacked(proxyCreationCode(), uint256(uint160(versaSingleton))); return Create2.computeAddress(bytes32(salt2), keccak256(deploymentData), address(this)); } + + function addStake(uint32 unstakeDelaySec) external payable onlyOwner { + entryPoint.addStake{ value: msg.value }(unstakeDelaySec); + } + + function unlockStake() external onlyOwner { + entryPoint.unlockStake(); + } + + function withdrawStake(address payable withdrawAddress) external onlyOwner { + entryPoint.withdrawStake(withdrawAddress); + } } diff --git a/deploy/deployAll.ts b/deploy/deployAll.ts index b5e302c..6251037 100644 --- a/deploy/deployAll.ts +++ b/deploy/deployAll.ts @@ -6,25 +6,41 @@ import scrollSepoliaAddresses from "./addresses/scrollSepolia.json"; import fs from "fs"; import { deployConfig } from "./helper/config"; import * as readline from "readline-sync"; +import { parseEther } from "ethers/lib/utils"; async function deployWithAddresses(addresses: any, config: any) { const deployCompatibilityFallbackHandler = readline.keyInYN("Do you need to deploy compatibilityFallbackHandler?"); if (deployCompatibilityFallbackHandler) { const compatibilityFallbackHandler = await deployer.deployCompatibilityFallbackHandler(config.salt); - addresses.compatibilityFallbackHandler = compatibilityFallbackHandler.address; + if (compatibilityFallbackHandler.address != ethers.constants.AddressZero) { + addresses.compatibilityFallbackHandler = compatibilityFallbackHandler.address; + } } const deployVersaSingleton = readline.keyInYN("Do you need to deploy versa singleton and versa factory?"); if (deployVersaSingleton) { const versaSingleton = await deployer.deployVersaSingleton(config.entryPointAddress, config.salt); - addresses.versaSingleton = versaSingleton.address; + if (versaSingleton.address != ethers.constants.AddressZero) { + addresses.versaSingleton = versaSingleton.address; + } const versaAccountFactoryData: VersaAccountFactoryData = { versaSingleton: addresses.versaSingleton, defaultFallbackHandler: addresses.compatibilityFallbackHandler, + entryPoint: deployConfig.entryPointAddress, + owner: deployConfig.versaFactoryOwner, }; const versaFactory = await deployer.deployVersaAccountFactory(versaAccountFactoryData, config.salt); - addresses.versaAccountFactory = versaFactory.address; + if (versaFactory.address != ethers.constants.AddressZero) { + addresses.versaAccountFactory = versaFactory.address; + } + const stakeAmount = readline.question("Please enter stake amount(in 1e18): "); + const unstakeDelaySec = readline.question("Please enter the unstake delay(in seconds): "); + if (parseEther(stakeAmount.toString()).gt(0)) { + let tx = await versaFactory.addStake(unstakeDelaySec, { value: parseEther(stakeAmount.toString()) }); + await tx.wait(); + console.log("Staked success!"); + } } const deployPaymaster = readline.keyInYN("Do you need to deploy paymaster?"); @@ -34,16 +50,24 @@ async function deployWithAddresses(addresses: any, config: any) { const deloyPlugins = readline.keyInYN("Do you need to deploy plugins?"); if (deloyPlugins) { const ecdsaValidator = await deployer.deployECDSAValidator(config.salt); - addresses.ecdsaValidator = ecdsaValidator.address; + if (ecdsaValidator.address != ethers.constants.AddressZero) { + addresses.ecdsaValidator = ecdsaValidator.address; + } const multisigValidator = await deployer.deployMultiSigValidator(config.salt); - addresses.multisigValidator = multisigValidator.address; + if (multisigValidator.address != ethers.constants.AddressZero) { + addresses.multisigValidator = multisigValidator.address; + } - const sessionKeyValdiator = await deployer.deploySessionKeyValidator(config.salt); - addresses.sessionKeyValdiator = sessionKeyValdiator.address; + const sessionKeyValidator = await deployer.deploySessionKeyValidator(config.salt); + if (sessionKeyValidator.address != ethers.constants.AddressZero) { + addresses.sessionKeyValidator = sessionKeyValidator.address; + } const spendingLimitHooks = await deployer.deploySpendingLimitHooks(config.salt); - addresses.spendingLimitHooks = spendingLimitHooks.address; + if (spendingLimitHooks.address != ethers.constants.AddressZero) { + addresses.spendingLimitHooks = spendingLimitHooks.address; + } } return addresses; } diff --git a/deploy/helper/config.ts b/deploy/helper/config.ts index 04a81fe..7a8aea3 100644 --- a/deploy/helper/config.ts +++ b/deploy/helper/config.ts @@ -6,4 +6,5 @@ export const deployConfig = { entryPointAddress: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", salt: keccak256("0x" + Buffer.from("versa-wallet-v1.0.0-test").toString("hex")), verifyingPaymasterOwner: "0x43370254AAAce51006cf368eb7734DB43Ddf9880", + versaFactoryOwner: "0x7C563F9423C93Fed57c6aC2cC562b0DE0956abB0", }; diff --git a/deploy/helper/deployer.ts b/deploy/helper/deployer.ts index 7c1539f..356ce25 100644 --- a/deploy/helper/deployer.ts +++ b/deploy/helper/deployer.ts @@ -4,6 +4,8 @@ import { universalSingletonFactoryAddress as singletonFactoryAddress } from "./c export interface VersaAccountFactoryData { versaSingleton: string; defaultFallbackHandler: string; + entryPoint: string; + owner: string; } const singletonFactoryABI = ["function deploy(bytes _initCode,bytes32 _salt) returns (address createdContract)"]; @@ -15,7 +17,12 @@ async function getSingletonFactory() { export async function deployVersaAccountFactory(data: VersaAccountFactoryData, salt: string) { const singletonFactory = await getSingletonFactory(); const VersaAccountFactory = await ethers.getContractFactory("VersaAccountFactory"); - const initCode = VersaAccountFactory.getDeployTransaction(data.versaSingleton, data.defaultFallbackHandler).data!; + const initCode = VersaAccountFactory.getDeployTransaction( + data.versaSingleton, + data.defaultFallbackHandler, + data.entryPoint, + data.owner + ).data!; const address = await singletonFactory.callStatic.deploy(initCode, salt); let tx; diff --git a/deploy/helper/verifier.ts b/deploy/helper/verifier.ts index 19dce74..afbd773 100644 --- a/deploy/helper/verifier.ts +++ b/deploy/helper/verifier.ts @@ -1,6 +1,7 @@ -import hre from "hardhat"; +import hre, { ethers } from "hardhat"; import mumbaiAddresses from "../addresses/polygonMumbai.json"; import scrollSepoliaAddresses from "../addresses/scrollSepolia.json"; +import { deployConfig } from "./config"; async function verify(address: string, constructorArguments?: any) { await hre.run("verify:verify", { @@ -15,14 +16,16 @@ async function main() { switch (network?.chainId) { case 80001: { - await verify(mumbaiAddresses.versaSingleton, [mumbaiAddresses.entryPoint]); + await verify(mumbaiAddresses.versaSingleton, [deployConfig.entryPointAddress]); await verify(mumbaiAddresses.versaAccountFactory, [ mumbaiAddresses.versaSingleton, mumbaiAddresses.compatibilityFallbackHandler, + deployConfig.entryPointAddress, + deployConfig.versaFactoryOwner, ]); await verify(mumbaiAddresses.versaVerifyingPaymaster, [ - mumbaiAddresses.entryPoint, - mumbaiAddresses.verifyingPaymasterOwner, + deployConfig.entryPointAddress, + deployConfig.verifyingPaymasterOwner, ]); await verify(mumbaiAddresses.compatibilityFallbackHandler); await verify(mumbaiAddresses.ecdsaValidator); @@ -32,14 +35,16 @@ async function main() { break; } case 534351: { - await verify(scrollSepoliaAddresses.versaSingleton, [scrollSepoliaAddresses.entryPoint]); + await verify(scrollSepoliaAddresses.versaSingleton, [deployConfig.entryPointAddress]); await verify(scrollSepoliaAddresses.versaAccountFactory, [ scrollSepoliaAddresses.versaSingleton, scrollSepoliaAddresses.compatibilityFallbackHandler, + deployConfig.entryPointAddress, + deployConfig.versaFactoryOwner, ]); await verify(scrollSepoliaAddresses.versaVerifyingPaymaster, [ - scrollSepoliaAddresses.entryPoint, - scrollSepoliaAddresses.verifyingPaymasterOwner, + deployConfig.entryPointAddress, + deployConfig.verifyingPaymasterOwner, ]); await verify(scrollSepoliaAddresses.compatibilityFallbackHandler); await verify(scrollSepoliaAddresses.ecdsaValidator); diff --git a/deploy/versaAccountFactory.ts b/deploy/versaAccountFactory.ts index 0050152..5902575 100644 --- a/deploy/versaAccountFactory.ts +++ b/deploy/versaAccountFactory.ts @@ -10,6 +10,8 @@ async function deployWithAddresses(addresses: any, config: any) { const versaAccountFactoryData: VersaAccountFactoryData = { versaSingleton: addresses.versaSingleton, defaultFallbackHandler: addresses.compatibilityFallbackHandler, + entryPoint: deployConfig.entryPointAddress, + owner: deployConfig.versaFactoryOwner, }; const versaAccountFactory = await deployer.deployVersaAccountFactory(versaAccountFactoryData, config.salt); addresses.versaAccountFactory = versaAccountFactory.address; diff --git a/deploy/versaSingleton.ts b/deploy/versaSingleton.ts index 12dafa5..45fedb7 100644 --- a/deploy/versaSingleton.ts +++ b/deploy/versaSingleton.ts @@ -6,7 +6,7 @@ import fs from "fs"; import { deployConfig } from "./helper/config"; async function deployWithAddresses(addresses: any, config: any) { - const versaSingleton = await deployer.deployVersaSingleton(config.entryPoint, config.salt); + const versaSingleton = await deployer.deployVersaSingleton(config.entryPointAddress, config.salt); addresses.versaSingleton = versaSingleton.address; return addresses; } diff --git a/test/VersaFactory.test.ts b/test/VersaFactory.test.ts index 94624d9..e8134e4 100644 --- a/test/VersaFactory.test.ts +++ b/test/VersaFactory.test.ts @@ -36,7 +36,9 @@ describe("VersaFactory", () => { // Deploy VersaAccountFactory versaFactory = await new VersaAccountFactory__factory(owner).deploy( versaWalletSingleton.address, - fallbackHandler + fallbackHandler, + entryPoint, + owner.address ); validator = await new MockValidator__factory(owner).deploy(); diff --git a/test/VersaWallet.test.ts b/test/VersaWallet.test.ts index d3c4062..58af773 100644 --- a/test/VersaWallet.test.ts +++ b/test/VersaWallet.test.ts @@ -45,7 +45,9 @@ describe("VersaWallet", () => { // Deploy VersaAccountFactory versaFactory = await new VersaAccountFactory__factory(owner).deploy( versaWalletSingleton.address, - fallbackHandler.address + fallbackHandler.address, + entryPoint.address, + owner.address ); sudoValidator = await new MockValidator__factory(owner).deploy(); diff --git a/test/utils.ts b/test/utils.ts index 5c2574e..b6754f6 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -33,7 +33,9 @@ export async function deployVersaWallet(options: { // Deploy VersaAccountFactory let versaFactory = await new VersaAccountFactory__factory(signer).deploy( versaWalletSingleton.address, - fallbackHandler.address + fallbackHandler.address, + entryPoint, + signer.address ); sudoValidatorAddr =