diff --git a/app/gas-relayer/abi/IdentityGasRelay.json b/app/gas-relayer/abi/IdentityGasRelay.json index 05cec0c..a83b817 100644 --- a/app/gas-relayer/abi/IdentityGasRelay.json +++ b/app/gas-relayer/abi/IdentityGasRelay.json @@ -1 +1 @@ -[{"constant":false,"inputs":[{"name":"_baseToken","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"},{"name":"_nonce","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_gasMinimal","type":"uint256"},{"name":"_gasToken","type":"address"},{"name":"_messageSignatures","type":"bytes"}],"name":"approveAndCallGasRelayed","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"},{"name":"_nonce","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_gasMinimal","type":"uint256"},{"name":"_gasToken","type":"address"},{"name":"_messageSignatures","type":"bytes"}],"name":"callGasRelayed","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[],"name":"Debug","type":"event"}] \ No newline at end of file +[{"constant":false,"inputs":[{"name":"_baseToken","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"},{"name":"_nonce","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_gasLimit","type":"uint256"},{"name":"_gasToken","type":"address"},{"name":"_messageSignatures","type":"bytes"}],"name":"approveAndCallGasRelayed","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"},{"name":"_nonce","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_gasLimit","type":"uint256"},{"name":"_gasToken","type":"address"},{"name":"_messageSignatures","type":"bytes"}],"name":"callGasRelayed","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[],"name":"Debug","type":"event"}] \ No newline at end of file diff --git a/app/gas-relayer/config/config.json b/app/gas-relayer/config/config.json index 1a2c578..67fde4f 100644 --- a/app/gas-relayer/config/config.json +++ b/app/gas-relayer/config/config.json @@ -1,8 +1,9 @@ { "blockchain": { "account": "0x9e14016ba37b23498885864053fded5226161a3a", - "rpcHost": "localhost", - "rpcPort": 8545 + "protocol": "ws", + "host": "localhost", + "port": 8545 }, "whisper": { @@ -32,7 +33,7 @@ "contracts":{ "IdentityGasRelay": { "isIdentity": true, - "factoryAddress": "0x96f0811c6484c59c2674da1f64e725c01d82c1b5", + "factoryAddress": "0x18f71378f4735b35e01eb71afcc66df090eccea7", "abiFile": "../abi/IdentityGasRelay.json", "allowedFunctions": [ { diff --git a/app/gas-relayer/package.json b/app/gas-relayer/package.json index e587f0e..b7d36b9 100644 --- a/app/gas-relayer/package.json +++ b/app/gas-relayer/package.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "daemonize2": "^0.4.2", + "ganache-cli": "^6.1.0", "md5": "^2.2.1", "web3": "^1.0.0-beta.33" } diff --git a/app/gas-relayer/src/service.js b/app/gas-relayer/src/service.js index b7f9ce9..e6d4f23 100644 --- a/app/gas-relayer/src/service.js +++ b/app/gas-relayer/src/service.js @@ -2,6 +2,7 @@ const md5 = require('md5'); const Web3 = require('web3'); const config = require('../config/config.json'); const web3 = new Web3(`${config.whisper.protocol}://${config.whisper.host}:${config.whisper.port}`); +var ganache = require("ganache-cli"); const erc20ABI = require('../abi/ERC20.json'); @@ -64,7 +65,6 @@ for(let contractName in config.contracts){ } } - // Setting up Whisper options const shhOptions = { ttl: config.whisper.ttl, @@ -169,7 +169,7 @@ const processMessages = async function(error, message, subscription){ Token.options.address = params[contract.allowedFunctions[functionName].gasToken]; balance = new web3.utils.BN(await Token.methods.balanceOf(address).call()); } - + // Determine if enough balance for baseToken if(contract.allowedFunctions[functionName].isToken){ const Token = new web3.eth.Contract(erc20ABI); @@ -179,21 +179,38 @@ const processMessages = async function(error, message, subscription){ return reply("Not enough balance", message); } } - + // Obtain factor let factor; if(contract.allowedFunctions[functionName].isToken){ - factor = config.tokens[tokenAddress].pricePlugin.getFactor(); + factor =web3.utils.toBN(config.tokens[tokenAddress].pricePlugin.getFactor()); } else { - factor = 1; + factor = web3.utils.toBN(1); } - + const balanceInETH = balance.div(factor); const gasLimitInETH = gasLimit.div(factor); - if(balanceInETH.lt(web3.utils.toBN(gasPrice.mul(gasLimit)))){ + + if(balanceInETH.lt(web3.utils.toBN(gasPrice.mul(gasLimit)))) { return reply("Not enough balance", message); } + + // Estimate costs + const web3Sim = new Web3(ganache.provider({fork: `${config.blockchain.protocol}://${config.blockchain.host}:${config.blockchain.port}`})); + const simAccounts = await web3.eth.getAccounts(); + let simulatedReceipt = await web3.eth.sendTransaction({ + from: simAccounts[0], + to: address, + value: 0, + data: payload + }); + const estimatedGas = web3.utils.toBN(simulatedReceipt.gasUsed); + + if(gasLimit.lt(estimatedGas)) { + return reply("Gas limit below estimated gas", message); + } + web3.eth.sendTransaction({ from: config.blockchain.account, to: address, diff --git a/app/gas-relayer/test/sampleContracts.sol b/app/gas-relayer/test/sampleContracts.sol index 178cb28..eeca5dd 100644 --- a/app/gas-relayer/test/sampleContracts.sol +++ b/app/gas-relayer/test/sampleContracts.sol @@ -10,7 +10,7 @@ contract TestIdentityGasRelay { bytes _data, uint _nonce, uint _gasPrice, - uint _gasMinimal, + uint _gasLimit, address _gasToken, bytes _messageSignatures ) external { @@ -23,7 +23,7 @@ contract TestIdentityGasRelay { bytes _data, uint _nonce, uint _gasPrice, - uint _gasMinimal, + uint _gasLimit, address _gasToken, bytes _messageSignatures ) external {