Merge pull request #6 from embarklabs/feat/lib

Make verifier usable as a library
This commit is contained in:
Jonathan Rainville 2021-11-16 09:43:51 -05:00 committed by GitHub
commit 1cef9b67b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 27 deletions

View File

@ -1,9 +1,9 @@
Embark-etherscan-verifier
======
Plugin for [Embark](https://github.com/embark-framework/embark) to flatten and verify contracts on Etherscan
Plugin for [Embark](https://github.com/embark-framework/embark) and library to flatten and verify contracts on Etherscan.
## Installation
## Plugin installation
In your Embark dapp directory:
@ -19,16 +19,16 @@ then add embark-etherscan-verifier to the plugins section in `embark.json`:
}
```
## Usage
### Usage
### Flatten
#### Flatten
In the console, type `flatten` or `flatten ContractName(s)`
- `flatten`: Flattens all contracts
- `flatten ContractName(s)`: Flattens the specified contract(s). For multiple contracts, separate them using a comma.
- Example: `flatten SimpleStorage,Token`
### Verify
#### Verify
You can also automatically verify on a valid network (mainnet, ropsten, rinkeby, kovan)
In the console:
@ -37,7 +37,44 @@ In the console:
- You need an Etherscan API key. You can find a simple tutorial [here](https://etherscancom.freshdesk.com/support/solutions/articles/35000022163-i-need-an-api-key)
- Example: `verify YOUR_KEY SimpleStorage`
## Requirements
### Requirements
- Embark 4.0.0 or higher
## Library usage
You can use the flattener and verifier standalone.
```
import FlattenerVerifier from 'embark-etherscan-verifier/lib/FlattenerVerifier`;
const flattenerVerifier = new FlattenerVerifier({
optimize: true,
optimizeRuns: 200,
contractsFiles: [...],
solcVersion: '0.5.2',
getWeb3DeployObject: (contract, cb) => {},
getAllContracts: (cb) => {},
getContractByName: (contractName, cb) => {},
getNetworkId: (cb) => {}
});
```
### Parameters
- `optimize`: bool: if the contract is optimized
- `optimizeRuns`: int: Number of optimize passes
- `contractsFiles`: Array of contract files objects. Must contain:
- `originalPath`: Original path to the contract (relative path)
- `path`: Absolute path to the contract object
- `importRemappings`: Array of remapping objects (for imports). Must contain:
- `target`: Absolute path to the imported contract
- `solcVersion`: string: solc version used to compile
- `getWeb3DeployObject`: Function to get a [web3 deploy object](https://web3js.readthedocs.io/en/v1.2.0/web3-eth-contract.html#deploy)
- `getAllContracts`: Function that returns all contract objects. Contract object must contain: linkReferences(from solc output contract.evm.bytecode.linkReferences)}
- `className`: string: Class name of the contract
- `originalFilename`: string: Original file name of the file (relative path)
- `filename`: string: Complete absolute file path
- `deployedAddress`: string: Address where the contract is deployed
- `linkReferences`: object: Library link references. You can get it from the solc output as `contract.evm.bytecode.linkReferences`
- `getContractByName`: Function to get a contract object by name. Contains the same as all contracts above
- `getNetworkId`: Function that returns the current networkId

View File

@ -3,9 +3,32 @@
const FlattenerVerifier = require('./lib/FlattenerVerifier');
module.exports = (embark) => {
const flattenerVerifier = new FlattenerVerifier(embark);
function createVerifier() {
return new FlattenerVerifier({
optimize: embark.config.embarkConfig.options.solc.optimize,
optimizeRuns: embark.config.embarkConfig.options.solc['optimize-runs'],
contractsFiles: embark.config.contractsFiles,
solcVersion: embark.config.embarkConfig.versions.solc,
getWeb3DeployObject: (contract, cb) => {
embark.events.request('deploy:contract:object', contract, cb);
},
getAllContracts: (cb) => {
embark.events.request('contracts:all', cb);
},
getContractByName: (contractName, cb) => {
embark.events.request("contracts:contract", contractName, (contract) => {
cb(null, contract);
});
},
getNetworkId: (cb) => {
embark.events.request("blockchain:networkId", (networkId) => {
cb(null, networkId);
});
}
});
}
embark.registerConsoleCommand({
embark.registerConsoleCommand({
description: "Flattens all or some of your contracts so that they can be verified on Etherscan\n\t\tYou can specify which contract to flatten by using their contract name. For multiple contracts, separate them using a comma",
matches: (cmd) => {
const [commandName] = cmd.split(' ');
@ -21,8 +44,7 @@ module.exports = (embark) => {
embark.logger.info('Flattening all contracts');
}
flattenerVerifier.flatten(contractNames, callback);
createVerifier().flatten(contractNames, callback);
}
});
@ -47,7 +69,7 @@ module.exports = (embark) => {
return callback(null, 'solc version not present in embarkjs.json. Please add it to versions.solc'.red);
}
flattenerVerifier.verify(apiKey, contractName, callback);
createVerifier().verify(apiKey, contractName, callback);
}
});
};

View File

@ -26,10 +26,9 @@ function sleep(ms) {
}
class FlattenerVerifier {
constructor(embark) {
this.embark = embark;
this.events = embark.events;
this.logger = embark.logger;
constructor(options) {
this.options = options;
this.logger = options.logger || console;
}
_doFlatten(contracts, callback) {
@ -103,7 +102,10 @@ class FlattenerVerifier {
libNames = Array.from(new Set(libNames));
async.eachOf(libNames, (libName, index, eachCb) => {
this.events.request("contracts:contract", libName, (lib) => {
this.options.getContractByName(libName, (err, lib) => {
if (err) {
return eachCb(err);
}
if (!this._isContractValid(lib, libName)) {
return eachCb('Make sure the library is not set as `deploy: false`');
}
@ -131,11 +133,11 @@ class FlattenerVerifier {
sourceCode: flattenedCode,
contractname: contract.className,
compilerversion: solcVersion,
optimizationUsed: this.embark.config.embarkConfig.options.solc.optimize ? 1 : 0,
runs: this.embark.config.embarkConfig.options.solc['optimize-runs']
optimizationUsed: this.options.optimize ? 1 : 0,
runs: this.options.optimizeRuns
};
this.events.request('deploy:contract:object', contract, (err, deployObject) => {
this.options.getWeb3DeployObject(contract, (err, deployObject) => {
if (err) {
return callback(err);
}
@ -219,7 +221,10 @@ class FlattenerVerifier {
}
verify(apiKey, contractName, callback) {
this.events.request("contracts:contract", contractName, (contract) => {
this.options.getContractByName(contractName, (err, contract) => {
if (err) {
return callback(err);
}
if (!this._isContractValid(contract, contractName)) {
return callback(null, 'Please make sure you specify the contract name as the class name. E.g. SimpleStorage instead of simple_storage.sol');
}
@ -236,7 +241,7 @@ class FlattenerVerifier {
if (flattenedFileExists) {
return next();
}
const file = this.embark.config.contractsFiles.find(file => path.normalize(file.path) === path.normalize(contract.filename));
const file = this.options.contractsFiles.find(file => path.normalize(file.path) === path.normalize(contract.filename));
this._doFlatten([file], next);
},
(next) => { // Read the flattened contract
@ -250,14 +255,17 @@ class FlattenerVerifier {
(content, next) => { // Get supported versions list
axios.get(solcVersionsListLink)
.then((response) => {
const solcVersion = response.data.split('\n').find(version => version.indexOf(this.embark.config.embarkConfig.versions.solc) > -1 && version.indexOf('nightly') === -1);
const solcVersion = response.data.split('\n')
.find(version => {
return version.indexOf(this.options.solcVersion) > -1 && version.indexOf('nightly') === -1;
});
next(null, content, solcVersion.replace('soljson-', '').replace('.js', ''));
})
.catch(next);
},
(content, solcVersion, next) => {
this.events.request("blockchain:networkId", (networkId) => {
next(null, content, solcVersion, networkId);
this.options.getNetworkId((err, networkId) => {
next(err, content, solcVersion, networkId);
});
}
], (err, content, solcVersion, networkId) => {
@ -271,10 +279,10 @@ class FlattenerVerifier {
flatten(contractNames, callback) {
if (!contractNames) {
return this._doFlatten(this.embark.config.contractsFiles, callback);
return this._doFlatten(this.options.contractsFiles, callback);
}
this.events.request('contracts:all', (err, contracts) => {
this.options.getAllContracts((err, contracts) => {
if (err) {
return callback(err);
}
@ -287,7 +295,7 @@ class FlattenerVerifier {
if (!contract) {
throw new Error('No contract named ' + contractName);
}
return this.embark.config.contractsFiles.find(file => path.normalize(file.originalPath) === path.normalize(contract.originalFilename));
return this.options.contractsFiles.find(file => path.normalize(file.originalPath) === path.normalize(contract.originalFilename));
});
} catch (e) {
return callback(null, e.message.red);