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

Random port on integrated devnet #202

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,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 @@ -343,8 +343,9 @@ More detailed documentation can be found [here](#account).

const { res: currBalance } = await account.call(contract, "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 account.call(contract, "get_balance");
expect(newBalance).to.deep.equal(currBalance + amount);
Expand Down Expand Up @@ -610,7 +611,7 @@ npm install --save-dev influenceth__cairo_math_64x61@npm:@influenceth/cairo-math

```typescript
paths: {
cairoPaths: ["./node_modules"]
cairoPaths: ["./node_modules"];
}
```

Expand Down Expand Up @@ -690,11 +691,11 @@ await contract.invoke("increase_balance", { amount: 1 }, { wallet });

Recompilation is performed when contracts are updated or when artifacts are missing. A file will be created with the name `cairo-files-cache.json` to handle caching. Recompilation is handled before the following [CLI commands](#cli-commands) are executed.

- `npx hardhat starknet-deploy`
- `npx hardhat starknet-invoke`
- `npx hardhat starknet-call`
- `npx hardhat run`
- `npx hardhat test`
- `npx hardhat starknet-deploy`
- `npx hardhat starknet-invoke`
- `npx hardhat starknet-call`
- `npx hardhat run`
- `npx hardhat test`

This feature is turned off by default and is specified in the `hardhat.config.ts` file.

Expand Down Expand Up @@ -784,6 +785,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{calls, invokes, fee estimations}.
Expand Down
2 changes: 1 addition & 1 deletion scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CONFIG_FILE_NAME="hardhat.config.ts"

# setup example repo
rm -rf starknet-hardhat-example
git clone -b plugin --single-branch [email protected]:Shard-Labs/starknet-hardhat-example.git
git clone -b release-0.7.0 --single-branch [email protected]:Shard-Labs/starknet-hardhat-example.git
cd starknet-hardhat-example
git log -n 1
npm install
Expand Down
17 changes: 17 additions & 0 deletions src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,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
4 changes: 3 additions & 1 deletion src/external-server/create-devnet-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import { DockerDevnet } from "./docker-devnet";
import { VenvDevnet } from "./venv-devnet";
import { ExternalServer } from "./external-server";

export function createIntegratedDevnet(hre: HardhatRuntimeEnvironment): ExternalServer {
export async function createIntegratedDevnet(
hre: HardhatRuntimeEnvironment
): Promise<ExternalServer> {
const devnetNetwork = getNetwork<HardhatNetworkConfig>(
INTEGRATED_DEVNET,
hre.config.networks,
Expand Down
3 changes: 2 additions & 1 deletion src/external-server/docker-devnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class DockerDevnet extends DockerServer {
}

protected async getContainerArgs(): Promise<string[]> {
return this.devnetArgs || [];
const containerArgs = this.devnetArgs || [];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the user provided --port in args in hardhat config?

return [...containerArgs, "--port", this.port];
}
}
2 changes: 1 addition & 1 deletion src/external-server/external-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function sleep(amountMillis: number): Promise<void> {
});
}

function isFreePort(port: number): Promise<boolean> {
export async function isFreePort(port: number): Promise<boolean> {
return new Promise((accept, reject) => {
const sock = net.createConnection(port);
sock.once("connect", () => {
Expand Down
5 changes: 1 addition & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,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
20 changes: 11 additions & 9 deletions src/task-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { getWalletUtil } from "./extend-utils";
import { createIntegratedDevnet } from "./external-server";
import { Recompiler } from "./recompiler";
import { version } from "../package.json";
import { getFreePort, isFreePort } from "./external-server/external-server";

function checkSourceExists(sourcePath: string): void {
if (!fs.existsSync(sourcePath)) {
Expand Down Expand Up @@ -343,14 +344,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 Expand Up @@ -560,7 +554,15 @@ async function runWithDevnet(hre: HardhatRuntimeEnvironment, fn: () => Promise<u
return;
}

const devnet = createIntegratedDevnet(hre);
const { hostname, port } = new URL(hre.config.starknet.networkUrl);
const isPortFree = await isFreePort(parseInt(port));
if (!isPortFree) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this check? Couldn't it surprise the user if we just silently change the specified port. If the port is occupied, integrated-devnet spawner will inform the user about that, right?

My understanding was that we should find a free port only if the user didn't provide a URL? Now I'm actually thinking, is it even possible for the user to omit the URL? Can the type extensions file be modified to allow that?

const newPort = await getFreePort();
const networkUrl = `http://${hostname}:${newPort}`;
hre.config.networks.integratedDevnet.url = networkUrl;
hre.config.starknet.networkUrl = networkUrl;
}
const devnet = await createIntegratedDevnet(hre);

await devnet.start();
await fn();
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ export interface InvokeOptions {
wallet?: Wallet;
nonce?: Numeric;
maxFee?: Numeric;
overhead?: number;
}

export interface CallOptions {
Expand Down
2 changes: 1 addition & 1 deletion test/general-tests/starknet-verify/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ echo "Verifying contract at $address"
echo "Sleeping to allow Voyager to index the deployment"
sleep 1m

npx hardhat starknet-verify --starknet-network "$NETWORK" --path $MAIN_CONTRACT $UTIL_CONTRACT --address $address --compiler-version 0.9.0 --license "No License (None)" --account-contract false
npx hardhat starknet-verify --starknet-network "$NETWORK" --path $MAIN_CONTRACT $UTIL_CONTRACT --address $address --compiler-version 0.9.0 --license "No License (None)"
echo "Sleeping to allow Voyager to register the verification"
sleep 15s

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@ starknet-devnet --host 127.0.0.1 --port 5050 --accounts 0 &

npx hardhat starknet-compile contracts/contract.cairo

npx hardhat test --no-compile test/integrated-devnet.test.ts 2>&1 |
../scripts/assert-contains.py "127.0.0.1:5050 already occupied."
npx hardhat test --no-compile test/integrated-devnet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ starknet-devnet --host 127.0.0.1 --port 5050 --accounts 0 &

npx hardhat starknet-compile contracts/contract.cairo

npx hardhat test --no-compile test/integrated-devnet.test.ts 2>&1 |
../scripts/assert-contains.py "127.0.0.1:5050 already occupied."
npx hardhat test --no-compile test/integrated-devnet.test.ts