diff --git a/README.md b/README.md index e03a13b6..fc957f02 100644 --- a/README.md +++ b/README.md @@ -48,16 +48,17 @@ node server/monitor/monitorCLI.js Use the following options with the Clawk Standalone CLI Monitor: -| Option | Description | Required | -| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| `--help` | Show help | No | -| `--version` | Show version number | No | -| `--address` | The address of the deployed contract | Yes | -| `--dcrID` | The DCR model identifier from DCRGraphs.net website | Yes | -| `--simID` | The identifier of the specific simulation you want to model this contract against. This identifier is retrievable by going to address [https://repository.dcrgraphs.net/api/graphs/${dcrID}/sims/](https://repository.dcrgraphs.net/api/graphs/${dcrID}/sims/) replacing ${dcrID} with the ID of the model you are trying to monitor against | Yes | -| `--ABIFileName` | The name of the contract ABI file (for example: PiggyBank.json). You should first put this file in the path `server/monitor/contracts/json-interface` | Yes | -| `--contract` | The contract parameter | Yes | -| `--paramap` | Supply parameter mapping for function calls to DCR graphs semantics for any transaction. The same file name as ABIFileName will be looked up in `server/monitor/contracts/paramaps/` directory. Format of the required json file:
`{`
` "functionName": {`
` "paramName": {`
` EVMType: "...",`
` DCRType: "...",`
` DCRNodeID: "..."`
` }`
` }`
`}` | No | +| Option | Description | Required | +| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| `--help` | Show help | No | +| `--version` | Show version number | No | +| `--address` | The address of the deployed contract | Yes | +| `--dcrID` | The DCR model identifier from DCRGraphs.net website | Yes | +| `--simID` | The identifier of the specific simulation you want to model this contract against. This identifier is retrievable by going to address [https://repository.dcrgraphs.net/api/graphs/${dcrID}/sims/](https://repository.dcrgraphs.net/api/graphs/${dcrID}/sims/) replacing ${dcrID} with the ID of the model you are trying to monitor against | Yes | +| `--ABIFileName` | The name of the contract ABI file (for example: PiggyBank.json). You should first put this file in the path `server/monitor/contracts/json-interface` | Yes | +| `--contract` | The contract parameter | Yes | +| `--paramap` | Supply parameter mapping for function calls to DCR graphs semantics for any transaction. The same file name as ABIFileName will be looked up in `server/monitor/contracts/paramaps/` directory. Format of the required json file:
`{`
` "functionName": {`
` "paramName": {`
` EVMType: "...",`
` DCRType: "...",`
` DCRNodeID: "..."`
` }`
`"roleSetter":true `
`"roleVariableIdentifier":"owner"`
`}`
`}` | +| | No | #### Example command usage: diff --git a/server/monitor/contractWatcher.js b/server/monitor/contractWatcher.js index 726c44d3..ea1de4f7 100644 --- a/server/monitor/contractWatcher.js +++ b/server/monitor/contractWatcher.js @@ -96,6 +96,8 @@ let getContractTransactions = (address, contractABI, activities, paramaps) => { // Get the function signature from the transaction data const signature = tx.input.slice(0, 10); + + // Find the function ABI that matches the signature const method = JSON.parse(contractABI).find((m) => m.type === 'function' && `0x${web3.utils.keccak256(m.name + '(' + m.inputs.map((i) => i.type).join(',') + ')').slice(2, 10)}` === signature); const decodedParams = web3.eth.abi.decodeParameters(method.inputs, tx.input.slice(10)); @@ -146,21 +148,21 @@ let getContractTransactions = (address, contractABI, activities, paramaps) => { }); } catch { - + console.log("TX conversion failed"); + } + if (activities.includes(method.name)) { + let tx_ = { + 'dcrID': method.name, + 'contractABI': contractABI, + 'dcrValue': null, + 'dcrType': null + }; + contract_queue.push(tx_); } - console.log("I am here at 149") - if (activities.includes(method.name)) { - console.log("I am here 151.") - let tx_ = { - 'dcrID': method.name, - 'contractABI': contractABI, - 'dcrValue': null, - 'dcrType': null - }; - contract_queue.push(tx_); - } - console.log(`method is: ${method.name}`); - + + + console.log(`method is: ${method.name}`); + } @@ -174,5 +176,4 @@ let getContractTransactions = (address, contractABI, activities, paramaps) => { -//module.exports = listen; module.exports = getContractTransactions; \ No newline at end of file diff --git a/server/monitor/contracts/paramaps/VulnerableVotingContract.json b/server/monitor/contracts/paramaps/VulnerableVotingContract.json index 9e7d360d..bc5adcab 100644 --- a/server/monitor/contracts/paramaps/VulnerableVotingContract.json +++ b/server/monitor/contracts/paramaps/VulnerableVotingContract.json @@ -5,6 +5,8 @@ "EVMUnit": "hours", "DCRType": "duration", "DCRNodeID": "_hoursFromNow" - } + }, + "roleSetter":true, + "roleVariableIdentifier": "owner" } } \ No newline at end of file diff --git a/server/monitor/evm-to-dcr.js b/server/monitor/evm-to-dcr.js new file mode 100644 index 00000000..82224b74 --- /dev/null +++ b/server/monitor/evm-to-dcr.js @@ -0,0 +1,82 @@ +let WaitQueue = require('wait-queue'); +let Web3 = require("web3"); +let fs = require('fs'); +let path = require('path'); + + +let getDCRMethodsToExecute = () => { + //console.log(`Transaction object: ${JSON.stringify(tx)}`); + + // Get the function signature from the transaction data + const signature = tx.input.slice(0, 10); + + // Find the function ABI that matches the signature + const method = JSON.parse(contractABI).find((m) => m.type === 'function' && `0x${web3.utils.keccak256(m.name + '(' + m.inputs.map((i) => i.type).join(',') + ')').slice(2, 10)}` === signature); + const decodedParams = web3.eth.abi.decodeParameters(method.inputs, tx.input.slice(10)); + + console.log(`Method is: ${method.name}`) + console.log(`Activities are: ${activities}`); + + const checkParametersAreInParamaps = () => { + const relevantKeys = Object.keys(decodedParams).filter(key => !key.match(/^(\d+|__length__)$/)); + return relevantKeys.filter(key => Object.hasOwnProperty.call(paramaps, key)); + }; + + // Assumption: + // If the event does not exist in the DCR model, just skip it + if (activities.includes(method.name) || checkParametersAreInParamaps()) { + try { + checkParametersAreInParamaps().forEach(parameter => { + // convert tx parameter to value suitable for DCR + if ((paramaps[parameter][method.name]["EVMType"] === "uint256") && (paramaps[parameter][method.name]["DCRType"] === "duration")) { + // Conversion between time parameters in SC to time in DCR + let unit = paramaps[parameter][method.name]["EVMUnit"]; + let value = decodedParams[parameter]; + + const convertToISO8601 = (value, unit) => { + switch (unit) { + case "hours": + return 'PT' + value + 'H'; + case "minutes": + return 'PT' + value + 'M'; + case "seconds": + return 'PT' + value + 'S'; + default: + return "Invalid unit"; + } + }; + + // DCR event types for REST API are: int, duration, ... + let iso8601Duration = convertToISO8601(value, unit); + let tx_ = { + 'dcrID': parameter, + 'contractABI': contractABI, + 'dcrValue': iso8601Duration, + 'dcrType': paramaps[parameter][method.name]["DCRType"] + }; + contract_queue.push(tx_); + } + + + }); + } catch { + console.log("TX conversion failed"); + } + if (activities.includes(method.name)) { + let tx_ = { + 'dcrID': method.name, + 'contractABI': contractABI, + 'dcrValue': null, + 'dcrType': null + }; + contract_queue.push(tx_); + } + + + console.log(`method is: ${method.name}`); + + } +} + + +module.exports = getDCRMethodsToExecute; \ No newline at end of file