Skip to content

Commit

Permalink
Allow fallback ABI resolution for contract initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
penovicp committed Dec 13, 2023
1 parent 8c7fd79 commit 861ef94
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 37 deletions.
5 changes: 0 additions & 5 deletions src/extend-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ export async function getContractFactoryUtil(hre: HardhatRuntimeEnvironment, con
`${path.basename(contractPath)}${ABI_SUFFIX}`
);
const abiPath = await findPath(artifactsPath, abiSearchTarget);
if (!abiPath) {
throw new StarknetPluginError(
`Could not find ABI JSON artifact for "${contractPath}.cairo". Consider recompiling your contracts.`
);
}

return new StarknetContractFactory({
metadataPath,
Expand Down
69 changes: 45 additions & 24 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import {
CallData,
DeclareContractTransaction,
InvocationsDetailsWithNonce,
LegacyContractClass,
ProviderInterface,
SequencerProvider,
SierraContractClass,
events as eventUtil,
hash,
json,
Expand All @@ -23,15 +25,7 @@ import {
} from "../constants";
import { StarknetPluginError } from "../starknet-plugin-error";
import * as starknet from "../starknet-types";
import {
adaptLog,
copyWithBigint,
findConstructor,
readContractAsync,
readContractSync,
sleep,
warn
} from "../utils";
import { adaptLog, copyWithBigint, findConstructor, readContractSync, sleep, warn } from "../utils";

/**
* According to: https://starknet.io/docs/hello_starknet/intro.html#interact-with-the-contract
Expand Down Expand Up @@ -65,17 +59,25 @@ export type TxStatus =
export type InvokeResponse = string;

export type StarknetContractFactoryConfig = {
abiPath: string;
abiPath?: string;
casmPath?: string;
metadataPath: string;
hre: HardhatRuntimeEnvironment;
};

export interface StarknetContractConfig {
abiPath: string;
export type StarknetContractConfig = {
hre: HardhatRuntimeEnvironment;
isCairo1: boolean;
}
} & (
| {
abiPath: string;
abiRaw?: undefined;
}
| {
abiPath?: undefined;
abiRaw: string;
}
);

export type Numeric = number | bigint;

Expand Down Expand Up @@ -202,6 +204,15 @@ function readAbi(abiPath: string): string {
return hash.formatSpaces(fs.readFileSync(abiPath).toString("ascii").trim());
}

/**
* Extracts the ABI from the contract
*/
function getFallbackAbi(contract: LegacyContractClass | SierraContractClass): string {
return hash.formatSpaces(
typeof contract.abi === "string" ? contract.abi : json.stringify(contract.abi)
);
}

/**
* Converts `rawAbi` to an object for lookup by name
*/
Expand Down Expand Up @@ -359,19 +370,26 @@ export type SierraContractEntryPointFields = {
export type NonceQueryOptions = BlockIdentifier;

export class StarknetContractFactory {
private classHash: string;
private constructorAbi: starknet.CairoFunction;
private contract: LegacyContractClass | SierraContractClass;
private hre: HardhatRuntimeEnvironment;

public abi: starknet.Abi;
public abiPath: string;
public abiPath?: string;
public abiRaw: string;
private constructorAbi: starknet.CairoFunction;
public metadataPath: string;
public casmPath: string;
private classHash: string;

constructor(config: StarknetContractFactoryConfig) {
this.hre = config.hre;
this.metadataPath = config.metadataPath;
this.contract = providerUtil.parseContract(readContractSync(this.metadataPath));

this.abiPath = config.abiPath;
this.abiRaw = readAbi(this.abiPath);
this.abiRaw = this.abiPath
? readAbi(this.abiPath)
: getFallbackAbi(this.retrieveContract());
this.abi = mapAbi(this.abiRaw);
this.metadataPath = config.metadataPath;
this.casmPath = config.casmPath;
Expand Down Expand Up @@ -412,17 +430,19 @@ export class StarknetContractFactory {
};
}

private retrieveContract() {
this.contract ??= providerUtil.parseContract(readContractSync(this.metadataPath));
return this.contract;
}

/**
* Declare a contract class.
* @param options optional arguments to class declaration
* @returns transaction hash as a hex string
*/
async declare(options: DeclareOptions = {}): Promise<string> {
const contractJson = await readContractAsync(this.metadataPath);
const contract = providerUtil.parseContract(contractJson);

const transaction: DeclareContractTransaction = {
contract,
contract: this.retrieveContract(),
senderAddress: options.sender,
signature: handleSignature(options.signature)
};
Expand Down Expand Up @@ -485,6 +505,7 @@ export class StarknetContractFactory {
}
const contract = new StarknetContract({
abiPath: this.abiPath,
abiRaw: this.abiRaw as undefined,
hre: this.hre,
isCairo1: this.isCairo1()
});
Expand Down Expand Up @@ -521,7 +542,7 @@ export class StarknetContract {
constructor(config: StarknetContractConfig) {
this.hre = config.hre;
this.abiPath = config.abiPath;
this.abiRaw = readAbi(this.abiPath);
this.abiRaw = config.abiRaw ?? readAbi(this.abiPath);
this.abi = mapAbi(this.abiRaw);
this.isCairo1 = config.isCairo1;
this.eventsSpecifications = extractEventSpecifications(this.abi);
Expand Down Expand Up @@ -786,11 +807,11 @@ export class StarknetContract {
}
}

export interface ContractClassConfig extends StarknetContractConfig {
export type ContractClassConfig = StarknetContractConfig & {
sierraProgram: string;
contractClassVersion: string;
entryPointsByType: SierraEntryPointsByType;
}
};

export class Cairo1ContractClass extends StarknetContract {
protected sierraProgram: string;
Expand Down
11 changes: 3 additions & 8 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,7 @@ import {
} from "hardhat/types";
import fs, { promises as fsp } from "node:fs";
import path from "node:path";
import {
CompiledSierra,
LegacyCompiledContract,
hash,
json,
stark
} from "starknet";
import { CompiledSierra, LegacyCompiledContract, hash, json, stark } from "starknet";

import { handleInternalContractArtifacts } from "./account-utils";
import {
Expand Down Expand Up @@ -326,13 +320,14 @@ export function readContract(contractPath: string) {

export function readCairo1Contract(contractPath: string) {
const parsedContract = readContractSync(contractPath) as CompiledSierra;
const { contract_class_version, entry_points_by_type, sierra_program } = parsedContract;
const { abi, contract_class_version, entry_points_by_type, sierra_program } = parsedContract;

const contract = new Cairo1ContractClass({
abiPath: path.join(
path.dirname(contractPath),
`${path.parse(contractPath).name}${ABI_SUFFIX}`
),
abiRaw: hash.formatSpaces(json.stringify(abi)),
sierraProgram: stark.compressProgram(hash.formatSpaces(json.stringify(sierra_program))),
entryPointsByType: entry_points_by_type,
contractClassVersion: contract_class_version
Expand Down

0 comments on commit 861ef94

Please sign in to comment.