Merge branch 'master' of https://github.com/status-im/snt-gas-relay
This commit is contained in:
commit
3347c4fc68
|
@ -78,7 +78,6 @@ class MessageProcessor {
|
|||
|
||||
if(!validationResult.success){
|
||||
reply(validationResult.message);
|
||||
return;
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
|
@ -95,6 +94,8 @@ class MessageProcessor {
|
|||
async processTransaction(contract, input, reply){
|
||||
const validationResult = await this.processStrategy(contract, input, reply);
|
||||
|
||||
if(!validationResult.success) return;
|
||||
|
||||
let p = {
|
||||
from: this.config.node.blockchain.account,
|
||||
to: input.contract,
|
||||
|
@ -107,10 +108,10 @@ class MessageProcessor {
|
|||
validationResult.estimatedGas = await this.web3.eth.estimateGas(p);
|
||||
}
|
||||
|
||||
p.gas = parseInt(validationResult.estimatedGas * 1.05, 10); // Tune this
|
||||
|
||||
p.gas = Math.floor(parseInt(validationResult.estimatedGas, 10)); // Tune this
|
||||
|
||||
const nodeBalance = await this.web3.eth.getBalance(this.config.node.blockchain.account);
|
||||
|
||||
|
||||
if(nodeBalance < p.gas){
|
||||
reply("Relayer unavailable");
|
||||
console.error("Relayer doesn't have enough gas to process trx: %s, required %s", nodeBalance, p.gas);
|
||||
|
|
|
@ -77,16 +77,15 @@ class BaseStrategy {
|
|||
}));
|
||||
|
||||
let simAccounts = await web3Sim.eth.getAccounts();
|
||||
|
||||
|
||||
let simulatedReceipt = await web3Sim.eth.sendTransaction({
|
||||
from: simAccounts[0],
|
||||
to: input.address,
|
||||
to: input.contract,
|
||||
value: 0,
|
||||
data: input.payload,
|
||||
gasLimit: 9500000 // 95% of current chain latest gas block limit
|
||||
|
||||
});
|
||||
|
||||
return simulatedReceipt;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
const Strategy = require('./BaseStrategy');
|
||||
const erc20ABI = require('../../abi/ERC20Token.json');
|
||||
|
||||
const CallGasRelayed = "0xfd0dded5";
|
||||
const ApproveAndCallGasRelayed = "0x59f4ac61";
|
||||
|
||||
/**
|
||||
* Class representing a strategy to validate a `transaction` request when the topic is related to Identities.
|
||||
* @extends Strategy
|
||||
|
@ -64,13 +67,23 @@ class IdentityStrategy extends Strategy {
|
|||
|
||||
let estimatedGas = 0;
|
||||
try {
|
||||
// Geth tends to fail estimation with proxies, so we simulate it with ganache
|
||||
estimatedGas = await this._simulateTransaction(input);
|
||||
if(gasLimit.mul(this.web3.utils.toBN(1.05)).lt(estimatedGas)) {
|
||||
// TODO: Investigate why sometimes geth fails estimations with proxies
|
||||
if(input.functionName == CallGasRelayed){
|
||||
estimatedGas = await this._estimateGas(input);
|
||||
} else {
|
||||
const tmp = Math.floor(parseInt((await this._estimateGas(input)).toString(10), 10) * 1.05);
|
||||
estimatedGas = this.web3.utils.toBN(tmp); // TODO: tune this
|
||||
}
|
||||
|
||||
if(gasLimit.lt(estimatedGas)) {
|
||||
return {success: false, message: "Gas limit below estimated gas (" + estimatedGas + ")"};
|
||||
}
|
||||
} catch(exc){
|
||||
if(exc.message.indexOf("revert") > -1) return {success: false, message: "Transaction will revert"};
|
||||
else {
|
||||
console.error(exc);
|
||||
return {success: false, message: "Couldn't process transaction"};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -41,7 +41,8 @@ class SNTStrategy extends Strategy {
|
|||
const latestBlock = await this.web3.eth.getBlock("latest");
|
||||
let estimatedGas = 0;
|
||||
try {
|
||||
estimatedGas = await this._estimateGas(input, latestBlock.gasLimit);
|
||||
const simulatedReceipt = await this._simulateTransaction(input, latestBlock.gasLimit);
|
||||
estimatedGas = this.web3.utils.toBN(simulatedReceipt.gasUsed);
|
||||
} catch(exc){
|
||||
if(exc.message.indexOf("revert") > -1) return {success: false, message: "Transaction will revert"};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component} from 'react';
|
||||
import StatusGasRelayer, {Contracts, Functions} from '../status-gas-relayer';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
|
@ -15,7 +16,7 @@ import TextField from '@material-ui/core/TextField';
|
|||
import config from '../config';
|
||||
import web3 from 'Embark/web3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
import { Typography } from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
|
@ -63,7 +64,7 @@ class ApproveAndCallGasRelayed extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
sign = (event) => {
|
||||
sign = async (event) => {
|
||||
if(event) event.preventDefault();
|
||||
|
||||
this.setState({
|
||||
|
@ -74,27 +75,21 @@ class ApproveAndCallGasRelayed extends Component {
|
|||
IdentityGasRelay.options.address = this.props.identityAddress;
|
||||
|
||||
try {
|
||||
IdentityGasRelay.methods.deployGasRelayHash(
|
||||
this.state.value,
|
||||
web3.utils.soliditySha3({t: 'bytes', v: this.state.data}),
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken
|
||||
)
|
||||
.call()
|
||||
.then(message => {
|
||||
return web3.eth.sign(message, web3.eth.defaultAccount);
|
||||
})
|
||||
.then(signature => {
|
||||
this.setState({signature});
|
||||
});
|
||||
const s = new StatusGasRelayer.Identity(this.props.identityAddress, web3.eth.defaultAccount)
|
||||
.setContractFunction(Functions.Identity.approveAndCall)
|
||||
.setTransaction(this.state.to, this.state.value, this.state.data)
|
||||
.setBaseToken(this.state.baseToken)
|
||||
.setGas(this.state.gasToken, this.state.gasPrice, this.state.gasLimit);
|
||||
|
||||
const signature = await s.sign(web3);
|
||||
|
||||
this.setState({signature});
|
||||
} catch(error){
|
||||
this.setState({transactionError: error.message});
|
||||
}
|
||||
}
|
||||
|
||||
obtainRelayers = event => {
|
||||
obtainRelayers = async event => {
|
||||
event.preventDefault();
|
||||
|
||||
const {web3, kid, skid} = this.props;
|
||||
|
@ -106,34 +101,20 @@ class ApproveAndCallGasRelayed extends Component {
|
|||
this.props.clearMessages();
|
||||
|
||||
try {
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
symKeyID: skid,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': this.props.identityAddress,
|
||||
'address': web3.eth.defaultAccount,
|
||||
'action': 'availability',
|
||||
'gasToken': this.state.gasToken,
|
||||
'gasPrice': this.state.gasPrice
|
||||
})
|
||||
};
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
const s = new StatusGasRelayer.AvailableRelayers(Contracts.Identity, this.props.identityAddress, web3.eth.defaultAccount)
|
||||
.setRelayersSymKeyID(skid)
|
||||
.setAsymmetricKeyID(kid)
|
||||
.setGas(this.state.gasToken, this.state.gasPrice);
|
||||
await s.post(web3);
|
||||
|
||||
console.log("Message sent");
|
||||
this.setState({submitting: false});
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
}
|
||||
|
||||
sendTransaction = event => {
|
||||
sendTransaction = async event => {
|
||||
event.preventDefault();
|
||||
|
||||
const {web3, kid} = this.props;
|
||||
|
@ -151,39 +132,18 @@ class ApproveAndCallGasRelayed extends Component {
|
|||
|
||||
|
||||
try {
|
||||
let jsonAbi = IdentityGasRelay._jsonInterface.filter(x => x.name == "approveAndCallGasRelayed")[0];
|
||||
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.state.baseToken,
|
||||
this.state.to,
|
||||
this.state.value,
|
||||
this.state.data,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken,
|
||||
this.state.signature
|
||||
]);
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
pubKey: relayer,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': this.props.identityAddress,
|
||||
'address': web3.eth.defaultAccount,
|
||||
'action': 'transaction',
|
||||
'encodedFunctionCall': funCall
|
||||
})
|
||||
};
|
||||
const s = new StatusGasRelayer.Identity(this.props.identityAddress, web3.eth.defaultAccount)
|
||||
.setContractFunction(Functions.Identity.approveAndCall)
|
||||
.setTransaction(this.state.to, this.state.value, this.state.data)
|
||||
.setBaseToken(this.state.baseToken)
|
||||
.setGas(this.state.gasToken, this.state.gasPrice, this.state.gasLimit)
|
||||
.setRelayer(relayer)
|
||||
.setAsymmetricKeyID(kid);
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
await s.post(this.state.signature, web3);
|
||||
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component} from 'react';
|
||||
import StatusGasRelayer, {Contracts, Functions} from '../status-gas-relayer';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
|
@ -6,7 +7,6 @@ import CardContent from '@material-ui/core/CardContent';
|
|||
import CardHeader from '@material-ui/core/CardHeader';
|
||||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import IdentityGasRelay from 'Embark/contracts/IdentityGasRelay';
|
||||
import MySnackbarContentWrapper from './snackbar';
|
||||
import PropTypes from 'prop-types';
|
||||
import STT from 'Embark/contracts/STT';
|
||||
|
@ -15,6 +15,7 @@ import TextField from '@material-ui/core/TextField';
|
|||
import config from '../config';
|
||||
import web3 from 'Embark/web3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
|
@ -66,7 +67,7 @@ class CallGasRelayed extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
sign = (event) => {
|
||||
sign = async (event) => {
|
||||
if(event) event.preventDefault();
|
||||
|
||||
this.setState({
|
||||
|
@ -74,31 +75,22 @@ class CallGasRelayed extends Component {
|
|||
transactionError: ''
|
||||
});
|
||||
|
||||
IdentityGasRelay.options.address = this.props.identityAddress;
|
||||
|
||||
try {
|
||||
IdentityGasRelay.methods.callGasRelayHash(
|
||||
this.state.to,
|
||||
this.state.value,
|
||||
web3.utils.soliditySha3({t: 'bytes', v: this.state.data}),
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken
|
||||
)
|
||||
.call()
|
||||
.then(message => {
|
||||
return web3.eth.sign(message, web3.eth.defaultAccount);
|
||||
})
|
||||
.then(signature => {
|
||||
this.setState({signature});
|
||||
});
|
||||
|
||||
const s = new StatusGasRelayer.Identity(this.props.identityAddress, web3.eth.defaultAccount)
|
||||
.setContractFunction(Functions.Identity.call)
|
||||
.setTransaction(this.state.to, this.state.value, this.state.data)
|
||||
.setGas(this.state.gasToken, this.state.gasPrice, this.state.gasLimit);
|
||||
|
||||
const signature = await s.sign(web3);
|
||||
|
||||
this.setState({signature});
|
||||
} catch(error){
|
||||
this.setState({transactionError: error.message});
|
||||
}
|
||||
}
|
||||
|
||||
obtainRelayers = event => {
|
||||
obtainRelayers = async event => {
|
||||
event.preventDefault();
|
||||
|
||||
const {web3, kid, skid} = this.props;
|
||||
|
@ -110,34 +102,21 @@ class CallGasRelayed extends Component {
|
|||
this.props.clearMessages();
|
||||
|
||||
try {
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
symKeyID: skid,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': this.props.identityAddress,
|
||||
'address': web3.eth.defaultAccount,
|
||||
'action': 'availability',
|
||||
'gasToken': this.state.gasToken,
|
||||
'gasPrice': this.state.gasPrice
|
||||
})
|
||||
};
|
||||
const s = new StatusGasRelayer.AvailableRelayers(Contracts.Identity, this.props.identityAddress, web3.eth.defaultAccount)
|
||||
.setRelayersSymKeyID(skid)
|
||||
.setAsymmetricKeyID(kid)
|
||||
.setGas(this.state.gasToken, this.state.gasPrice);
|
||||
await s.post(web3);
|
||||
|
||||
console.log("Message sent");
|
||||
this.setState({submitting: false});
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
}
|
||||
|
||||
sendTransaction = event => {
|
||||
sendTransaction = async event => {
|
||||
event.preventDefault();
|
||||
|
||||
const {web3, kid} = this.props;
|
||||
|
@ -154,38 +133,17 @@ class CallGasRelayed extends Component {
|
|||
this.props.clearMessages();
|
||||
|
||||
try {
|
||||
let jsonAbi = IdentityGasRelay._jsonInterface.filter(x => x.name == "callGasRelayed")[0];
|
||||
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.state.to,
|
||||
this.state.value,
|
||||
this.state.data,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasLimit,
|
||||
this.state.gasToken,
|
||||
this.state.signature
|
||||
]);
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
pubKey: relayer,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': this.props.identityAddress,
|
||||
'address': web3.eth.defaultAccount,
|
||||
'action': 'transaction',
|
||||
'encodedFunctionCall': funCall
|
||||
})
|
||||
};
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
const s = new StatusGasRelayer.Identity(this.props.identityAddress, web3.eth.defaultAccount)
|
||||
.setContractFunction(Functions.Identity.call)
|
||||
.setTransaction(this.state.to, this.state.value, this.state.data)
|
||||
.setGas(this.state.gasToken, this.state.gasPrice, this.state.gasLimit)
|
||||
.setRelayer(relayer)
|
||||
.setAsymmetricKeyID(kid);
|
||||
|
||||
await s.post(this.state.signature, web3);
|
||||
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component} from 'react';
|
||||
import StatusGasRelayer, {Contracts} from '../status-gas-relayer';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
|
@ -9,11 +10,11 @@ import MySnackbarContentWrapper from './snackbar';
|
|||
import PropTypes from 'prop-types';
|
||||
import SNTController from 'Embark/contracts/SNTController';
|
||||
import STT from 'Embark/contracts/STT';
|
||||
import TestContract from 'Embark/contracts/TestContract';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import config from '../config';
|
||||
import web3 from 'Embark/web3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
import TestContract from 'Embark/contracts/TestContract';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
|
@ -55,7 +56,7 @@ class Execute extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
sign = (event) => {
|
||||
sign = async (event) => {
|
||||
if(event) event.preventDefault();
|
||||
|
||||
this.setState({
|
||||
|
@ -63,28 +64,16 @@ class Execute extends Component {
|
|||
transactionError: ''
|
||||
});
|
||||
|
||||
SNTController.options.address = this.props.identityAddress;
|
||||
|
||||
try {
|
||||
let message = "";
|
||||
SNTController.methods.getExecuteGasRelayedHash(
|
||||
this.state.allowedContract,
|
||||
this.state.data,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasMinimal
|
||||
)
|
||||
.call()
|
||||
.then(result => {
|
||||
message = result;
|
||||
return web3.eth.getAccounts();
|
||||
})
|
||||
.then(accounts => {
|
||||
return web3.eth.sign(message, accounts[2]);
|
||||
})
|
||||
.then(signature => {
|
||||
this.setState({signature});
|
||||
});
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
|
||||
.execute(this.state.allowedContract, this.state.data)
|
||||
.setGas(this.state.gasPrice, this.state.gasMinimal);
|
||||
|
||||
const signature = await s.sign(web3);
|
||||
|
||||
this.setState({signature});
|
||||
} catch(error){
|
||||
this.setState({transactionError: error.message});
|
||||
}
|
||||
|
@ -112,32 +101,18 @@ class Execute extends Component {
|
|||
|
||||
this.props.clearMessages();
|
||||
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
|
||||
try {
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
symKeyID: skid,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': SNTController.options.address,
|
||||
'address': accounts[2],
|
||||
'action': 'availability',
|
||||
'gasToken': STT.options.address,
|
||||
'gasPrice': this.state.gasPrice
|
||||
})
|
||||
};
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
const s = new StatusGasRelayer.AvailableRelayers(Contracts.SNT, SNTController.options.address, accounts[2])
|
||||
.setRelayersSymKeyID(skid)
|
||||
.setAsymmetricKeyID(kid)
|
||||
.setGas(STT.options.address, this.state.gasPrice);
|
||||
await s.post(web3);
|
||||
|
||||
console.log("Message sent");
|
||||
this.setState({submitting: false});
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
|
@ -161,39 +136,19 @@ class Execute extends Component {
|
|||
this.props.clearMessages();
|
||||
|
||||
try {
|
||||
let jsonAbi = SNTController._jsonInterface.filter(x => x.name == "executeGasRelayed")[0];
|
||||
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.state.allowedContract,
|
||||
this.state.data,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.gasMinimal,
|
||||
this.state.signature
|
||||
]);
|
||||
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
pubKey: relayer,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': SNTController.options.address,
|
||||
'address': accounts[2],
|
||||
'action': 'transaction',
|
||||
'encodedFunctionCall': funCall
|
||||
})
|
||||
};
|
||||
const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
|
||||
.execute(this.state.allowedContract, this.state.data)
|
||||
.setGas(this.state.gasPrice, this.state.gasMinimal)
|
||||
.setRelayer(relayer)
|
||||
.setAsymmetricKeyID(kid);
|
||||
|
||||
await s.post(this.state.signature, web3);
|
||||
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, {Component} from 'react';
|
||||
import StatusGasRelayer, {Contracts} from '../status-gas-relayer';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
|
@ -9,12 +10,12 @@ import MySnackbarContentWrapper from './snackbar';
|
|||
import PropTypes from 'prop-types';
|
||||
import SNTController from 'Embark/contracts/SNTController';
|
||||
import STT from 'Embark/contracts/STT';
|
||||
|
||||
import TestContract from 'Embark/contracts/TestContract';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import config from '../config';
|
||||
import web3 from 'Embark/web3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
|
@ -64,7 +65,7 @@ class TransferSNT extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
sign = (event) => {
|
||||
sign = async (event) => {
|
||||
if(event) event.preventDefault();
|
||||
|
||||
this.setState({
|
||||
|
@ -72,27 +73,18 @@ class TransferSNT extends Component {
|
|||
transactionError: ''
|
||||
});
|
||||
|
||||
SNTController.options.address = this.props.identityAddress;
|
||||
|
||||
try {
|
||||
let message = "";
|
||||
SNTController.methods.getTransferSNTHash(
|
||||
this.state.to,
|
||||
this.state.amount,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice
|
||||
)
|
||||
.call()
|
||||
.then(result => {
|
||||
message = result;
|
||||
return web3.eth.getAccounts();
|
||||
})
|
||||
.then(accounts => {
|
||||
return web3.eth.sign(message, accounts[2]);
|
||||
})
|
||||
.then(signature => {
|
||||
this.setState({signature});
|
||||
});
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
|
||||
.transferSNT(this.state.to, this.state.amount)
|
||||
.setGas(this.state.gasPrice);
|
||||
|
||||
const signature = await s.sign(web3);
|
||||
|
||||
this.setState({signature});
|
||||
|
||||
} catch(error){
|
||||
this.setState({transactionError: error.message});
|
||||
}
|
||||
|
@ -109,31 +101,19 @@ class TransferSNT extends Component {
|
|||
});
|
||||
this.props.clearMessages();
|
||||
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
try {
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
symKeyID: skid,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': SNTController.options.address,
|
||||
'address': accounts[2],
|
||||
'action': 'availability',
|
||||
'gasToken': this.state.gasToken,
|
||||
'gasPrice': this.state.gasPrice
|
||||
})
|
||||
};
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
const s = new StatusGasRelayer.AvailableRelayers(Contracts.SNT, SNTController.options.address, accounts[2])
|
||||
.setRelayersSymKeyID(skid)
|
||||
.setAsymmetricKeyID(kid)
|
||||
.setGas(STT.options.address, this.state.gasPrice);
|
||||
await s.post(web3);
|
||||
|
||||
console.log("Message sent");
|
||||
this.setState({submitting: false});
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
|
@ -156,38 +136,19 @@ class TransferSNT extends Component {
|
|||
this.props.clearMessages();
|
||||
|
||||
try {
|
||||
let jsonAbi = SNTController._jsonInterface.filter(x => x.name == "transferSNT")[0];
|
||||
let funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.state.to,
|
||||
this.state.amount,
|
||||
this.props.nonce,
|
||||
this.state.gasPrice,
|
||||
this.state.signature
|
||||
]);
|
||||
|
||||
const accounts = await web3.eth.getAccounts();
|
||||
|
||||
const sendOptions = {
|
||||
ttl: 1000,
|
||||
sig: kid,
|
||||
powTarget: 1,
|
||||
powTime: 20,
|
||||
topic: this.state.topic,
|
||||
pubKey: relayer,
|
||||
payload: web3.utils.toHex({
|
||||
'contract': SNTController.options.address,
|
||||
'address': accounts[2],
|
||||
'action': 'transaction',
|
||||
'encodedFunctionCall': funCall
|
||||
})
|
||||
};
|
||||
const s = new StatusGasRelayer.SNTController(SNTController.options.address, accounts[2])
|
||||
.transferSNT(this.state.to, this.state.amount)
|
||||
.setGas(this.state.gasPrice)
|
||||
.setRelayer(relayer)
|
||||
.setAsymmetricKeyID(kid);
|
||||
|
||||
await s.post(this.state.signature, web3);
|
||||
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
|
||||
web3.shh.post(sendOptions)
|
||||
.then(() => {
|
||||
this.setState({submitting: false});
|
||||
console.log("Message sent");
|
||||
return true;
|
||||
});
|
||||
} catch(error){
|
||||
this.setState({messagingError: error.message, submitting: false});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,777 @@
|
|||
export const Contracts = {
|
||||
'Identity': 'IdentityGasRelay',
|
||||
'SNT': 'SNTController'
|
||||
};
|
||||
|
||||
export const Functions = {
|
||||
'Identity': {
|
||||
'call': 'callGasRelayed',
|
||||
'approveAndCall': 'approveAndCallGasRelayed'
|
||||
},
|
||||
'SNT': {
|
||||
'transfer': 'transferSNT',
|
||||
'execute': 'executeGasRelayed'
|
||||
}
|
||||
};
|
||||
|
||||
export const Actions = {
|
||||
'Availability': 'availability',
|
||||
'Transaction': 'transaction'
|
||||
};
|
||||
|
||||
const relayerSymmmetricKeyID = "0xd0d905c1c62b810b787141430417caf2b3f54cffadb395b7bb39fdeb8f17266b";
|
||||
|
||||
class StatusGasRelayer {
|
||||
constructor(build, web3) {
|
||||
if (arguments.length !== 2 || !this.validateBuild(build)) throw new Error("Invalid build");
|
||||
|
||||
this.web3 = web3;
|
||||
|
||||
Object.defineProperties(this, {
|
||||
message: {
|
||||
value: build._getMessage(web3),
|
||||
writable: false
|
||||
},
|
||||
topic: {
|
||||
value: web3.utils.toHex(build.contractName).slice(0, 10),
|
||||
writable: false
|
||||
},
|
||||
kid: {
|
||||
value: build.kid,
|
||||
writable: false
|
||||
}
|
||||
});
|
||||
|
||||
if(build.operation === Actions.Transaction){
|
||||
Object.defineProperties(this, {
|
||||
pubKey: {
|
||||
value: build.relayer,
|
||||
writable: false
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Object.defineProperties(this, {
|
||||
skid: {
|
||||
value: build.skid,
|
||||
writable: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
post = async (options) => {
|
||||
options = options || {};
|
||||
|
||||
let pubKey = options.pubKey || this.pubKey;
|
||||
let skid = options.skid || this.skid;
|
||||
|
||||
let kid = options.kid || this.kid;
|
||||
if(!kid){
|
||||
kid = await this.web3.shh.newKeyPair();
|
||||
}
|
||||
|
||||
const sendOptions = {
|
||||
ttl: options.ttl || 1000,
|
||||
sig: kid,
|
||||
powTarget: options.powTarget || 1,
|
||||
powTime: options.powTime || 20,
|
||||
topic: this.topic,
|
||||
payload: this.web3.utils.toHex(this.message)
|
||||
};
|
||||
|
||||
if(pubKey){
|
||||
sendOptions.pubKey = pubKey;
|
||||
} else {
|
||||
if(!skid){
|
||||
skid = await this.web3.shh.addSymKey(relayerSymmmetricKeyID);
|
||||
}
|
||||
sendOptions.symKeyID = skid;
|
||||
}
|
||||
|
||||
const msgId = await this.web3.shh.post(sendOptions);
|
||||
return msgId;
|
||||
}
|
||||
|
||||
validateBuild = (build) => {
|
||||
return (String(build.constructor) === String(StatusGasRelayer.AvailableRelayers) ||
|
||||
String(build.constructor) === String(StatusGasRelayer.Identity) ||
|
||||
String(build.constructor) === String(StatusGasRelayer.SNTController)
|
||||
);
|
||||
}
|
||||
|
||||
static get AvailableRelayers() {
|
||||
return AvailableRelayersAction;
|
||||
}
|
||||
|
||||
static get Identity() {
|
||||
return IdentityGasRelayedAction;
|
||||
}
|
||||
|
||||
static get SNTController() {
|
||||
return SNTControllerAction;
|
||||
}
|
||||
}
|
||||
|
||||
class Action {
|
||||
setGas(token, price, limit){
|
||||
this.gasToken = token;
|
||||
this.gasPrice = price;
|
||||
this.gasLimit = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
setOperation(operation){
|
||||
this.operation = operation;
|
||||
return this;
|
||||
}
|
||||
|
||||
setRelayer(relayer){
|
||||
this.relayer = relayer;
|
||||
return this;
|
||||
}
|
||||
|
||||
setRelayersSymKeyID = (skid) => {
|
||||
this.skid = skid;
|
||||
return this;
|
||||
}
|
||||
|
||||
setAsymmetricKeyID = (kid) => {
|
||||
this.kid = kid;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class IdentityGasRelayedAction extends Action {
|
||||
constructor(contractAddress, accountAddress) {
|
||||
super();
|
||||
this.contractName = Contracts.Identity;
|
||||
this.contractAddress = contractAddress;
|
||||
this.accountAddress = accountAddress;
|
||||
|
||||
this.operation = Actions.Transaction;
|
||||
return this;
|
||||
}
|
||||
|
||||
setContractFunction = contractFunction => {
|
||||
this.contractFunction = contractFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
setTransaction = (to, value, data) => {
|
||||
this.to = to;
|
||||
this.value = value;
|
||||
this.data = data;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
setBaseToken = baseToken => {
|
||||
this.baseToken = baseToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
_nonce = async(contract) => {
|
||||
const nonce = await contract.methods.nonce().call();
|
||||
return nonce;
|
||||
}
|
||||
|
||||
getNonce = async (web3) => {
|
||||
const contract = new web3.eth.Contract(identityGasRelayABI, this.contractAddress);
|
||||
const nonce = await this._nonce(contract);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
sign = async web3 => {
|
||||
const contract = new web3.eth.Contract(identityGasRelayABI, this.contractAddress);
|
||||
const nonce = await this._nonce(contract);
|
||||
let hashedMessage;
|
||||
|
||||
switch(this.contractFunction){
|
||||
case Functions.Identity.call:
|
||||
hashedMessage = await contract.methods.callGasRelayHash(
|
||||
this.to,
|
||||
this.value,
|
||||
web3.utils.soliditySha3({t: 'bytes', v: this.data}),
|
||||
nonce,
|
||||
this.gasPrice,
|
||||
this.gasLimit,
|
||||
this.gasToken
|
||||
).call();
|
||||
break;
|
||||
case Functions.Identity.approveAndCall:
|
||||
hashedMessage = await contract.methods.deployGasRelayHash(
|
||||
this.value,
|
||||
web3.utils.soliditySha3({t: 'bytes', v: this.data}),
|
||||
nonce,
|
||||
this.gasPrice,
|
||||
this.gasLimit,
|
||||
this.gasToken
|
||||
).call();
|
||||
break;
|
||||
default:
|
||||
throw new Error("Function not allowed");
|
||||
}
|
||||
|
||||
const signedMessage = await web3.eth.sign(hashedMessage, this.accountAddress);
|
||||
|
||||
return signedMessage;
|
||||
}
|
||||
|
||||
post = async (signature, web3, options) => {
|
||||
this.nonce = await this.getNonce(web3);
|
||||
this.signature = signature;
|
||||
|
||||
const s = new StatusGasRelayer(this, web3);
|
||||
return s.post(options);
|
||||
}
|
||||
|
||||
_getMessage = web3 => {
|
||||
let jsonAbi = identityGasRelayABI.find(x => x.name == this.contractFunction);
|
||||
let funCall;
|
||||
|
||||
switch(this.contractFunction){
|
||||
case Functions.Identity.call:
|
||||
funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.to,
|
||||
this.value,
|
||||
this.data,
|
||||
this.nonce,
|
||||
this.gasPrice,
|
||||
this.gasLimit,
|
||||
this.gasToken,
|
||||
this.signature
|
||||
]);
|
||||
break;
|
||||
case Functions.Identity.approveAndCall:
|
||||
funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.baseToken,
|
||||
this.to,
|
||||
this.value,
|
||||
this.data,
|
||||
this.nonce,
|
||||
this.gasPrice,
|
||||
this.gasLimit,
|
||||
this.gasToken,
|
||||
this.signature
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Function not allowed");
|
||||
}
|
||||
|
||||
return {
|
||||
'contract': this.contractAddress,
|
||||
'address': this.accountAddress,
|
||||
'action': Actions.Transaction,
|
||||
'encodedFunctionCall': funCall
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SNTControllerAction extends Action {
|
||||
constructor(contractAddress, accountAddress) {
|
||||
super();
|
||||
this.contractName = Contracts.SNT;
|
||||
this.contractAddress = contractAddress;
|
||||
this.accountAddress = accountAddress;
|
||||
|
||||
this.operation = Actions.Transaction;
|
||||
return this;
|
||||
}
|
||||
|
||||
transferSNT = (to, value) => {
|
||||
this.to = to;
|
||||
this.value = value;
|
||||
this.contractFunction = Functions.SNT.transfer;
|
||||
return this;
|
||||
}
|
||||
|
||||
execute = (contract, data) => {
|
||||
this.allowedContract = contract;
|
||||
this.data = data;
|
||||
this.contractFunction = Functions.SNT.execute;
|
||||
return this;
|
||||
}
|
||||
|
||||
_nonce = async(contract) => {
|
||||
const nonce = await contract.methods.signNonce(this.accountAddress).call();
|
||||
return nonce;
|
||||
}
|
||||
|
||||
getNonce = async (web3) => {
|
||||
const contract = new web3.eth.Contract(sntControllerABI, this.contractAddress);
|
||||
const nonce = await this._nonce(contract);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
setGas(price, minimal){
|
||||
this.gasPrice = price;
|
||||
this.gasMinimal = minimal;
|
||||
return this;
|
||||
}
|
||||
|
||||
sign = async web3 => {
|
||||
const contract = new web3.eth.Contract(sntControllerABI, this.contractAddress);
|
||||
const nonce = await this._nonce(contract);
|
||||
let hashedMessage;
|
||||
|
||||
switch(this.contractFunction){
|
||||
case Functions.SNT.execute:
|
||||
hashedMessage = await contract.methods.getExecuteGasRelayedHash(
|
||||
this.allowedContract,
|
||||
this.data,
|
||||
nonce,
|
||||
this.gasPrice,
|
||||
this.gasMinimal,
|
||||
).call();
|
||||
break;
|
||||
case Functions.SNT.transfer:
|
||||
hashedMessage = await contract.methods.getTransferSNTHash(
|
||||
this.to,
|
||||
this.value,
|
||||
nonce,
|
||||
this.gasPrice
|
||||
).call();
|
||||
break;
|
||||
default:
|
||||
throw new Error("Function not allowed");
|
||||
}
|
||||
|
||||
const signedMessage = await web3.eth.sign(hashedMessage, this.accountAddress);
|
||||
|
||||
return signedMessage;
|
||||
}
|
||||
|
||||
post = async (signature, web3, options) => {
|
||||
this.nonce = await this.getNonce(web3);
|
||||
this.signature = signature;
|
||||
const s = new StatusGasRelayer(this, web3);
|
||||
return s.post(options);
|
||||
}
|
||||
|
||||
_getMessage = web3 => {
|
||||
let jsonAbi = sntControllerABI.find(x => x.name == this.contractFunction);
|
||||
let funCall;
|
||||
|
||||
switch(this.contractFunction){
|
||||
case Functions.SNT.execute:
|
||||
funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.allowedContract,
|
||||
this.data,
|
||||
this.nonce,
|
||||
this.gasPrice,
|
||||
this.gasMinimal,
|
||||
this.signature
|
||||
]);
|
||||
break;
|
||||
case Functions.SNT.transfer:
|
||||
funCall = web3.eth.abi.encodeFunctionCall(jsonAbi, [
|
||||
this.to,
|
||||
this.value,
|
||||
this.nonce,
|
||||
this.gasPrice,
|
||||
this.signature
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Function not allowed");
|
||||
}
|
||||
|
||||
return {
|
||||
'contract': this.contractAddress,
|
||||
'address': this.accountAddress,
|
||||
'action': Actions.Transaction,
|
||||
'encodedFunctionCall': funCall
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AvailableRelayersAction extends Action {
|
||||
constructor(contractName, contractAddress, accountAddress) {
|
||||
super();
|
||||
this.contractName = contractName;
|
||||
this.contractAddress = contractAddress;
|
||||
this.accountAddress = accountAddress;
|
||||
|
||||
this.operation = Actions.Availability;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
_getMessage = web3 => {
|
||||
return {
|
||||
contract: this.contractAddress,
|
||||
address: this.accountAddress || web3.eth.defaultAccount,
|
||||
action: Actions.Availability,
|
||||
gasToken: this.gasToken,
|
||||
gasPrice: this.gasPrice
|
||||
};
|
||||
}
|
||||
|
||||
post(web3, options) {
|
||||
const s = new StatusGasRelayer(this, web3);
|
||||
return s.post(options);
|
||||
}
|
||||
}
|
||||
|
||||
const sntControllerABI = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasPrice",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getTransferSNTHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "txHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function",
|
||||
"signature": "0x0c1f1f25"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_allowedContract",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_data",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasPrice",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasMinimal",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getExecuteGasRelayedHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "execHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function",
|
||||
"signature": "0x31c128b1"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasPrice",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "transferSNT",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function",
|
||||
"signature": "0x916b6511"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_allowedContract",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_data",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasPrice",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasMinimal",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "executeGasRelayed",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function",
|
||||
"signature": "0x754e6ab0"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "signNonce",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function",
|
||||
"signature": "0x907920c7"
|
||||
}
|
||||
];
|
||||
|
||||
const identityGasRelayABI = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_dataHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasPrice",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasLimit",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasToken",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "callGasRelayHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_callGasRelayHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function",
|
||||
"signature": "0xe27e2e5c"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "nonce",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function",
|
||||
"signature": "0xaffed0e0"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function",
|
||||
"signature": "0xfd0dded5"
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function",
|
||||
"signature": "0x59f4ac61"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_dataHash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "_nonce",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasPrice",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasLimit",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "_gasToken",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "deployGasRelayHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "_callGasRelayHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function",
|
||||
"signature": "0x86962d85"
|
||||
}
|
||||
];
|
||||
|
||||
export default StatusGasRelayer;
|
|
@ -119,7 +119,7 @@ contract IdentityGasRelay is Identity {
|
|||
uint startGas = gasleft();
|
||||
|
||||
//verify transaction parameters
|
||||
require(startGas >= _gasLimit);
|
||||
//require(startGas >= _gasLimit); // TODO: Tune this
|
||||
require(_nonce == nonce);
|
||||
|
||||
//verify if signatures are valid and came from correct actors;
|
||||
|
@ -255,7 +255,7 @@ contract IdentityGasRelay is Identity {
|
|||
uint startGas = gasleft();
|
||||
|
||||
//verify transaction parameters
|
||||
require(startGas >= _gasLimit);
|
||||
// require(startGas >= _gasLimit); // TODO: tune this
|
||||
require(_nonce == nonce);
|
||||
|
||||
//verify if signatures are valid and came from correct actors;
|
||||
|
|
Loading…
Reference in New Issue