ContractSetupParameter vs ContractRunnerConfig

Hi devs,

I am using the @ContractParametersProvider together with @ContractSetupParameter. This works well in the unit tests and when using the values the decorated functions return.

I configure the unit tests using a JO:

JO setupParams = new JO();
setupParams.put("paramName", valueForTheUnitTest;
...
String contractName = ContractTestHelper.deployContract(MyContract.class, setupParams, false);

On the network, I would like to load these parameters, other than the defaults (to be flexible with Testnet and Mainnet deployments.

Is this possible? If not, I could change the contract to use ContractRunnerConfigParams, but I assume that I wouldn't be able to unit-test them that way.

I tried to use the contracts.uploader.json, which didn't let me set the parameters either.

These settings:

{
"contracts": [
{
"className": "IgnisAssetLottery",
"description":"description",
"version": "0.9",
"url": "https://ourDomain.org/",
"params": {
"paramName": 1,
...
}
}
]
}

caused the upload to crash. What am I doing wrong?

2021-03-24 10:06:44 INFO: main Contract class com.jelurida.ardor.contracts.MyContract uploaded 6f0d85a6b71db9369f125a23334e81567b3932bf1a2b5960cda7824ee63e5cba
2021-03-24 10:06:44 INFO: main contract.IgnisAssetLottery.param.paramName not defined
...
2021-03-24 10:06:44 SEVERE: main Contract reference not registered MyContract response {"errorDescription":"Failed to broadcast transaction: Invalid light contract announcement: {"contract":{"chain":2,"transactionFullHash":"6f0d85a6b71db9369f125a23334e81567b3932bf1a2b5960cda7824ee63e5cba"},"contractName":"MyContract","version.ContractReference":1,"contractParams":"{\"paramName\":1,\"tarascaRs\":\"ARDOR-G33B-A4HN-DGMX-8RQ6J\",\"cardsPerPack\":3,\"tarascaCutPerPack\":5000000000,\"collectionRs\":\"ARDOR-2LLJ-JRUA-M9X9-2V6EB\",\"priceIgnis\":9900000000,\"validCurrency\":\"8633185858724739856\"}"}","errorCode":4,"requestProcessingTime":29,"error":"nxt.NxtException$NotValidException: Invalid light contract announcement: {"contract":{"chain":2,"transactionFullHash":"6f0d85a6b71db9369f125a23334e81567b3932bf1a2b5960cda7824ee63e5cba"},"contractName":"MyContract","version.ContractReference":1,"contractParams":"{\"paramName\":1,\"tarascaRs\":\"ARDOR-G33B-A4HN-DGMX-8RQ6J\",\"cardsPerPack\":3,\"tarascaCutPerPack\":5000000000,\"collectionRs\":\"ARDOR-2LLJ-JRUA-M9X9-2V6EB\",\"priceIgnis\":9900000000,\"validCurrency\":\"8633185858724739856\"}"}"}
2021-03-24 10:06:44 INFO: main Waiting for new block {"registered":true,"requestProcessingTime":0,"token":"6"}

Note, still trying to troubleshoot this, I found that the strategy to use the contract.uploader.json worked for another contract.

The INFO: main contract.OtherContract.param.paramName not defined message appeared there too, but later it was registered with the correct parameters.

What could be the reason for the particular MyContract to fail to be registered on the blockchain?

There are three types of contract parameters:

  • ContractInvocationParameter are sent as part of the JSON that triggers a contract
  • ContractRunnerParameter are set when starting the contract runner and are private to the node running the contract
  • ContractSetupParameter are set on the contract reference transaction where the contract is given a name and points to the data cloud transaction containing the contract code

So, yes you can have different setup parameters on the unit tests, on mainnet and testnet. Those parameters are set when uploading the contract.

My guess about the error you are seeing is the length of the parameters JSON. You see, the setup parameters are encoded as json as part of the contract reference transaction and the length is limited to 160 characters (Constants.MAX_CONTRACT_PARAMS_LENGTH).

Try to make the names and values as small as possible. Instead of using RS format for the addresses you can go with the account id which is shorter. If you still hit the limit you will need to move some parameters to be for the contract runner where you don't have any limit.