Skip to content

Commit a4a0e9d

Browse files
committed
feat(plugins/specialconfigs): adds support for Smart Contract args as functions
This commit introduces a new feature that enables users to calculate Smart Contract constructor arguments lazily using an (async) function. Similar to normal Smart Contract configurations, the return or resolved value from that function has to be either a list of arguments in the order as they are needed for the constructor, or as an object with named members that match the arguments individually. ``` ... development: { deploy: { SimpleStorage: { args: async ({ contracts, web3, logger}) => { // do something with `contracts` and `web3` to determine // arguments let someValue = await ...; return [someValue]; // or return { initialValue: someValue }; } } } } ... ``` Closes #2270
1 parent 8de6cf9 commit a4a0e9d

File tree

8 files changed

+71
-9
lines changed

8 files changed

+71
-9
lines changed

dapps/tests/app/config/contracts.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ module.exports = {
2222
args: [100],
2323
onDeploy: ["SimpleStorage.methods.setRegistar('embark.eth').send()"]
2424
},
25+
SimpleStorageArgsFn: {
26+
instanceOf: 'SimpleStorage',
27+
args: async ({ contracts, web3, logger }) => {
28+
return [5000];
29+
}
30+
},
2531
SimpleStorageTest: {
2632
//file: "./some_folder/test_contract.sol",
2733
args: [1000, 'embark.eth']

packages/core/utils/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,11 @@ export function prepareContractsConfig(config) {
213213
config.contracts[contractName].address = extendZeroAddressShorthand(address);
214214
}
215215

216-
if (args && args.length) {
216+
if (typeof args === 'function') {
217+
config.contracts[contractName].args = args;
218+
}
219+
220+
if (args && Array.isArray(args)) {
217221
config.contracts[contractName].args = args.map((val) => {
218222
if (typeof val === "string") {
219223
return extendZeroAddressShorthand(val);

packages/plugins/ens/src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@ class ENS {
438438
});
439439

440440
function checkArgs(args, done) {
441+
if (typeof args === 'function') {
442+
return done(null, args);
443+
}
441444
if (Array.isArray(args)) {
442445
async.map(args, (arg, next) => {
443446
if (Array.isArray(arg)) {

packages/plugins/specialconfigs/src/functionConfigs.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,22 @@ class FunctionConfigs {
7878
}
7979
}
8080

81+
async determineSmartContractArgs(params, cb) {
82+
const contract = params.contract;
83+
const argsFn = contract.args;
84+
try {
85+
const logger = Utils.createLoggerWithPrefix(this.logger, 'determineArgs >');
86+
const dependencies = await this.getDependenciesObject(logger);
87+
const args = await argsFn(dependencies);
88+
params.contract.args = args;
89+
cb();
90+
} catch (e) {
91+
cb(new Error(`Error running args function for ${contract.className}: ${e.message || e}`));
92+
}
93+
}
94+
8195
async getDependenciesObject(logger) {
8296
let contracts = await this.events.request2("contracts:list");
83-
8497
let args = { contracts: {}, logger};
8598
for (let contract of contracts) {
8699
// TODO: for this to work correctly we need to add a default from address to the contract

packages/plugins/specialconfigs/src/index.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class SpecialConfigs {
1919
this.embark.registerActionForEvent("deployment:contract:deployed", this.doOnDeployAction.bind(this));
2020
this.embark.registerActionForEvent("deployment:contract:shouldDeploy", this.deployIfAction.bind(this));
2121
this.embark.registerActionForEvent('deployment:contract:beforeDeploy', this.beforeDeployAction.bind(this));
22+
this.embark.registerActionForEvent('deployment:contract:determineArgs', this.determineSmartContractArgs.bind(this));
2223
}
2324

2425
async executeAddressHandlerForContract(params, cb) {
@@ -40,10 +41,17 @@ class SpecialConfigs {
4041
}
4142

4243
async beforeDeployAction(params, cb) {
43-
if (typeof params.contract.beforeDeploy !== 'function') {
44-
return this.listConfigs.beforeDeployAction(params, cb);
44+
if (params.contract.beforeDeploy) {
45+
return this.functionConfigs.beforeDeployAction(params, cb);
4546
}
46-
return this.functionConfigs.beforeDeployAction(params, cb);
47+
cb();
48+
}
49+
50+
async determineSmartContractArgs(params, cb) {
51+
if (typeof params.contract.args === 'function') {
52+
return this.functionConfigs.determineSmartContractArgs(params, cb);
53+
}
54+
cb();
4755
}
4856

4957
async doOnDeployAction(params, cb) {

packages/plugins/specialconfigs/src/listConfigs.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ class ListConfigs {
7474
});
7575
}
7676

77-
async beforeDeployAction(_params, cb) {
78-
return cb();
79-
}
80-
8177
runOnDeployCode(onDeployCode, callback, silent) {
8278
const logFunction = silent ? this.logger.trace.bind(this.logger) : this.logger.info.bind(this.logger);
8379
async.each(onDeployCode, (cmd, eachCb) => {

packages/stack/deployment/src/contract_deployer.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ class ContractDeployer {
1414

1515
deployContract(contract, callback) {
1616
async.waterfall([
17+
(next) => {
18+
this.plugins.emitAndRunActionsForEvent('deployment:contract:determineArgs', { contract }, (err) => {
19+
next(err);
20+
});
21+
},
1722
(next) => {
1823
this.plugins.emitAndRunActionsForEvent('deployment:contract:beforeDeploy', {contract: contract}, (err, _params) => {
1924
// TODO: confirm this really works and shouldn't be next(err, params)

site/source/docs/contracts_configuration.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,33 @@ development: {
5959
...
6060
```
6161

62+
### Calculating constructor parameters lazily
63+
64+
Another way to configure arguments for Smart Contract constructors is to calculate them lazily using an asynchronous function. This is especially useful if the Smart Contract's arguments depend on other runtime dependencies, such as already deployed Smart Contracts. To calculate arguments, all you have to do is define `args` as an (async) function and resolve with either a list of arguments or an object where each member maps to an individual constructor argument:
65+
66+
```
67+
...
68+
development: {
69+
deploy: {
70+
SimpleStorage: {
71+
args: async ({ contracts, web3, logger}) => {
72+
// do something with `contracts` and `web3` to determine
73+
// arguments
74+
let someValue = await ...;
75+
return [someValue];
76+
77+
// or
78+
return {
79+
initialValue: someValue
80+
};
81+
}
82+
}
83+
}
84+
}
85+
...
86+
```
87+
88+
6289
### Configuring gas and gas price
6390

6491
Both, `gas` and `gasPrice` can be configured for each Smart Contract. If we don't want to configure that for every single contract, we can also specify `gas: auto` in the environment, like this:

0 commit comments

Comments
 (0)