feat: custom provider that only acts as relayer on low balance and calling specific functions (#300)

* feat: hide token offers if you don't have ETH in your wallet
* fix: code review
* feat: hidde other assets from profile
* fix: code review
* feat: custom provider
* fix: code review
* fix: code revew / reversing condition
This commit is contained in:
Richard Ramos 2019-06-05 11:30:13 -04:00 committed by GitHub
parent 14567debb0
commit 173db39623
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 156 additions and 6 deletions

View File

@ -43,7 +43,7 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
}
function setRelayHubAddress(address _relayHub) public onlyOwner {
init_relay_hub(RelayHub(_relayHub));
set_relay_hub(RelayHub(_relayHub));
}
Arbitration arbitration;

View File

@ -260,6 +260,46 @@ module.exports = {
dappConnection: ["$WEB3"]
},
ropsten: {
tracking: 'shared.ropsten.chains.json',
contracts: {
Escrow: {
args: ["$License", "$Arbitration", "$MetadataStore", "$SNT", BURN_ADDRESS, FEE_AMOUNT],
deps: ['RelayHub'],
onDeploy: [
"Arbitration.methods.setEscrowAddress('$Escrow').send()",
"MetadataStore.methods.setEscrowAddress('$Escrow').send()",
"Escrow.methods.setRelayHubAddress('$RelayHub').send()",
"RelayHub.methods.depositFor('$Escrow').send({value: 300000000000000000})"
]
},
SNT: {
address: "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"
},
"RLPReader": {
deploy: false
},
"RelayHub": {
address: "0x1349584869A1C7b8dc8AE0e93D8c15F5BB3B4B87"
}
},
deployment: {
accounts: [
{
mnemonic: secret.mnemonic,
hdpath: secret.hdpath || "m/44'/60'/0'/0/",
numAddresses: "10"
}
],
host: `ropsten.infura.io/${secret.infuraKey}`,
port: false,
protocol: 'https',
type: "rpc"
},
afterDeploy: dataMigration.bind(null, LICENSE_PRICE, ARB_LICENSE_PRICE, FEE_AMOUNT),
dappConnection: ["$WEB3"]
},
// merges with the settings in default
// used with "embark run livenet"
livenet: {

View File

@ -0,0 +1,46 @@
{
"0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d": {
"contracts": {
"0x3043b04ad856d169c8f0b0509c0bc63192dc7edd92d6933c58708298a0e381be": {
"name": "ENSRegistry",
"address": "0x112234455c3a32fd11230c42e7bccd4a84e02010"
},
"0x4f96b534860cd72e9388b7373c14f4d9bdc201a81bdccdc1b2922865de029497": {
"name": "RelayHub",
"address": "0x1349584869A1C7b8dc8AE0e93D8c15F5BB3B4B87"
},
"0x573ce922ef30ea27239add0fb9f2af8d008314dc4a0b3eaefa0adaf8963e44fa": {
"name": "StandardToken",
"address": "0xEAFb5d3c2c79B48896589ec1dfd1E95ed24D6f93"
},
"0x5cd70a563902729e50887cf8436b89ccf72107e0acf1a98fd78d1b68c0a8edcc": {
"name": "MiniMeTokenFactory",
"address": "0x1B3748Bdc4aF6f6BE159DDDEA0154fa3717cB516"
},
"0x90633e0d0e44dedf48012ba2f1f863ad09468d7fb9793830f6e1a8adbeaaf2e7": {
"name": "SNT",
"address": "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"
},
"0x823f81eb5239fd857afd6bb050d2d628acddcaf2394ef641cd91cf0b8ff874b9": {
"name": "ERC20Receiver",
"address": "0xB59B23736D852b854aE0eE6687c2b90B01A02AB4"
},
"0x2677020cbbcaa18ce69dd8bb8df64aa0e52a0223b292a7a9abb9a9bdef750dd3": {
"name": "License",
"address": "0x0c7e44b251861a8D4E5E1C81E100CAAd4DCD1DEc"
},
"0x744d8dd8d4284e8cdebc5adaf2047826cb846f723c7ec842d12ad5b52678a73a": {
"name": "Arbitration",
"address": "0xaCd119C6049D3cDAe874d73b944a25592233Dd14"
},
"0xf0e3441440660cc814b11ddb03e1e1f801b6208fe8d821643596e92ac3af2450": {
"name": "MetadataStore",
"address": "0x72296A3Bd9bdcdE4bCa5fa63920D40388D84cafB"
},
"0x6736899f25ec619bbd3b81360f73a21009700e238aa3d743aaa8f9456e4ea5d3": {
"name": "Escrow",
"address": "0xe515E50DeB4280a3C4f57509CCA9310B0D75b501"
}
}
}
}

View File

@ -19,7 +19,7 @@ import {sortByDate, sortByRating} from '../../utils/sorters';
import './index.scss';
import {withNamespaces} from "react-i18next";
import {addressCompare} from "../../utils/address";
import {checkEnoughETH, filterValidGaslessOffers} from "../../utils/transaction";
import {checkNotEnoughETH, filterValidGaslessOffers} from "../../utils/transaction";
class OffersList extends Component {
constructor(props) {
@ -89,7 +89,7 @@ class OffersList extends Component {
};
render() {
const notEnoughETH = checkEnoughETH(this.props.gasPrice, this.props.ethBalance);
const notEnoughETH = checkNotEnoughETH(this.props.gasPrice, this.props.ethBalance);
let filteredOffers = filterValidGaslessOffers(this.props.offers, notEnoughETH);
if (this.state.locationCoords) {

View File

@ -14,7 +14,7 @@ import newBuy from "../../features/newBuy";
import network from "../../features/network";
import {addressCompare} from "../../utils/address";
import {checkEnoughETH, filterValidGaslessOffers} from "../../utils/transaction";
import {checkNotEnoughETH, filterValidGaslessOffers} from "../../utils/transaction";
import './index.scss';
import Loading from "../../components/Loading";
@ -39,7 +39,7 @@ class Profile extends Component {
const {profile, prices, address} = this.props;
if(!profile || !prices) return <Loading page={true} />;
const notEnoughETH = checkEnoughETH(this.props.gasPrice, this.props.ethBalance);
const notEnoughETH = checkNotEnoughETH(this.props.gasPrice, this.props.ethBalance);
const filteredOffers = filterValidGaslessOffers(profile.offers, notEnoughETH);
return (

56
src/js/provider.js Normal file
View File

@ -0,0 +1,56 @@
/* global web3 */
import Escrow from '../embarkArtifacts/contracts/Escrow';
import {checkNotEnoughETH} from './utils/transaction';
import {addressCompare} from './utils/address';
const VALID_OPERATIONS = {
"cancel(uint256)": "40e58ee5",
"create(address,uint256,uint256,uint8,uint256,bytes,string,string)": "a63c5162",
"openCase(uint256,string)": "58b67904",
"pay(uint256)": "c290d691"
};
class Provider {
constructor(origProvider, relayProvider) {
this.origProvider = origProvider;
this.relayProvider = relayProvider;
this.origProviderSend = (this.origProvider['sendAsync'] || this.origProvider['send']).bind(this.origProvider);
this.relayProviderSend = (this.relayProvider['sendAsync'] || this.relayProvider['send']).bind(this.relayProvider);
}
send(payload, callback) {
const params = payload.params[0];
if(!(params && params.to && addressCompare(params.to, Escrow.options.address.toLowerCase()) &&
payload.method === "eth_sendTransaction" &&
Object.values(VALID_OPERATIONS).includes(params.data.substring(2, 10)))){
this.origProviderSend(payload, callback);
return;
}
(async () => {
const balance = await web3.eth.getBalance(web3.eth.defaultAccount);
const gasPrice = await web3.eth.getGasPrice();
if(checkNotEnoughETH(gasPrice, balance)){
// Increase 120%.
// Normally we would use gaspriceFactorPercent on tabookey.RelayProvider
// but this version of web3 does a getPrice before send() if the gas price is null
// to set this gas price as a parameter. Tabookey will then use this value directly
// without applying the factor percent
const useGasPrice = web3.utils.toBN(gasPrice).mul(web3.utils.toBN("120")).div(web3.utils.toBN("100"));
payload.params[0].gasPrice = web3.utils.toHex(useGasPrice);
this.relayProviderSend(payload, function (error, result) {
callback(error, result);
});
} else {
this.origProviderSend(payload, callback);
}
})();
}
sendAsync(payload, callback) {
return this.send(payload, callback);
}
}
export default Provider;

View File

@ -1,6 +1,8 @@
/*global web3*/
import EmbarkJS from '../../embarkArtifacts/embarkjs';
import {contactCodeRegExp} from '../utils/address';
import TellerProvider from '../provider';
import tabookey from 'tabookey-gasless';
export function onReady() {
return new Promise((resolve, reject) => {
@ -9,6 +11,12 @@ export function onReady() {
return reject(err);
}
// A relay gets compensated whenever it relays a transaction: whatever the gas usage it pays,
// it gets back the same plus the "txFee" precent - that is, it gets back ( (txFee+100)*gasUsed ) / 100
const relayProvider = new tabookey.RelayProvider(web3.currentProvider, { txfee: 12 });
const customProvider = new TellerProvider(web3.currentProvider, relayProvider);
web3.setProvider(customProvider);
resolve();
});
});

View File

@ -13,7 +13,7 @@ export const calculateEscrowPrice = (escrow, prices) => {
const toBN = web3.utils.toBN;
export const checkEnoughETH = (gasPrice, ethBalance) => {
export const checkNotEnoughETH = (gasPrice, ethBalance) => {
const relayGasPrice = toBN(gasPrice || '0').mul(toBN(120)).div(toBN(100)); // 120%. toBN doesnt like decimals?
return toBN(web3.utils.toWei(ethBalance || '0', 'ether')).lt(toBN(500000).mul(relayGasPrice)); // only allow ETH if less than 500000*gasPrice
};