Skip to content

Commit 97e1f3f

Browse files
authored
Merge pull request #71 from AztecProtocol/jc/more-fees
add claim and pay, and private fpc
2 parents 2136ff8 + 648da37 commit 97e1f3f

File tree

6 files changed

+148
-79
lines changed

6 files changed

+148
-79
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ jobs:
4747
run: script -e -c "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --config jest.integration.config.json && aztec test"
4848

4949
- name: Run scripts
50-
run: script -e -c "yarn deploy && yarn deploy-account && yarn bridge-juice"
50+
run: script -e -c "yarn deploy && yarn deploy-account && yarn fees"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"private": true,
99
"type": "module",
1010
"scripts": {
11-
"bridge-juice": "node --loader ts-node/esm scripts/bridgeFeeJuice.ts",
11+
"fees": "node --loader ts-node/esm scripts/fees.ts",
1212
"clean": "rm -rf ./src/artifacts ./target",
1313
"codegen": "aztec codegen target --outdir src/artifacts",
1414
"compile": "${AZTEC_NARGO:-aztec-nargo} compile",

scripts/bridgeFeeJuice.ts

Lines changed: 0 additions & 75 deletions
This file was deleted.

scripts/fees.ts

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import { AccountWallet, CompleteAddress, createLogger, FeeJuicePaymentMethodWithClaim, Fr, L1FeeJuicePortalManager, PXE, waitForPXE , createPXEClient, Logger, FeeJuicePaymentMethod, PrivateFeePaymentMethod, PublicFeePaymentMethod } from "@aztec/aztec.js";
2+
import { getInitialTestAccountsWallets } from "@aztec/accounts/testing";
3+
import {
4+
createPublicClient,
5+
createWalletClient,
6+
http,
7+
} from 'viem';
8+
import { getSchnorrAccount } from '@aztec/accounts/schnorr';
9+
import { deriveSigningKey } from '@aztec/stdlib/keys';
10+
import { foundry } from 'viem/chains'
11+
import { mnemonicToAccount } from 'viem/accounts';
12+
import { FeeJuiceContract } from "@aztec/noir-contracts.js/FeeJuice";
13+
import { FPCContract } from "@aztec/noir-contracts.js/FPC";
14+
import { EasyPrivateVotingContract } from "../src/artifacts/EasyPrivateVoting.js"
15+
import { TokenContract } from "@aztec/noir-contracts.js/Token";
16+
// TODO: replace with import from aztec.js when published
17+
import { SponsoredFeePaymentMethod } from '../src/utils/sponsored_fee_payment_method.js'
18+
19+
const setupSandbox = async () => {
20+
const { PXE_URL = 'http://localhost:8080' } = process.env;
21+
const pxe = await createPXEClient(PXE_URL);
22+
await waitForPXE(pxe);
23+
return pxe;
24+
};
25+
26+
const MNEMONIC = 'test test test test test test test test test test test junk';
27+
const FEE_FUNDING_FOR_TESTER_ACCOUNT = BigInt(1_000e20);
28+
29+
let walletClient = getL1WalletClient(foundry.rpcUrls.default.http[0], 0);
30+
const ownerEthAddress = walletClient.account.address;
31+
32+
const publicClient = createPublicClient({
33+
chain: foundry,
34+
transport: http("http://127.0.0.1:8545"),
35+
});
36+
37+
async function main() {
38+
39+
let pxe: PXE;
40+
let wallets: AccountWallet[] = [];
41+
let logger: Logger;
42+
43+
const amount = FEE_FUNDING_FOR_TESTER_ACCOUNT;
44+
45+
logger = createLogger('aztec:aztec-starter');
46+
47+
pxe = await setupSandbox();
48+
wallets = await getInitialTestAccountsWallets(pxe);
49+
const nodeInfo = (await pxe.getNodeInfo())
50+
const l1ContractAddresses = nodeInfo.l1ContractAddresses;
51+
52+
// Setup Schnorr AccountManager
53+
54+
let secretKey = Fr.random();
55+
let salt = Fr.random();
56+
let schnorrAccount = await getSchnorrAccount(pxe, secretKey, deriveSigningKey(secretKey), salt);
57+
58+
const newWallet = await schnorrAccount.getWallet()
59+
const feeJuiceReceipient = schnorrAccount.getAddress()
60+
61+
// Setup and bridge fee asset to L2 to get fee juice
62+
63+
const feeJuicePortalManager = new L1FeeJuicePortalManager(
64+
l1ContractAddresses.feeJuicePortalAddress,
65+
l1ContractAddresses.feeJuiceAddress,
66+
//@ts-ignore
67+
publicClient,
68+
walletClient,
69+
logger,
70+
);
71+
72+
const claim = await feeJuicePortalManager.bridgeTokensPublic(feeJuiceReceipient, amount, true);
73+
74+
const feeJuice = await FeeJuiceContract.at(nodeInfo.protocolContractAddresses.feeJuice, wallets[0])
75+
logger.info(`Fee Juice minted to ${feeJuiceReceipient} on L2.`)
76+
77+
// Two arbitraty txs to make the L1 message available on L2
78+
const votingContract = await EasyPrivateVotingContract.deploy(wallets[0], wallets[0].getAddress()).send().deployed();
79+
const bananaCoin = await TokenContract.deploy(wallets[0], wallets[0].getAddress(), "bananaCoin", "BNC", 18).send().deployed()
80+
81+
// Claim Fee Juice & Pay Fees yourself
82+
83+
const claimAndPay = new FeeJuicePaymentMethodWithClaim(newWallet, claim)
84+
await schnorrAccount.deploy({ fee: { paymentMethod: claimAndPay } }).wait()
85+
logger.info(`New account at ${newWallet.getAddress()} deployed using claimed funds for fees.`)
86+
87+
// Pay fees yourself
88+
89+
// Create a new voting contract instance, interacting from the newWallet
90+
const useFeeJuice = new FeeJuicePaymentMethod(newWallet.getAddress())
91+
await votingContract.withWallet(newWallet).methods.cast_vote(wallets[0].getAddress()).send({ fee: { paymentMethod: useFeeJuice }}).wait()
92+
logger.info(`Vote cast from new account, paying fees via newWallet.`)
93+
94+
// Private Fee Payments via FPC
95+
96+
// Must use a Fee Paying Contract (FPC) to pay fees privately
97+
// Need to deploy an FPC to use Private Fee payment methods
98+
99+
// This uses bananaCoin as the fee paying asset that will be exchanged for fee juice
100+
const fpc = await FPCContract.deploy(wallets[0], bananaCoin.address, wallets[0].getAddress()).send().deployed()
101+
const fpcClaim = await feeJuicePortalManager.bridgeTokensPublic(fpc.address, amount, true);
102+
// 2 public txs to make the bridged fee juice available
103+
// Mint some bananaCoin and send to the newWallet to pay fees privately
104+
await bananaCoin.methods.mint_to_private(wallets[0].getAddress(), newWallet.getAddress(), FEE_FUNDING_FOR_TESTER_ACCOUNT).send().wait()
105+
// mint some public bananaCoin to the newWallet to pay fees publicly
106+
await bananaCoin.methods.mint_to_public(newWallet.getAddress(), FEE_FUNDING_FOR_TESTER_ACCOUNT).send().wait()
107+
const bananaBalance = await bananaCoin.withWallet(newWallet).methods.balance_of_private(newWallet.getAddress()).simulate()
108+
109+
logger.info(`BananaCoin balance of newWallet is ${bananaBalance}`)
110+
111+
await feeJuice.methods.claim(fpc.address, fpcClaim.claimAmount, fpcClaim.claimSecret, fpcClaim.messageLeafIndex).send().wait()
112+
113+
logger.info(`Fpc fee juice balance ${await feeJuice.methods.balance_of_public(fpc.address).simulate()}`)
114+
115+
const privateFee = new PrivateFeePaymentMethod(fpc.address, newWallet)
116+
await bananaCoin.withWallet(newWallet).methods.transfer_in_private(newWallet.getAddress(), wallets[0].getAddress(), 10, 0).send({ fee: { paymentMethod: privateFee }}).wait()
117+
118+
logger.info(`Transfer paid with fees via the FPC, privately.`)
119+
120+
// Public Fee Payments via FPC
121+
122+
const publicFee = new PublicFeePaymentMethod(fpc.address, newWallet)
123+
await bananaCoin.withWallet(newWallet).methods.transfer_in_private(newWallet.getAddress(), wallets[0].getAddress(), 10, 0).send({ fee: { paymentMethod: publicFee }}).wait()
124+
logger.info(`Transfer paid with fees via the FPC, publicly.`)
125+
126+
// Sponsored Fee Payment
127+
128+
// This method will only work in environments where there is a sponsored fee contract deployed
129+
const sponsoredPaymentMethod = await SponsoredFeePaymentMethod.new(pxe);
130+
await bananaCoin.withWallet(newWallet).methods.transfer_in_private(newWallet.getAddress(), wallets[0].getAddress(), 10, 0).send({ fee: { paymentMethod: sponsoredPaymentMethod }}).wait()
131+
logger.info(`Transfer paid with fees from Sponsored FPC.`)
132+
}
133+
134+
main();
135+
136+
// from here: https://github.com/AztecProtocol/aztec-packages/blob/ecbd59e58006533c8885a8b2fadbd9507489300c/yarn-project/end-to-end/src/fixtures/utils.ts#L534
137+
function getL1WalletClient(rpcUrl: string, index: number) {
138+
const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: index });
139+
return createWalletClient({
140+
account: hdAccount,
141+
chain: foundry,
142+
transport: http(rpcUrl),
143+
});
144+
}

src/test/accounts.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ 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 '../utils/sponsored_fee_payment_method.js';
6+
import { SponsoredFeePaymentMethod } from '../utils/sponsored_fee_payment_method.js'
77
import { getFeeJuiceBalance, type L2AmountClaim, L1FeeJuicePortalManager, FeeJuicePaymentMethodWithClaim, AztecAddress } from "@aztec/aztec.js";
88
import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
99

src/test/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ 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 '../utils/sponsored_fee_payment_method.js';
6+
import { SponsoredFeePaymentMethod } from '../utils/sponsored_fee_payment_method.js'
77
import { L1FeeJuicePortalManager, AztecAddress } from "@aztec/aztec.js";
88
import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
99

0 commit comments

Comments
 (0)