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

Updated starknet-verify action #68

Merged
merged 4 commits into from
Mar 3, 2022
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
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,14 @@ extendEnvironment((hre) => {

task("starknet-verify", "Verifies the contract in the Starknet network.")
.addOptionalParam("starknetNetwork", "The network version to be used (e.g. alpha)")
.addParam("path", "The path of the cairo contract (e.g. contracts/conract.cairo)")
.addParam("path", "The path of the main cairo contract (e.g. contracts/contract.cairo)")
.addParam("address", "The address where the contract is deployed")
.addOptionalVariadicPositionalParam(
"paths",
"The paths of the dependencies of the contract specified in --path" +
"All dependencies should be in the same folder as the contract." +
"e.g. path/to/dependency1 path/to/dependency2"
)
.setAction(starknetVoyagerAction);

task("starknet-invoke", "Invokes a function on a contract in the provided address.")
Expand Down
105 changes: 74 additions & 31 deletions src/task-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,51 +278,94 @@ export async function starknetVoyagerAction(args: TaskArguments, hre: HardhatRun
});
const data = resp.data;

if (data.contract != null && data.contract.length > 0) {
isVerified = true;
if (data.contract) {
if (data.contract.length > 0 || Object.keys(data.contract).length > 0) {
isVerified = true;
}
}
} catch (error) {
const msg = `Something went wrong when trying to verify the code at address ${args.address}`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}

if (isVerified) {
const msg = `Contract at address ${args.address} has already been verified`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
console.log(`Contract at address ${args.address} has already been verified`);
} else {
await handleContractVerification(args, voyagerUrl, hre);
}
//If contract hasn't been verified yet, do it
}

async function handleContractVerification(
args: TaskArguments,
voyagerUrl: string,
hre: HardhatRuntimeEnvironment
) {
// Set main contract path
let contractPath = args.path;
if (!path.isAbsolute(contractPath)) {
contractPath = path.normalize(path.join(hre.config.paths.root, contractPath));
if (!fs.existsSync(contractPath)) {
throw new HardhatPluginError(PLUGIN_NAME, `File ${contractPath} does not exist`);
}
}
if (fs.existsSync(contractPath)) {
const content = {
code: fs
.readFileSync(contractPath)
.toString()
.split(/\r?\n|\r/)
};
await axios.post(voyagerUrl, JSON.stringify(content)).catch((error) => {
switch (error.response.status) {
case 400: {
const msg = `Contract at address ${args.address} does not match the provided code`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}
case 500: {
const msg = `There is no contract deployed at address ${args.address}, or the transaction was not finished`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}
default: {
const msg = `Something went wrong when trying to verify the code at address ${args.address}`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}
}
});
console.log(`Contract has been successfuly verified at address ${args.address}`);
return;
// The other option for the formData would be to add a new dependency 'form-data', but the URLSearchParams works exactly the same
const bodyFormData = new URLSearchParams();
dribeiro-ShardLabs marked this conversation as resolved.
Show resolved Hide resolved
bodyFormData.append("contract-name", path.parse(contractPath).base);

// If the contract has dependencies, insert them into the form
if (args.paths) {
dribeiro-ShardLabs marked this conversation as resolved.
Show resolved Hide resolved
handleMultiPartContractVerification(bodyFormData, contractPath, args, hre);
} else {
throw new HardhatPluginError(PLUGIN_NAME, `File ${contractPath} does not exist`);
handleSingleContractVerification(bodyFormData, contractPath);
}

await axios.post(voyagerUrl, bodyFormData).catch((error) => {
switch (error.response.status) {
case 400: {
const msg = `Contract at address ${args.address} does not match the provided code`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}
case 500: {
const msg = `There is no contract deployed at address ${args.address}, or the transaction was not finished`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}
default: {
const msg = `Something went wrong when trying to verify the code at address ${args.address}`;
throw new HardhatPluginError(PLUGIN_NAME, msg);
}
}
});
console.log(`Contract has been successfuly verified at address ${args.address}`);
}

function handleSingleContractVerification(bodyFormData: URLSearchParams, contractPath: string) {
const file = fs.readFileSync(contractPath);
const fileContent = file.toString().split(/\r?\n|\r/);
bodyFormData.append("code", JSON.stringify(fileContent));
}

function handleMultiPartContractVerification(
bodyFormData: URLSearchParams,
contractPath: string,
args: TaskArguments,
hre: HardhatRuntimeEnvironment
) {
bodyFormData.append("filename", path.parse(contractPath).base);
bodyFormData.append("file", fs.readFileSync(contractPath).toString());

args.paths.forEach(function (item: string, index: number) {
if (!path.isAbsolute(item)) {
args.paths[index] = path.normalize(path.join(hre.config.paths.root, item));
if (!fs.existsSync(args.paths[index])) {
throw new HardhatPluginError(
PLUGIN_NAME,
`File ${args.paths[index]} does not exist`
);
}
bodyFormData.append("filename", path.parse(args.paths[index]).base);
bodyFormData.append("file", fs.readFileSync(args.paths[index]).toString());
}
});
}

export async function starknetInvokeAction(args: TaskArguments, hre: HardhatRuntimeEnvironment) {
Expand Down
21 changes: 16 additions & 5 deletions test/general-tests/starknet-verify/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,24 @@ set -e
echo "The starknet-verify test is temporarily disabled."
echo "To enable it back, uncomment the lines in its check.sh."

# npx hardhat starknet-compile contracts/util.cairo
### The util contract is only being compiled with the purpose of testing a Single part contract verification, as it does not have any dependencies
# npx hardhat starknet-compile contracts/contract.cairo contracts/util.cairo
dribeiro-ShardLabs marked this conversation as resolved.
Show resolved Hide resolved

# output=$(npx hardhat starknet-deploy --starknet-network "$NETWORK" starknet-artifacts/contracts/util.cairo/)
# echo $output
# address=$(echo $output | sed -r "s/.*Contract address: (\w*).*/\1/")
# util_address=$(echo $output | sed -r "s/.*Contract address: (\w*).*/\1/")
# echo "Util contract address: $util_address"

# output=$(npx hardhat starknet-deploy --starknet-network "$NETWORK" starknet-artifacts/contracts/contract.cairo/)
# main_address=$(echo $output | sed -r "s/.*Contract address: (\w*).*/\1/")
# echo "Main contract address: $main_address"

# echo "Address: $address"

# sleep 5m

# npx hardhat starknet-verify --starknet-network "$NETWORK" --path contracts/util.cairo --address $address
### Single contract verification

# npx hardhat starknet-verify --starknet-network "$NETWORK" --path contracts/util.cairo --address $util_address

### Multi part contract verification

# npx hardhat starknet-verify --starknet-network "$NETWORK" --path contracts/contract.cairo --address $main_address contracts/util.cairo