Skip to content

Commit e9cae25

Browse files
committed
Initial commit
0 parents  commit e9cae25

File tree

3,020 files changed

+993409
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

3,020 files changed

+993409
-0
lines changed

.github/workflows/test.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
env:
9+
FOUNDRY_PROFILE: ci
10+
11+
jobs:
12+
check:
13+
name: Foundry project
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
with:
18+
submodules: recursive
19+
20+
- name: Install Foundry
21+
uses: foundry-rs/foundry-toolchain@v1
22+
23+
- name: Show Forge version
24+
run: |
25+
forge --version
26+
27+
- name: Run Forge fmt
28+
run: |
29+
forge fmt --check
30+
id: fmt
31+
32+
- name: Run Forge build
33+
run: |
34+
forge build --sizes
35+
id: build
36+
37+
- name: Run Forge tests
38+
run: |
39+
forge test -vvv
40+
id: test

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Compiler files
2+
cache/
3+
out/
4+
5+
# Ignores development broadcast logs
6+
!/broadcast
7+
/broadcast/*/31337/
8+
/broadcast/**/dry-run/
9+
10+
# Docs
11+
docs/
12+
13+
# Dotenv file
14+
.env

.gitmodules

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[submodule "lib/forge-std"]
2+
path = lib/forge-std
3+
url = https://github.com/foundry-rs/forge-std
4+
[submodule "lib/account-abstraction"]
5+
path = lib/account-abstraction
6+
url = https://github.com/eth-infinitism/account-abstraction
7+
[submodule "lib/openzeppelin-contracts"]
8+
path = lib/openzeppelin-contracts
9+
url = https://github.com/openzeppelin/openzeppelin-contracts
10+
[submodule "lib/foundry-era-contracts"]
11+
path = lib/foundry-era-contracts
12+
url = https://github.com/Cyfrin/foundry-era-contracts
13+
[submodule "lib/foundry-devops"]
14+
path = lib/foundry-devops
15+
url = https://github.com/chainaccelorg/foundry-devops

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## Foundry
2+
3+
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
4+
5+
Foundry consists of:
6+
7+
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
8+
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
9+
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
10+
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
11+
12+
## Documentation
13+
14+
https://book.getfoundry.sh/
15+
16+
## Usage
17+
18+
### Build
19+
20+
```shell
21+
$ forge build
22+
```
23+
24+
### Test
25+
26+
```shell
27+
$ forge test
28+
```
29+
30+
### Format
31+
32+
```shell
33+
$ forge fmt
34+
```
35+
36+
### Gas Snapshots
37+
38+
```shell
39+
$ forge snapshot
40+
```
41+
42+
### Anvil
43+
44+
```shell
45+
$ anvil
46+
```
47+
48+
### Deploy
49+
50+
```shell
51+
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
52+
```
53+
54+
### Cast
55+
56+
```shell
57+
$ cast <subcommand>
58+
```
59+
60+
### Help
61+
62+
```shell
63+
$ forge --help
64+
$ anvil --help
65+
$ cast --help
66+
```

foundry.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[profile.default]
2+
src = "src"
3+
out = "out"
4+
etherscan_api_key = "${ETHERSCAN_API_KEY}"
5+
libs = ["lib"]
6+
remappings=[
7+
'@openzeppelin/contracts=lib/openzeppelin-contracts/contracts'
8+
]
9+
is-system = true
10+
via-ir = true
11+
optimizer = true
12+
fs_permissions = [
13+
{ access = "read", path = "./broadcast" },
14+
{ access = "read", path = "./reports" },
15+
]
16+
[rpc_endpoints]
17+
mainnet = "${MAINNET_RPC_URL}"
18+
19+
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as fs from "fs-extra";
2+
import { Wallet, Provider, ContractFactory } from "zksync-ethers";
3+
import "dotenv/config";
4+
5+
async function main() {
6+
const provider = new Provider(process.env.MAINNET_RPC_URL!);
7+
const encryptedJson = fs.readFileSync(".encryptedKey.json", "utf8");
8+
let wallet = Wallet.fromEncryptedJsonSync(encryptedJson, process.env.PRIVATE_KEY_PASSWORD!);
9+
wallet = wallet.connect(provider);
10+
const abi = JSON.parse(fs.readFileSync("./out/ZkMinimalAccount.sol/ZkMinimalAccount.json", "utf8")).abi;
11+
const bytecode = JSON.parse(fs.readFileSync("./out/ZkMinimalAccount.sol/ZkMinimalAccount.json", "utf8")).bytecode.object;
12+
const zkMinimalAccountFactory = new ContractFactory(abi, bytecode, wallet);
13+
const zkMinimalAccount = await zkMinimalAccountFactory.deploy();
14+
await (await zkMinimalAccount.deploymentTransaction())!.wait();
15+
console.log(`zkMinimalAccount deployed to: ${await zkMinimalAccount.getAddress()}`);
16+
console.log(`Deployment transaction hash: ${(await zkMinimalAccount.deploymentTransaction())!.hash}`);
17+
}
18+
19+
main()
20+
.then(() => process.exit(0))
21+
.catch(error => {
22+
console.error(error);
23+
process.exit(1);
24+
});

javascript-scripts/EncryptKey.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ethers } from "ethers";
2+
import * as fs from "fs-extra";
3+
import "dotenv/config";
4+
5+
async function main() {
6+
const privateKey = process.env.PRIVATE_KEY;
7+
const password = process.env.PRIVATE_KEY_PASSWORD;
8+
9+
if (!privateKey || !password) {
10+
throw new Error("Missing PRIVATE_KEY or PRIVATE_KEY_PASSWORD in .env");
11+
}
12+
13+
const wallet = new ethers.Wallet(privateKey);
14+
const encryptedJsonKey = await wallet.encrypt(password);
15+
16+
fs.writeFileSync(".encryptedKey.json", encryptedJsonKey);
17+
console.log("Encrypted key saved to .encryptedKey.json");
18+
}
19+
20+
main().catch((error) => {
21+
console.error("Error:", error);
22+
process.exit(1);
23+
});

javascript-scripts/SendAATx.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import * as fs from "fs-extra"
2+
import { utils, Wallet, Provider, EIP712Signer, types, Contract, ContractFactory } from "zksync-ethers"
3+
import * as ethers from "ethers"
4+
import "dotenv/config"
5+
6+
const ZK_MINIMAL_ADDRESS = "0x7653816f9a95083b726F30ACf6bAb6c6A20447F4"
7+
8+
const RANDOM_APPROVER = "0x7653816f9a95083b726F30ACf6bAb6c6A20447F4"
9+
10+
const USDC_ZKSYNC = "0x7653816f9a95083b726F30ACf6bAb6c6A20447F4"
11+
12+
13+
const AMOUNT_TO_APPROVE = "1000000"
14+
15+
async function main() {
16+
console.log("Let's do this!")
17+
18+
let provider = new Provider(process.env.ZKSYNC_SEPOLIA_RPC_URL!)
19+
const encryptedJson = fs.readFileSync(".encryptedKey.json", "utf8")
20+
let wallet = Wallet.fromEncryptedJsonSync(
21+
encryptedJson,
22+
process.env.PRIVATE_KEY_PASSWORD!
23+
)
24+
25+
wallet = wallet.connect(provider)
26+
27+
const abi = JSON.parse(fs.readFileSync("./out/ZkMinimalAccount.sol/ZkMinimalAccount.json", "utf8"))["abi"]
28+
console.log("Setting up contract details...")
29+
const zkMinimalAccount = new Contract(ZK_MINIMAL_ADDRESS, abi, provider)
30+
31+
// If this doesn't log the owner, you have an issue!
32+
console.log(`The owner of this minimal account is: `, await zkMinimalAccount.owner())
33+
const usdcAbi = JSON.parse(fs.readFileSync("./out/ERC20/IERC20.sol/IERC20.json", "utf8"))["abi"]
34+
const usdcContract = new Contract(USDC_ZKSYNC, usdcAbi, provider)
35+
36+
console.log("Populating transaction...")
37+
let approvalData = await usdcContract.approve.populateTransaction(
38+
RANDOM_APPROVER,
39+
AMOUNT_TO_APPROVE
40+
)
41+
42+
let aaTx = approvalData
43+
44+
const gasLimit = await provider.estimateGas({
45+
...aaTx,
46+
from: wallet.address,
47+
})
48+
const gasPrice = (await provider.getFeeData()).gasPrice!
49+
50+
aaTx = {
51+
...aaTx,
52+
from: ZK_MINIMAL_ADDRESS,
53+
gasLimit: gasLimit,
54+
gasPrice: gasPrice,
55+
chainId: (await provider.getNetwork()).chainId,
56+
nonce: await provider.getTransactionCount(ZK_MINIMAL_ADDRESS),
57+
type: 113,
58+
customData: {
59+
gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT,
60+
} as types.Eip712Meta,
61+
value: 0n,
62+
}
63+
const signedTxHash = EIP712Signer.getSignedDigest(aaTx)
64+
65+
console.log("Signing transaction...")
66+
const signature = ethers.concat([
67+
ethers.Signature.from(wallet.signingKey.sign(signedTxHash)).serialized,
68+
])
69+
console.log(signature)
70+
71+
aaTx.customData = {
72+
...aaTx.customData,
73+
customSignature: signature,
74+
}
75+
76+
console.log(
77+
`The minimal account nonce before the first tx is ${await provider.getTransactionCount(
78+
ZK_MINIMAL_ADDRESS,
79+
)}`,
80+
)
81+
82+
const sentTx = await provider.broadcastTransaction(
83+
types.Transaction.from(aaTx).serialized,
84+
)
85+
86+
console.log(`Transaction sent from minimal account with hash ${sentTx.hash}`)
87+
await sentTx.wait()
88+
89+
// Checking that the nonce for the account has increased
90+
console.log(
91+
`The account's nonce after the first tx is ${await provider.getTransactionCount(
92+
ZK_MINIMAL_ADDRESS,
93+
)}`,
94+
)
95+
}
96+
97+
main()
98+
.then(() => process.exit(0))
99+
.catch((error) => {
100+
console.error(error)
101+
process.exit(1)
102+
})

lib/account-abstraction

Submodule account-abstraction added at 7af70c8

lib/forge-std

Submodule forge-std added at 8bbcf6e

0 commit comments

Comments
 (0)