Using Embark default ERC20Token, and changed way to determine if contract instance is valid

This commit is contained in:
Richard Ramos 2018-04-25 14:49:13 -04:00
parent 6c90a57cad
commit dd262752c2
13 changed files with 2244 additions and 303 deletions

View File

@ -1,272 +0,0 @@
[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "version",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
},
{
"name": "_extraData",
"type": "bytes"
}
],
"name": "approveAndCall",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "remaining",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"inputs": [
{
"name": "_initialAmount",
"type": "uint256"
},
{
"name": "_tokenName",
"type": "string"
},
{
"name": "_decimalUnits",
"type": "uint8"
},
{
"name": "_tokenSymbol",
"type": "string"
}
],
"type": "constructor"
},
{
"payable": false,
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
}
]

View File

@ -0,0 +1,191 @@
{
"contract_name": "ERC20Token",
"code": "",
"runtime_bytecode": "",
"real_runtime_bytecode": "",
"swarm_hash": "",
"gas_estimates": null,
"function_hashes": {
"allowance(address,address)": "dd62ed3e",
"approve(address,uint256)": "095ea7b3",
"balanceOf(address)": "70a08231",
"totalSupply()": "18160ddd",
"transfer(address,uint256)": "a9059cbb",
"transferFrom(address,address,uint256)": "23b872dd"
},
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "remaining",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -30,9 +30,10 @@
"contracts":{ "contracts":{
"IdentityGasRelay": { "IdentityGasRelay": {
"abiFile": "../abi/IdentityGasRelay.json",
"isIdentity": true, "isIdentity": true,
"factoryAddress": "0x18f71378f4735b35e01eb71afcc66df090eccea7", "factoryAddress": "0x18f71378f4735b35e01eb71afcc66df090eccea7",
"abiFile": "../abi/IdentityGasRelay.json", "kernelVerification": "isKernel(address _addr)",
"allowedFunctions": [ "allowedFunctions": [
{ {
"function": "approveAndCallGasRelayed(address,address,uint256,bytes,uint256,uint256,uint256,address,bytes)", "function": "approveAndCallGasRelayed(address,address,uint256,bytes,uint256,uint256,uint256,address,bytes)",
@ -58,9 +59,9 @@
] ]
}, },
"SNTController": { "SNTController": {
"abiFile": "../abi/SNTController.json",
"isIdentity": false, "isIdentity": false,
"address": "0x96f0811c6484c59c2674da1f64e725c01d82c1b5", "address": "0x96f0811c6484c59c2674da1f64e725c01d82c1b5",
"abiFile": "../abi/SNTController.json",
"allowedFunctions": [ "allowedFunctions": [
{ {
"function":"transferSNT(address,uint256,uint256,uint256,bytes)", "function":"transferSNT(address,uint256,uint256,uint256,bytes)",

View File

@ -2,9 +2,10 @@
"name": "gas-relayer", "name": "gas-relayer",
"version": "0.0.1", "version": "0.0.1",
"description": "Gas relayer to avoid having to hold ether to perform transactions when you already have a token", "description": "Gas relayer to avoid having to hold ether to perform transactions when you already have a token",
"main": "index.js", "main": "src/service.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/service.js"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",

View File

@ -11,8 +11,6 @@ class ContractSettings {
this.events = eventEmitter; this.events = eventEmitter;
this.pendingToLoad = 0; this.pendingToLoad = 0;
this.events.on('setup:bytecode-address', this._obtainContractBytecode.bind(this))
} }
process(){ process(){
@ -41,21 +39,11 @@ class ContractSettings {
} }
} }
_determineBytecodeAddress(topicName, i){ _obtainContractBytecode(topicName){
let contractAddress = this.contracts[topicName].address; if(this.contracts[topicName].isIdentity) return;
if(this.contracts[topicName].isIdentity){
this.pendingToLoad++;
const lastKernelSignature = "0x4ac99424"; // REFACTOR
this.web3.eth.call({to: this.contracts[topicName].factoryAddress, data: lastKernelSignature})
.then(kernel => {
contractAddress = '0x' + kernel.slice(26);
this.events.emit('setup:bytecode-address', topicName, contractAddress);
})
}
}
_obtainContractBytecode(topicName, contractAddress){ this.pendingToLoad++;
this.web3.eth.getCode(contractAddress) this.web3.eth.getCode(this.contracts[topicName].address)
.then(code => { .then(code => {
this.contracts[topicName].code = md5(code); this.contracts[topicName].code = md5(code);
this.pendingToLoad--; this.pendingToLoad--;
@ -90,7 +78,7 @@ class ContractSettings {
_processContracts(){ _processContracts(){
for(let contractName in this.contracts){ for(let contractName in this.contracts){
// Obtaining the abis // Obtaining the abis
this.contracts[contractName].abi = require(this.contracts[contractName].abiFile); this.contracts[contractName].abi = require(this.contracts[contractName].abiFile).abi;
const topicName = this.getTopicName(contractName); const topicName = this.getTopicName(contractName);
@ -100,7 +88,7 @@ class ContractSettings {
this.contracts[topicName].name = contractName; this.contracts[topicName].name = contractName;
delete this.contracts[contractName]; delete this.contracts[contractName];
this._determineBytecodeAddress(topicName); this._obtainContractBytecode(topicName);
this._extractFunctions(topicName); this._extractFunctions(topicName);
} }

View File

@ -1,5 +1,5 @@
const md5 = require('md5'); const md5 = require('md5');
const erc20ABI = require('../abi/ERC20.json'); const erc20ABI = require('../abi/ERC20Token.json');
const ganache = require("ganache-cli"); const ganache = require("ganache-cli");
class MessageProcessor { class MessageProcessor {
@ -26,7 +26,7 @@ class MessageProcessor {
} }
} }
async _validateInput(message, input){ async _validateInput(message, input){
const contract = this.settings.getContractByTopic(message.topic); const contract = this.settings.getContractByTopic(message.topic);
@ -56,6 +56,15 @@ class MessageProcessor {
} }
async _validateInstance(message, input){
const contract = this.settings.getContractByTopic(message.topic);
const kernelVerifSignature = this.web3.utils.sha3(contract.kernelVerification).slice(0, 10)
return await this.web3.eth.call({
to: contract.factoryAddress,
data: kernelVerifSignature + "000000000000000000000000" + input.address});
}
_extractInput(message){ _extractInput(message){
return { return {
address: message.payload.slice(0, 42), address: message.payload.slice(0, 42),
@ -73,6 +82,7 @@ class MessageProcessor {
} }
} }
_getFactor(input, contract, gasToken){ _getFactor(input, contract, gasToken){
if(contract.allowedFunctions[input.functionName].isToken){ if(contract.allowedFunctions[input.functionName].isToken){
return this.web3.utils.toBN(this.settings.getToken(gasToken).pricePlugin.getFactor()); return this.web3.utils.toBN(this.settings.getToken(gasToken).pricePlugin.getFactor());
@ -87,14 +97,14 @@ class MessageProcessor {
if(token.symbol == "ETH") if(token.symbol == "ETH")
return new this.web3.utils.BN(await this.web3.eth.getBalance(input.address)); return new this.web3.utils.BN(await this.web3.eth.getBalance(input.address));
else { else {
const Token = new this.web3.eth.Contract(erc20ABI); const Token = new this.web3.eth.Contract(erc20ABI.abi);
Token.options.address = params('gasToken'); Token.options.address = params('gasToken');
return new this.web3.utils.BN(await Token.methods.balanceOf(input.address).call()); return new this.web3.utils.BN(await Token.methods.balanceOf(input.address).call());
} }
} }
_estimateGas(input){ async _estimateGas(input){
const web3Sim = new Web3(ganache.provider({fork: `${this.config.node.protocol}://${this.config.node.host}:${this.config.node.port}`})); const web3Sim = new Web3(ganache.provider({fork: `${this.config.node.protocol}://${this.config.node.host}:${this.config.node.port}`}));
const simAccounts = await web3Sim.eth.getAccounts(); const simAccounts = await web3Sim.eth.getAccounts();
let simulatedReceipt = await web3Sim.eth.sendTransaction({ let simulatedReceipt = await web3Sim.eth.sendTransaction({
@ -121,6 +131,9 @@ class MessageProcessor {
if(!this._validateInput(message, input)) return; // TODO Log if(!this._validateInput(message, input)) return; // TODO Log
if(contract.isIdentity)
if(!this._validateInstance(message, input)) return;
const params = this._obtainParametersFunc(contract, input); const params = this._obtainParametersFunc(contract, input);
const token = this.settings.getToken(params('gasToken')); const token = this.settings.getToken(params('gasToken'));

View File

@ -40,7 +40,7 @@ $(function(){
$('button').on('click', async function(e){ $('button').on('click', async function(e){
e.preventDefault(); e.preventDefault();
$('p.result').text(''); $('p.result, #messageArea').text('');
let sKey = add0x($("#sKey")); let sKey = add0x($("#sKey"));
let msgTopic = add0x($('#topic')); let msgTopic = add0x($('#topic'));

View File

@ -15,6 +15,24 @@
], ],
"gas": "auto", "gas": "auto",
"contracts": { "contracts": {
"Identity": {"deploy": false},
"IdentityFactory": {"deploy": false},
"SafeMath": {"deploy": false},
"DelayedUpdatableInstance": {"deploy": false},
"DelayedUpdatableInstanceStorage": {"deploy": false},
"Factory": {"deploy": false},
"Instance": {"deploy": false},
"InstanceStorage": {"deploy": false},
"MiniMeToken": {"deploy": false},
"MiniMeTokenFactory": {"deploy": false},
"UpdatableInstance": {"deploy": false},
"Controlled": {"deploy": false},
"Owned": {"deploy": false},
"IdentityGasRelay": {"deploy": false},
"IdentityKernel": {"deploy": false},
"SNTController": {"deploy": false},
"UpdatedIdentityKernel": {"deploy": false},
"TestContract": {"deploy": false}
} }
} }
} }

View File

@ -50,6 +50,10 @@ contract Factory is Controlled {
); );
} }
function isKernel(address _addr) public returns (bool){
return versionMap[_addr] > 0;
}
function getCodeHash(address _addr) function getCodeHash(address _addr)
public public
view view

View File

@ -6,6 +6,6 @@ import "./Identity.sol";
contract IdentityKernel is DelayedUpdatableInstanceStorage, Identity { contract IdentityKernel is DelayedUpdatableInstanceStorage, Identity {
function initIdentity(address _caller) external { function initIdentity(address _caller) external {
_constructIdentity(_caller); _constructIdentity(keccak256(_caller));
} }
} }