Skip to content

Commit ebde6ee

Browse files
authored
Merge pull request #62 from AztecProtocol/jz/test-bridged-juice
Jz/test bridged juice
2 parents 73696bd + 82b6182 commit ebde6ee

File tree

6 files changed

+229
-15
lines changed

6 files changed

+229
-15
lines changed

jest.integration.config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
},
99
"testRegex": "./src/.*\\.test\\.ts$",
1010
"rootDir": "./src",
11-
"testTimeout": 30000
11+
"testTimeout": 70000
1212
}

scripts/deploy-account.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AccountWallet, CompleteAddress, createLogger, Fr, PXE, waitForPXE, crea
22
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
33
import { deriveSigningKey } from '@aztec/stdlib/keys';
44
import { getInitialTestAccountsWallets } from "@aztec/accounts/testing";
5-
import { SponsoredFeePaymentMethod } from "../src/test/sponsored_fee_payment_method.js";
5+
import { SponsoredFeePaymentMethod } from "../src/utils/sponsored_fee_payment_method.js";
66

77

88
const setupSandbox = async () => {

src/test/accounts.test.ts

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import { EasyPrivateVotingContractArtifact, EasyPrivateVotingContract } from "../artifacts/EasyPrivateVoting.js"
2+
import { AccountManager, AccountWallet, CompleteAddress, ContractDeployer, createLogger, Fr, PXE, waitForPXE, TxStatus, createPXEClient, getContractInstanceFromDeployParams, Logger } from "@aztec/aztec.js";
3+
import { getInitialTestAccountsWallets, generateSchnorrAccounts } from "@aztec/accounts/testing"
4+
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
5+
import { spawn } from 'child_process';
6+
import { SponsoredFeePaymentMethod } from '../utils/sponsored_fee_payment_method.js';
7+
import { getFeeJuiceBalance, type L2AmountClaim, L1FeeJuicePortalManager, FeeJuicePaymentMethodWithClaim, AztecAddress } from "@aztec/aztec.js";
8+
import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
9+
10+
const setupSandbox = async () => {
11+
const { PXE_URL = 'http://localhost:8080' } = process.env;
12+
const pxe = createPXEClient(PXE_URL);
13+
await waitForPXE(pxe);
14+
return pxe;
15+
};
16+
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
17+
18+
describe("Accounts", () => {
19+
let pxe: PXE;
20+
let wallets: AccountWallet[] = [];
21+
let accounts: CompleteAddress[] = [];
22+
let logger: Logger;
23+
let sandboxInstance;
24+
let sponsoredPaymentMethod: SponsoredFeePaymentMethod;
25+
26+
let randomAccountManagers: AccountManager[] = [];
27+
let randomWallets: AccountWallet[] = [];
28+
let randomAddresses: AztecAddress[] = [];
29+
30+
let l1PortalManager: L1FeeJuicePortalManager;
31+
let feeJuiceAddress: AztecAddress;
32+
let skipSandbox: boolean;
33+
34+
beforeAll(async () => {
35+
skipSandbox = process.env.SKIP_SANDBOX === 'true';
36+
if (!skipSandbox) {
37+
sandboxInstance = spawn("aztec", ["start", "--sandbox"], {
38+
detached: true,
39+
stdio: 'ignore'
40+
})
41+
await sleep(15000);
42+
}
43+
44+
logger = createLogger('aztec:aztec-starter:accounts');
45+
logger.info("Aztec-Starter tests running.")
46+
47+
pxe = await setupSandbox();
48+
49+
wallets = await getInitialTestAccountsWallets(pxe);
50+
accounts = wallets.map(w => w.getCompleteAddress());
51+
sponsoredPaymentMethod = await SponsoredFeePaymentMethod.new(pxe);
52+
53+
// generate random accounts
54+
randomAccountManagers = await Promise.all(
55+
(await generateSchnorrAccounts(5)).map(
56+
a => getSchnorrAccount(pxe, a.secret, a.signingKey, a.salt)
57+
)
58+
);
59+
// get corresponding wallets
60+
randomWallets = await Promise.all(randomAccountManagers.map(am => am.getWallet()));
61+
// get corresponding addresses
62+
randomAddresses = await Promise.all(randomWallets.map(async w => (await w.getCompleteAddress()).address));
63+
64+
// create default ethereum clients
65+
const nodeInfo = await pxe.getNodeInfo();
66+
const chain = createEthereumChain(['http://localhost:8545'], nodeInfo.l1ChainId);
67+
const DefaultMnemonic = 'test test test test test test test test test test test junk';
68+
const { publicClient, walletClient } = createL1Clients(chain.rpcUrls, DefaultMnemonic, chain.chainInfo);
69+
70+
feeJuiceAddress = nodeInfo.protocolContractAddresses.feeJuice;
71+
72+
// create portal manager
73+
l1PortalManager = await L1FeeJuicePortalManager.new(
74+
pxe,
75+
publicClient,
76+
walletClient,
77+
logger
78+
);
79+
80+
})
81+
82+
afterAll(async () => {
83+
if (!skipSandbox) {
84+
sandboxInstance!.kill('SIGINT');
85+
}
86+
})
87+
88+
it("Creates accounts with fee juice", async () => {
89+
// balance of each random account is 0 before bridge
90+
let balances = await Promise.all(randomAddresses.map(async a => getFeeJuiceBalance(a, pxe)));
91+
balances.forEach(b => expect(b).toBe(0n));
92+
93+
94+
// bridge funds to unfunded random addresses
95+
const claimAmount = 10n ** 22n;
96+
const approxMaxDeployCost = 10n ** 10n; // Need to manually update this if fees increase significantly
97+
let claims: L2AmountClaim[] = [];
98+
// bridge sequentially to avoid l1 txs (nonces) being processed out of order
99+
for (let i = 0; i < randomAddresses.length; i++) {
100+
claims.push(await l1PortalManager.bridgeTokensPublic(randomAddresses[i], claimAmount, true));
101+
}
102+
103+
// arbitrary transactions to progress 2 blocks, and have fee juice on Aztec ready to claim
104+
await EasyPrivateVotingContract.deploy(wallets[0], accounts[0]).send().deployed(); // deploy contract with first funded wallet
105+
await EasyPrivateVotingContract.deploy(wallets[0], accounts[0]).send().deployed(); // deploy contract with first funded wallet
106+
107+
// claim and pay to deploy random accounts
108+
let sentTxs = [];
109+
for (let i = 0; i < randomWallets.length; i++) {
110+
const paymentMethod = new FeeJuicePaymentMethodWithClaim(randomWallets[i], claims[i]);
111+
sentTxs.push(randomAccountManagers[i].deploy({ fee: { paymentMethod } }));
112+
}
113+
await Promise.all(sentTxs.map(stx => stx.wait()));
114+
115+
// balance after deploy with claimed fee juice
116+
balances = await Promise.all(randomAddresses.map(async a => getFeeJuiceBalance(a, pxe)));
117+
const amountAfterDeploy = claimAmount - approxMaxDeployCost;
118+
balances.forEach(b => expect(b).toBeGreaterThanOrEqual(amountAfterDeploy));
119+
120+
});
121+
122+
it("Deploys first unfunded account from first funded account", async () => {
123+
const tx_acc = await randomAccountManagers[0].deploy({ deployWallet: wallets[0] });
124+
});
125+
126+
it("Sponsored contract deployment", async () => {
127+
const salt = Fr.random();
128+
const VotingContractArtifact = EasyPrivateVotingContractArtifact
129+
// const [deployerWallet, adminWallet] = wallets; // using first account as deployer and second as contract admin
130+
const accounts = await Promise.all(
131+
(await generateSchnorrAccounts(2)).map(
132+
async a => await getSchnorrAccount(pxe, a.secret, a.signingKey, a.salt)
133+
)
134+
);
135+
await Promise.all(accounts.map(a => a.deploy({ fee: { paymentMethod: sponsoredPaymentMethod } })));
136+
const daWallets = await Promise.all(accounts.map(a => a.getWallet()));
137+
const [deployerWallet, adminWallet] = daWallets;
138+
const [deployerAddress, adminAddress] = daWallets.map(w => w.getAddress());
139+
// const adminAddress = adminWallet.getCompleteAddress().address;
140+
141+
const deploymentData = await getContractInstanceFromDeployParams(VotingContractArtifact,
142+
{
143+
constructorArgs: [adminAddress],
144+
salt,
145+
deployer: deployerWallet.getAddress()
146+
});
147+
const deployer = new ContractDeployer(VotingContractArtifact, deployerWallet);
148+
const tx = deployer.deploy(adminAddress).send({
149+
contractAddressSalt: salt,
150+
fee: { paymentMethod: sponsoredPaymentMethod } // without the sponsoredFPC the deployment fails, thus confirming it works
151+
})
152+
const receipt = await tx.getReceipt();
153+
154+
expect(receipt).toEqual(
155+
expect.objectContaining({
156+
status: TxStatus.PENDING,
157+
error: ''
158+
}),
159+
);
160+
161+
const receiptAfterMined = await tx.wait({ wallet: deployerWallet });
162+
expect(await pxe.getContractMetadata(deploymentData.address)).toBeDefined();
163+
expect((await pxe.getContractMetadata(deploymentData.address)).contractInstance).toBeTruthy();
164+
expect(receiptAfterMined).toEqual(
165+
expect.objectContaining({
166+
status: TxStatus.SUCCESS,
167+
}),
168+
);
169+
170+
expect(receiptAfterMined.contract.instance.address).toEqual(deploymentData.address)
171+
})
172+
173+
});

src/test/index.test.ts

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { AccountManager, AccountWallet, CompleteAddress, ContractDeployer, creat
33
import { getInitialTestAccountsWallets, generateSchnorrAccounts } from "@aztec/accounts/testing"
44
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
55
import { spawn } from 'child_process';
6-
import { SponsoredFeePaymentMethod } from './sponsored_fee_payment_method.js';
6+
import { SponsoredFeePaymentMethod } from '../utils/sponsored_fee_payment_method.js';
7+
import { L1FeeJuicePortalManager, AztecAddress } from "@aztec/aztec.js";
8+
import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
79

810
const setupSandbox = async () => {
911
const { PXE_URL = 'http://localhost:8080' } = process.env;
@@ -21,24 +23,63 @@ describe("Voting", () => {
2123
let sandboxInstance;
2224
let sponsoredPaymentMethod: SponsoredFeePaymentMethod;
2325

26+
let randomAccountManagers: AccountManager[] = [];
27+
let randomWallets: AccountWallet[] = [];
28+
let randomAddresses: AztecAddress[] = [];
29+
30+
let l1PortalManager: L1FeeJuicePortalManager;
31+
let skipSandbox: boolean;
32+
2433
beforeAll(async () => {
25-
sandboxInstance = spawn("aztec", ["start", "--sandbox"], {
26-
detached: true,
27-
stdio: 'ignore'
28-
})
29-
sleep(15000)
30-
logger = createLogger('aztec:aztec-starter');
34+
skipSandbox = process.env.SKIP_SANDBOX === 'true';
35+
if (!skipSandbox) {
36+
sandboxInstance = spawn("aztec", ["start", "--sandbox"], {
37+
detached: true,
38+
stdio: 'ignore'
39+
})
40+
await sleep(15000);
41+
}
42+
43+
logger = createLogger('aztec:aztec-starter:voting');
3144
logger.info("Aztec-Starter tests running.")
3245

3346
pxe = await setupSandbox();
3447

3548
wallets = await getInitialTestAccountsWallets(pxe);
36-
accounts = wallets.map(w => w.getCompleteAddress())
49+
accounts = wallets.map(w => w.getCompleteAddress());
3750
sponsoredPaymentMethod = await SponsoredFeePaymentMethod.new(pxe);
51+
52+
// generate random accounts
53+
randomAccountManagers = await Promise.all(
54+
(await generateSchnorrAccounts(5)).map(
55+
a => getSchnorrAccount(pxe, a.secret, a.signingKey, a.salt)
56+
)
57+
);
58+
// get corresponding wallets
59+
randomWallets = await Promise.all(randomAccountManagers.map(am => am.getWallet()));
60+
// get corresponding addresses
61+
randomAddresses = await Promise.all(randomWallets.map(async w => (await w.getCompleteAddress()).address));
62+
63+
// create default ethereum clients
64+
const nodeInfo = await pxe.getNodeInfo();
65+
const chain = createEthereumChain(['http://localhost:8545'], nodeInfo.l1ChainId);
66+
const DefaultMnemonic = 'test test test test test test test test test test test junk';
67+
const { publicClient, walletClient } = createL1Clients(chain.rpcUrls, DefaultMnemonic, chain.chainInfo);
68+
69+
// create portal manager
70+
l1PortalManager = await L1FeeJuicePortalManager.new(
71+
pxe,
72+
publicClient,
73+
walletClient,
74+
logger
75+
);
76+
3877
})
3978

4079
afterAll(async () => {
41-
sandboxInstance!.kill();
80+
if (!skipSandbox) {
81+
sandboxInstance!.kill('SIGINT');
82+
}
4283
})
4384

4485
it("Deploys the contract", async () => {
@@ -86,7 +127,7 @@ describe("Voting", () => {
86127
);
87128

88129
expect(receiptAfterMined.contract.instance.address).toEqual(deploymentData.address)
89-
}, 300_000)
130+
})
90131

91132
it("It casts a vote", async () => {
92133
const candidate = new Fr(1)
@@ -95,7 +136,7 @@ describe("Voting", () => {
95136
const tx = await contract.methods.cast_vote(candidate).send().wait();
96137
let count = await contract.methods.get_vote(candidate).simulate();
97138
expect(count).toBe(1n);
98-
}, 300_000)
139+
})
99140

100141
it("It should fail when trying to vote twice", async () => {
101142
const candidate = new Fr(1)
@@ -113,6 +154,6 @@ describe("Voting", () => {
113154
votingContract.methods.cast_vote(candidate).send({ skipPublicSimulation: true }).wait(),
114155
).rejects.toThrow(TxStatus.APP_LOGIC_REVERTED);
115156

116-
}, 300_000)
157+
})
117158

118159
});
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class SponsoredFeePaymentMethod implements FeePaymentMethod {
1515
* Contract which will pay the fee.
1616
*/
1717
private paymentContract: AztecAddress,
18-
) {}
18+
) { }
1919

2020
static async new(pxe: PXE) {
2121
const sponsoredFPC = await getDeployedSponsoredFPCAddress(pxe);

0 commit comments

Comments
 (0)