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

fix: canonical contract address #5030

Merged
merged 5 commits into from
Mar 8, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ contract AppSubscription {
SharedImmutable
};

use dep::aztec::protocol_types::traits::is_empty;

use dep::aztec::{context::Context, oracle::get_public_key::get_public_key};
use dep::authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit};

Expand All @@ -29,7 +31,7 @@ contract AppSubscription {

global SUBSCRIPTION_DURATION_IN_BLOCKS = 5;
global SUBSCRIPTION_TXS = 5;
// global GAS_TOKEN_ADDRESS = AztecAddress::from_field(0x08c0e8041f92758ca49ccb62a77318b46090019d380552ddaec5cd0b54804636);
global CANONICAL_GAS_TOKEN_ADDRESS = AztecAddress::from_field(0x22a29a9544c0cbdbc35bb21caa78b6f08903be4b390a65319e33afd7443f3499);

#[aztec(private)]
fn entrypoint(payload: pub DAppPayload, user_address: pub AztecAddress) {
Expand Down Expand Up @@ -79,7 +81,13 @@ contract AppSubscription {
storage.subscription_token_address.initialize(subscription_token_address);
storage.subscription_recipient_address.initialize(subscription_recipient_address);
storage.subscription_price.initialize(subscription_price);
storage.gas_token_address.initialize(gas_token_address);

let actual_gas_token_address = if is_empty(gas_token_address) {
CANONICAL_GAS_TOKEN_ADDRESS
} else {
gas_token_address
};
storage.gas_token_address.initialize(actual_gas_token_address);
}

#[aztec(public)]
Expand Down
18 changes: 13 additions & 5 deletions noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
mod interfaces;

contract FPC {
use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress};
use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::is_empty};
use dep::aztec::state_vars::SharedImmutable;

use crate::interfaces::Token;

struct Storage {
other_asset: SharedImmutable<AztecAddress>,
fee_asset: SharedImmutable<AztecAddress>,
gas_token_address: SharedImmutable<AztecAddress>,
}

global CANONICAL_GAS_TOKEN_ADDRESS = AztecAddress::from_field(0x22a29a9544c0cbdbc35bb21caa78b6f08903be4b390a65319e33afd7443f3499);

#[aztec(public)]
#[aztec(initializer)]
fn constructor(other_asset: AztecAddress, fee_asset: AztecAddress) {
fn constructor(other_asset: AztecAddress, gas_token_address: AztecAddress) {
let actual_gas_token_address = if is_empty(gas_token_address) {
CANONICAL_GAS_TOKEN_ADDRESS
} else {
gas_token_address
};

storage.other_asset.initialize(other_asset);
storage.fee_asset.initialize(fee_asset);
storage.gas_token_address.initialize(actual_gas_token_address);
}

#[aztec(private)]
Expand Down Expand Up @@ -62,7 +70,7 @@ contract FPC {
#[aztec(internal)]
fn pay_fee(refund_address: AztecAddress, amount: Field, asset: AztecAddress) {
let refund = context.call_public_function(
storage.fee_asset.read_public(),
storage.gas_token_address.read_public(),
FunctionSelector::from_signature("pay_fee(Field)"),
[amount]
)[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@ exports[`ContractClass creates a contract class from a contract compilation arti
"privateFunctions": [
{
"selector": {
"value": 2432309179
"value": 283286945
},
"vkHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"isInternal": false
},
{
"selector": {
"value": 283286945
"value": 332459554
},
"vkHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"isInternal": false
},
{
"selector": {
"value": 332459554
"value": 2432309179
},
"vkHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"isInternal": false
Expand Down
24 changes: 16 additions & 8 deletions yarn-project/circuits.js/src/contract/contract_class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { packBytecode } from './public_bytecode.js';
/** Contract artifact including its artifact hash */
type ContractArtifactWithHash = ContractArtifact & { artifactHash: Fr };

const cmpFunctionArtifacts = <T extends { selector: FunctionSelector }>(a: T, b: T) =>
a.selector.toField().cmp(b.selector.toField());

/** Creates a ContractClass from a contract compilation artifact. */
export function getContractClassFromArtifact(
artifact: ContractArtifact | ContractArtifactWithHash,
Expand All @@ -20,21 +23,26 @@ export function getContractClassFromArtifact(
selector: FunctionSelector.fromNameAndParameters(f.name, f.parameters),
bytecode: Buffer.from(f.bytecode, 'base64'),
isInternal: f.isInternal,
}));
}))
.sort(cmpFunctionArtifacts);

const packedBytecode = packBytecode(publicFunctions);

const privateFunctions: ContractClass['privateFunctions'] = artifact.functions
.filter(f => f.functionType === FunctionType.SECRET)
.map(f => ({
selector: FunctionSelector.fromNameAndParameters(f.name, f.parameters),
vkHash: getVerificationKeyHash(f.verificationKey!),
isInternal: f.isInternal,
}))
.sort(cmpFunctionArtifacts);

const contractClass: ContractClass = {
version: 1,
artifactHash,
publicFunctions,
packedBytecode,
privateFunctions: artifact.functions
.filter(f => f.functionType === FunctionType.SECRET)
.map(f => ({
selector: FunctionSelector.fromNameAndParameters(f.name, f.parameters),
vkHash: getVerificationKeyHash(f.verificationKey!),
isInternal: f.isInternal,
})),
privateFunctions,
};
return { ...contractClass, ...computeContractClassIdWithPreimage(contractClass) };
}
Expand Down
5 changes: 2 additions & 3 deletions yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('e2e_dapp_subscription', () => {
bananaCoin = await BananaCoin.deploy(aliceWallet, aliceAddress, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS)
.send()
.deployed();
bananaFPC = await FPCContract.deploy(aliceWallet, bananaCoin.address, gasTokenContract.address).send().deployed();
bananaFPC = await FPCContract.deploy(aliceWallet, bananaCoin.address, AztecAddress.ZERO).send().deployed();

counterContract = await CounterContract.deploy(bobWallet, 0, bobAddress).send().deployed();

Expand All @@ -95,8 +95,7 @@ describe('e2e_dapp_subscription', () => {
// anyone can purchase a subscription for 100 test tokens
bananaCoin.address,
SUBSCRIPTION_AMOUNT,
// I had to pass this in because the address kept changing
gasTokenContract.address,
AztecAddress.ZERO,
)
.send()
.deployed();
Expand Down
14 changes: 14 additions & 0 deletions yarn-project/foundation/src/fields/fields.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,18 @@ describe('Bn254 arithmetic', () => {
expect(() => a.div(b)).toThrowError();
});
});

describe('Comparison', () => {
it.each([
[new Fr(5), new Fr(10), -1],
[new Fr(10), new Fr(5), 1],
[new Fr(5), new Fr(5), 0],
[new Fr(0), new Fr(Fr.MODULUS - 1n), -1],
[new Fr(Fr.MODULUS - 1n), new Fr(0), 1],
[Fr.ZERO, Fr.ZERO, 0],
[Fr.zero(), Fr.ZERO, 0],
])('Should compare field elements correctly', (a, b, expected) => {
expect(a.cmp(b)).toEqual(expected);
});
});
});
6 changes: 6 additions & 0 deletions yarn-project/foundation/src/fields/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ abstract class BaseField {
return this.toBigInt() < rhs.toBigInt();
}

cmp(rhs: BaseField): -1 | 0 | 1 {
const lhsBigInt = this.toBigInt();
const rhsBigInt = rhs.toBigInt();
return lhsBigInt === rhsBigInt ? 0 : lhsBigInt < rhsBigInt ? -1 : 1;
}

isZero(): boolean {
return this.toBuffer().equals(ZERO_BUFFER);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { ClassRegistererAddress, getCanonicalClassRegisterer } from './index.js'
describe('ClassRegisterer', () => {
it('returns canonical protocol contract', () => {
const contract = getCanonicalClassRegisterer();
contract.contractClass.privateFunctions.sort((a, b) => a.selector.value - b.selector.value);
contract.contractClass.publicFunctions.sort((a, b) => a.selector.value - b.selector.value);
expect(omit(contract, 'artifact')).toMatchSnapshot();
expect(contract.address.toString()).toEqual(ClassRegistererAddress.toString());
});
Expand Down
Loading
Loading