@solidstate/hardhat-4byte-uploader
Version:
Upload local function selectors to the Ethereum Selector Database
67 lines (56 loc) • 2.05 kB
text/typescript
import { name as pluginName } from '../../package.json';
import axios from 'axios';
import { TASK_COMPILE } from 'hardhat/builtin-tasks/task-names';
import { task } from 'hardhat/config';
import { HardhatPluginError } from 'hardhat/plugins';
const API_ENDPOINT = 'https://www.4byte.directory/api/v1/import-abi/';
task(
'upload-selectors',
'Upload local function selectors to the Ethereum Selector Database',
)
.addFlag('noCompile', "Don't compile before running this task")
.setAction(async (args, hre) => {
if (!args.noCompile) {
await hre.run(TASK_COMPILE);
}
const fullNames = await hre.artifacts.getAllFullyQualifiedNames();
const elements: { [key: string]: any } = {};
await Promise.all(
fullNames.map(async (fullName) => {
const { abi } = await hre.artifacts.readArtifact(fullName);
for (let element of abi) {
elements[JSON.stringify(element)] = element;
}
}),
);
const compositeAbi = Object.values(elements).filter((el) => {
return (
el.type === 'function' || el.type === 'event' || el.type === 'error'
);
});
compositeAbi.forEach((el) => {
// We convert all errors to 'function' type, since 4byte.directory does not support ABIs that include errors and both types are encoded in the same way.
if (el.type === 'error') {
el.type = 'function';
el.outputs = [];
}
});
try {
const { data } = await axios.post(API_ENDPOINT, {
contract_abi: JSON.stringify(compositeAbi),
});
console.log(
`Processed ${data.num_processed} unique items from ${fullNames.length} ABIs`,
);
console.log(
`Added ${data.num_imported} selectors to 4byte.directory database`,
);
console.log(`Found ${data.num_duplicates} duplicates`);
console.log(`Ignored ${data.num_ignored} items`);
} catch (e) {
throw new HardhatPluginError(
pluginName,
'failed to upload selectors to 4byte.directory',
);
}
});