Skip to content
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

Account abstraction #110

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ packages/circuits/out
packages/circuits/trusted_setup
packages/circuits/zkeys
packages/webapp/public/proofs

# Roll-op files
roll-op/
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ anvil:
cd packages/contracts && make anvil
.PHONY: anvil

# Runs rollop
rollop:
@if [ ! -d "../roll-op" ]; then \
git clone https://github.com/0xFableOrg/roll-op.git ../roll-op; \
fi
cd ../roll-op && ./rollop setup && ./rollop devnet

# Runs account abstraction bundler and paymaster
account-abstraction:
cd ../roll-op && ./rollop aa

# Runs the webapp in dev mode.
webdev:
cd packages/webapp && make dev
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
"author": "0xFable Team",
"license": "BSD-3-Clause-Clear",
"version": "1.0.0",
"private": true,
"packageManager": "[email protected]"
"private": true
}
2 changes: 1 addition & 1 deletion packages/contracts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ export PRIVATE_KEY_LOCAL=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784
export PRIVATE_KEY_TEST=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
export PRIVATE_KEY_MAIN=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

export RPC_LOCAL=http://localhost:8545
export RPC_LOCAL=http://localhost:9545
export RPC_TEST=https://rpc.chiadochain.net
export RPC_MAIN=https://rpc.ankr.com/gnosis
3 changes: 2 additions & 1 deletion packages/contracts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ selectors:

# Deploys locally, to testnet or mainnet depending on the $CONFIG value (locally if not set).
deploy: build
@forge script src/deploy/Deploy.s.sol:Deploy \
echo "Deploying to $(CONFIG)"
forge script src/deploy/Deploy.s.sol:Deploy \
--fork-url $(RPC_$(CONFIG)) \
--private-key $(PRIVATE_KEY_$(CONFIG)) \
--broadcast \
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
"@dnd-kit/sortable": "^7.0.2",
"@dnd-kit/utilities": "^3.2.1",
"@emotion/react": "^11.11.1",
"axios": "^1.6.5",
"circomlibjs": "^0.1.7",
"connectkit": "^1.5.3",
"jotai": "^2.4.3",
"jotai-devtools": "^0.7.0",
"lodash": "^4.17.21",
"next": "^13.5.6",
"next-transpile-modules": "^10.0.1",
"permissionless": "^0.0.20",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.11.0",
Expand Down
21 changes: 20 additions & 1 deletion packages/webapp/src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import { getDefaultConfig, getDefaultConnectors } from "connectkit"
import { defineChain } from "viem"
import { type Chain, createConfig } from "wagmi"
import { localhost } from "wagmi/chains"

Expand All @@ -13,7 +14,25 @@ import { BurnerConnector } from "src/wagmi/BurnerConnector"
// =================================================================================================

/** The list of chains supported by the app. */
export const chains = [localhost]
export const rollop = defineChain({
...localhost,
id: 1201101712,
name: 'Rollop',
nativeCurrency: {
decimals: 18,
name: 'Ether',
symbol: 'ETH',
},
rpcUrls: {
default: {
http: ["http://localhost:9545"]
},
public: {
http: ["http://localhost:9545"]
}
}
});
export const chains = [rollop]

// =================================================================================================
// Wagmi + ConnectKit Config
Expand Down
9 changes: 9 additions & 0 deletions packages/webapp/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { MintDeckModal } from "src/components/modals/mintDeckModal"
import { useGameInGame } from "src/generated"
import { FablePage } from "src/pages/_app"
import { useGameID } from "src/store/hooks"
import { createAccount } from "src/utils/accounts"

const Home: FablePage = ({ isHydrated }) => {
const { address } = useAccount()
Expand Down Expand Up @@ -51,6 +52,14 @@ const Home: FablePage = ({ isHydrated }) => {
>
Connect Wallet
</button>
<button
className="btn-lg btn border-2 border-yellow-500 normal-case hover:scale-105 hover:border-yellow-400"
onClick={async () => {
await createAccount();
}}
>
Create Burner Wallet
</button>
</div>
}

Expand Down
3 changes: 2 additions & 1 deletion packages/webapp/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ const filteredErrorCodes = [
]

const filteredErrorMessages: (string|RegExp)[] = [
"ChainDoesNotSupportContract: Chain \"Localhost\" does not support contract \"ensUniversalResolver\"."
"ChainDoesNotSupportContract: Chain \"Localhost\" does not support contract \"ensUniversalResolver\".",
"ChainDoesNotSupportContract: Chain \"Rollop\" does not support contract \"ensUniversalResolver\"."
]

const filteredWarningMessages = [
Expand Down
87 changes: 87 additions & 0 deletions packages/webapp/src/utils/accounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* Utilities to deal with burner accounts.
*
* @module utils/accounts
*/

import axios from 'axios'
import { Address, http, parseEther, defineChain, toHex, concat, createPublicClient } from 'viem'
import { localhost } from 'viem/chains'
import { generatePrivateKey } from 'viem/accounts'
import { createSmartAccountClient, UserOperation } from 'permissionless'
import { privateKeyToSimpleSmartAccount } from 'permissionless/accounts'

export async function createAccount() {

const rollop = defineChain({
...localhost,
id: 1201101712,
name: 'Rollop',
nativeCurrency: {
decimals: 18,
name: 'Ether',
symbol: 'ETH',
},
});

const publicClient = createPublicClient({
transport: http("http://localhost:9545"),
});

// generate an in browser private key
const privateKey = generatePrivateKey()
// TODO: store this private key in atom

// create a simple account where the private key is the signer
const simpleAccount = await privateKeyToSimpleSmartAccount(publicClient, {
privateKey: privateKey,
factoryAddress: "0x9406Cc6185a346906296840746125a0E44976454",
entryPoint: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", // global entrypoint
});

// create a smart account client (equivalent to a walletClient)
const smartAccountClient = createSmartAccountClient({
chain: rollop,
account: simpleAccount,
transport: http("http://localhost:4337"),
sponsorUserOperation: async (args: { userOperation: UserOperation, entryPoint: Address }) => {
const userOp = {
sender: args.userOperation.sender,
nonce: toHex(args.userOperation.nonce),
initCode: args.userOperation.initCode,
callData: args.userOperation.callData,
paymasterAndData: concat([
'0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9',
'0x' + '00'.repeat(64) as `0x${string}`,
'0x' + '00'.repeat(65) as `0x${string}`
]),
signature: args.userOperation.signature,
maxFeePerGas: toHex(2_000_000_000),
maxPriorityFeePerGas: toHex(1_000_000_000),
callGasLimit: toHex(3_000_000),
verificationGasLimit: toHex(3_000_000),
preVerificationGas: toHex(2_000_000)
}
const jsonRpcRequest = {
jsonrpc: '2.0',
method: 'pm_sponsorUserOperation',
params: userOp,
id: 1
};
const response = await axios.post("http://localhost:3000", jsonRpcRequest, {
headers: {
'Content-Type': 'application/json',
},
});
return response.data.result;
}
});

// to send a transaction, it will be similar to using walletClient, example below
/*
const txHash = await smartAccountClient.sendTransaction({
to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
value: BigInt(0),
data: "0x68656c6c6f"
}); */
}
7 changes: 3 additions & 4 deletions packages/webapp/src/wagmi/BurnerConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
*/

import { Connector, ConnectorData, WalletClient } from "wagmi"
import { Address } from "src/chain"
import { Address, rollop } from "src/chain"
import { PrivateKeyAccount, privateKeyToAccount } from "viem/accounts"
import { createWalletClient, http } from "viem"
import { localhost } from "wagmi/chains"
import { connect, disconnect, getAccount } from "wagmi/actions"
import { AsyncLock } from "src/utils/asyncLock"

Expand Down Expand Up @@ -43,7 +42,7 @@ export class BurnerConnector extends Connector {
readonly name = "0xFable Burner Wallet"
ready = false

#chain = localhost
#chain = rollop
#connected = false
#connectLock = new AsyncLock()
#privKey: PrivateKey = undefined as any
Expand All @@ -52,7 +51,7 @@ export class BurnerConnector extends Connector {

constructor() {
super({
chains: [localhost],
chains: [rollop],
options: {}
})
}
Expand Down
Loading