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

Introduce some breaking changes for 0.7.0 #199

Merged
merged 13 commits into from
Dec 2, 2022
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ You would typically use the input feature when deploying a single contract requi
### `starknet-verify`

```
npx hardhat starknet-verify [--starknet-network <NAME>] [--path <PATH>] [<DEPENDENCY_PATH> ...] [--address <CONTRACT_ADDRESS>] [--compiler-version <COMPILER_VERSION>] [--license <LICENSE_SCHEME>] [--contract-name <CONTRACT_NAME>] [--acount-contract <BOOLEAN>]
npx hardhat starknet-verify [--starknet-network <NAME>] [--path <PATH>] [<DEPENDENCY_PATH> ...] [--address <CONTRACT_ADDRESS>] [--compiler-version <COMPILER_VERSION>] [--license <LICENSE_SCHEME>] [--contract-name <CONTRACT_NAME>] [--acount-contract]
```

Queries [Voyager](https://voyager.online/) to [verify the contract](https://voyager.online/verifyContract) deployed at `<CONTRACT_ADDRESS>` using the source files at `<PATH>` and any number of `<DEPENDENCY_PATH>`.
Expand Down Expand Up @@ -369,8 +369,9 @@ More detailed documentation can be found [here](#account).

const { res: currBalance } = await contract.call("get_balance");
const amount = BigInt(10);
// Passing max_fee is currently optional
await account.invoke(contract, "increase_balance", { amount }, { maxFee: BigInt("123") });

// Read more about max fee specification under # Funds and fees
await account.invoke(contract, "increase_balance", { amount }, { maxFee: BigInt("1000000000") });

const { res: newBalance } = await contract.call("get_balance");
expect(newBalance).to.deep.equal(currBalance + amount);
Expand Down Expand Up @@ -419,7 +420,7 @@ it("should return transaction data and transaction receipt", async function () {
const txHash = await account.invoke(contract, "increase_balance", { amount: 10 });

const receipt = await starknet.getTransactionReceipt(txHash);
const decodedEvents = await contract.decodeEvents(receipt.events);
const decodedEvents = contract.decodeEvents(receipt.events);
// decodedEvents contains hex data array converted to a structured object
// { name: "increase_balance_called", data: { current_balance: 0n, amount: 10n } }
});
Expand Down Expand Up @@ -814,6 +815,13 @@ Once your account has funds, you can specify a max fee greater than zero:
await account.invoke(contract, "foo", { arg1: ... }, { maxFee: BigInt(...) });
```

If you don't specify a `maxFee`, one will be calculated for you by applying an overhead of 50% to the result of fee estimation. You can also customize the overhead by providing a value for `overhead`:

```typescript
// maxFee will be 40% of estimated fee; if overhead not provided, a default value is used.
await account.invoke(contract, "foo", { arg1: ... }, { overhead: 0.4 );
```

### Multicalls

You can also use the Account object to perform multi{invokes, fee estimations}.
Expand Down
2 changes: 1 addition & 1 deletion scripts/ensure-python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Ensures that pyenv uses the desired Python version (on Linux).

set -e
set -eu

PY_VERSION=3.8.9

Expand Down
2 changes: 1 addition & 1 deletion scripts/install-devnet.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

set -e
set -eu

pip3 install "starknet-devnet==$STARKNET_DEVNET"
STARKNET_DEVNET_PATH=$(which starknet-devnet)
Expand Down
2 changes: 1 addition & 1 deletion scripts/npm-publish.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -eu

LOCAL_VERSION=$(jq -r ".version" package.json)
NPM_VERSION=$(npm view @shardlabs/starknet-hardhat-plugin dist-tags.latest)
Expand Down
8 changes: 1 addition & 7 deletions scripts/setup-venv.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

set -e
set -eu

VENV=../my-venv

Expand All @@ -15,14 +15,8 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
brew ls --versions gmp || brew install gmp
fi

if [ -z "$TEST_SUBDIR" ]; then
echo "Missing TEST_SUBDIR env var"
exit 1
fi

if [ "$TEST_SUBDIR" == "venv-tests" ]; then
which "$VENV/bin/starknet" || pip3 install cairo-lang=="$(cat /tmp/cairo-lang-version)"
echo "starknet at: $(which starknet)"
echo "starknet version: $(starknet --version)"
fi

4 changes: 2 additions & 2 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -eu

trap 'for killable in $(jobs -p); do kill -9 $killable; done' EXIT

Expand Down Expand Up @@ -72,7 +72,7 @@ function iterate_dir() {
# check if test_case/check.ts exists
if [ -f "$test_case/check.ts" ]; then
# run the test
NETWORK="$network" npx mocha -r ts-node/register "$test_case/check.ts" && success=$((success + 1)) || echo "Test failed!"
NETWORK="$network" npx ts-node "$test_case/check.ts" && success=$((success + 1)) || echo "Test failed!"
fi

rm -rf starknet-artifacts
Expand Down
2 changes: 1 addition & 1 deletion scripts/versions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Logs used versions

set -e
set -eu

echo "node: $(node --version)"
echo "npm: $(npm --version)"
Expand Down
17 changes: 17 additions & 0 deletions src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ export abstract class Account {
calldata?: StringMap,
options?: InvokeOptions
): Promise<InvokeResponse> {
if (options?.maxFee && options?.overhead) {
const msg = "Both maxFee and overhead cannot be specified";
throw new StarknetPluginError(msg);
}

if (options?.maxFee === undefined || options?.maxFee === null) {
let overhead =
options?.overhead === undefined || options?.overhead === null
? 0.5
: options?.overhead;
overhead = Math.round((1 + overhead) * 100);
const maxFee = await this.estimateFee(toContract, functionName, calldata, options);
options = {
...options,
maxFee: (maxFee.amount * BigInt(overhead)) / BigInt(100)
};
}
return (
await this.interact(InteractChoice.INVOKE, toContract, functionName, calldata, options)
).toString();
Expand Down
5 changes: 1 addition & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,7 @@ task("starknet-verify", "Verifies a contract on a Starknet network.")
.addParam("path", "The path of the main cairo contract (e.g. contracts/contract.cairo)")
.addParam("address", "The address where the contract is deployed")
.addParam("compilerVersion", "The compiler version used to compile the cairo contract")
.addOptionalParam(
"accountContract",
"The contract type which specifies whether it's an account contract. Omitting it sets false."
)
.addFlag("accountContract", "The contract type which specifies it's an account contract.")
.addOptionalParam("license", "The licence of the contract (e.g No License (None))")
.addOptionalVariadicPositionalParam(
"paths",
Expand Down
9 changes: 1 addition & 8 deletions src/task-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,7 @@ async function handleContractVerification(

const bodyFormData = new FormData();
bodyFormData.append("compiler-version", args.compilerVersion);
let accountContract;
if (args.accountContract === "true") {
accountContract = "true";
} else if (!args.accountContract || args.accountContract === "false") {
accountContract = "false";
} else {
throw new StarknetPluginError("--account-contract must be true or false");
}
const accountContract = args.accountContract ? "true" : "false";
bodyFormData.append("account-contract", accountContract);
bodyFormData.append("license", args.license || "No License (None)");

Expand Down
8 changes: 7 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ export interface InvokeOptions {
wallet?: Wallet;
nonce?: Numeric;
maxFee?: Numeric;
overhead?: number;
}

export interface CallOptions {
Expand Down Expand Up @@ -752,9 +753,10 @@ export class StarknetContract {
* @param events as received from the server.
* @returns structured object with parameter names.
*/
async decodeEvents(events: starknet.Event[]): Promise<DecodedEvent[]> {
decodeEvents(events: starknet.Event[]): DecodedEvent[] {
const decodedEvents: DecodedEvent[] = [];
for (const event of events) {
if (parseInt(event.from_address, 16) !== parseInt(this.address, 16)) continue;
const rawEventData = event.data.map(BigInt).join(" ");
// encoded event name guaranteed to be at index 0
const eventSpecification = this.eventsSpecifications[event.keys[0]];
Expand All @@ -767,6 +769,10 @@ export class StarknetContract {
decodedEvents.push({ name: eventSpecification.name, data: adapted });
}

if (decodedEvents.length === 0) {
const msg = `No events were decoded. You might be using a wrong contract.\nABI used for decoding: ${this.abiPath}`;
throw new StarknetPluginError(msg);
}
return decodedEvents;
}
}
1 change: 1 addition & 0 deletions test/configuration-tests/with-networks/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ assertContains(execution.stderr, expected);
console.log("Success");

console.log("Testing with alpha-goerli2 config network");
process.env.NETWORK = "alpha-goerli2";
hardhatStarknetDeploy(
"starknet-artifacts/contracts/contract.cairo --starknet-network alpha-goerli2 --inputs 10".split(
" "
Expand Down
2 changes: 1 addition & 1 deletion test/general-tests/cairo-migrate/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ copyFileSync(path.join(__dirname, contractName), contractPath);

console.log("Testing migration of old cairo contract to a new one");
// Migrate contract to new version.
const execution = hardhatStarknetMigrate([contractPath], true);
const execution = hardhatStarknetMigrate([contractPath]);
assertContains(execution.stdout, newComment);

// Migrate contract to new version with change content in place option.
Expand Down
4 changes: 1 addition & 3 deletions test/general-tests/starknet-call/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ hardhatStarknetCompile(["contracts/contract.cairo"]);
const output = hardhatStarknetDeploy(
`--starknet-network ${network} starknet-artifacts/contracts/contract.cairo/ --inputs 10`.split(
" "
),
true
)
);
console.log(output.stdout);

const address = extractAddress(output.stdout, "Contract address: ");
const prefix = path.join(__dirname);
Expand Down
12 changes: 9 additions & 3 deletions test/general-tests/starknet-verify/check.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { assertEqual, ensureEnvVar, exec, extractAddress } from "../../utils/utils";
import { hardhatStarknetCompile, hardhatStarknetDeploy } from "../../utils/cli-functions";
import {
hardhatStarknetCompile,
hardhatStarknetDeploy,
hardhatStarknetVerify
} from "../../utils/cli-functions";
import axios from "axios";

console.log(
Expand All @@ -24,8 +28,10 @@ console.log("Verifying contract at $address");
console.log("Sleeping to allow Voyager to index the deployment");
exec("sleep 1m");

exec(
`npx hardhat starknet-verify --starknet-network ${network} --path ${mainContract} ${utilContract} --address ${address} --compiler-version 0.9.0 --license "No License (None)" --account-contract false`
hardhatStarknetVerify(
`--starknet-network ${network} --path ${mainContract} ${utilContract} --address ${address} --compiler-version 0.9.0 --license "No License (None)"`.split(
" "
)
);
console.log("Sleeping to allow Voyager to register the verification");
exec("sleep 15s");
Expand Down
5 changes: 1 addition & 4 deletions test/integrated-devnet-tests/with-stderr-to-STDERR/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import { hardhatStarknetCompile, hardhatStarknetTest } from "../../utils/cli-fun
"WARNING: Use these accounts and their keys ONLY for local testing. DO NOT use them on mainnet or other live networks because you will LOSE FUNDS.";

hardhatStarknetCompile(["contracts/contract.cairo"]);
const execution = hardhatStarknetTest(
"--no-compile test/integrated-devnet.test.ts".split(" "),
true
);
const execution = hardhatStarknetTest("--no-compile test/integrated-devnet.test.ts".split(" "));
assertContains(execution.stderr, expectedWarning);

// Checks if file logs/stderr.log exists and contains the expected warning string
Expand Down
58 changes: 35 additions & 23 deletions test/utils/cli-functions.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,60 @@
import shell from "shelljs";
import { assertEqual, assertNotEqual } from "./utils";

const exec = (cmd: string, silent?: boolean) => {
silent = silent || false;
return shell.exec(cmd, { silent: silent });
export function exec(cmd: string, expectFailure = false) {
const result = shell.exec(cmd, { silent: expectFailure });
const msg = `Command ${cmd} failed.\n${result.stderr}`;
if (!expectFailure) {
assertEqual(result.code, 0, msg);
} else {
assertNotEqual(result.code, 0, msg);
}

return result;
}

export const hardhatStarknetCompile = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-compile ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetCompile = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-compile ${args.join(" ")}`, silent);
export const hardhatStarknetDeploy = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-deploy ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetDeploy = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-deploy ${args.join(" ")}`, silent);
export const hardhatStarknetInvoke = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-invoke ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetInvoke = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-invoke ${args.join(" ")}`, silent);
export const hardhatStarknetCall = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-call ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetCall = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-call ${args.join(" ")}`, silent);
export const hardhatStarknetEstimateFee = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-estimate-fee ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetEstimateFee = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-estimate-fee ${args.join(" ")}`, silent);
export const hardhatStarknetNewAccount = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-new-account ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetNewAccount = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-new-account ${args.join(" ")}`, silent);
export const hardhatStarknetDeployAccount = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-deploy-account ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetDeployAccount = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat starknet-deploy-account ${args.join(" ")}`, silent);
export const hardhatStarknetRun = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat run ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetRun = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat run ${args.join(" ")}`, silent);
export const hardhatStarknetTest = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat test ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetTest = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat test ${args.join(" ")}`, silent);
export const hardhatStarknetVerify = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat starknet-verify ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetMigrate = (args: Array<string>, silent?: boolean) => {
return exec(`npx hardhat migrate ${args.join(" ")}`, silent);
export const hardhatStarknetMigrate = (args: Array<string>, expectFailure = false) => {
return exec(`npx hardhat migrate ${args.join(" ")}`, expectFailure);
};

export const hardhatStarknetPluginVersion = () => {
Expand Down
8 changes: 5 additions & 3 deletions test/utils/deploy-funded-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ export async function deployFundedAccount(url = DEVNET_URL) {
.address;

console.log(`Funding account ${accountAddress} on ${network}.`);
await axios.post(`${url}/mint`, {
const data = {
address: accountAddress,
amount: 1000000000000000000n,
amount: 10 ** 18,
lite: true
});
};

await axios.post(`${url}/mint`, data);

// Deploying funded account on the network
hardhatStarknetDeployAccount(args);
Expand Down