Skip to content

Commit

Permalink
Gsn helpers (#334)
Browse files Browse the repository at this point in the history
Initial helper scripts
Fix balance
Fix fund-paymaster
Fix deploy, withdraw
Fix register
- adding workdir to save contracts' artifacts
- fixing gsn configurator to use config.chainId
- fixing relay provider to check for undefined input
- Calling setHub() after deploying paymaster in gsn-helper
- Using transaction.getSenderAddress() which verifies signature while
taking into account chainId for recovery
- removed compiled data.js
- added "prepublish" stemp to compile (ts,sol) and copy compiled
solidity.
- added 'index.ts' entrypoint for all exported items

Co-authored-by: Alex Forshtat <forshtat1@gmail.com>
Co-authored-by: Dror Tirosh <dror@opengsn.org>
  • Loading branch information
3 people authored Apr 24, 2020
1 parent 4499902 commit 81955f9
Show file tree
Hide file tree
Showing 29 changed files with 559 additions and 858 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ node_modules
serverdock/
/dist/
cache
/helpers/compiled/
21 changes: 21 additions & 0 deletions helpers/gsn-balance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const program = require('commander')
const lodash = require('lodash')
const fs = require('fs')

program
.option('-n, --ethereumNodeURL <url>', 'url to the local Ethereum node', 'http://localhost:8545')
.option('--paymaster <address>', 'address of the paymaster contract or relayer owner')
.option('--hub <address>', 'address of the hub contract')
.parse(process.argv)

const nodeURL = program.ethereumNodeURL !== undefined ? program.ethereumNodeURL : 'http://localhost:8545'
const hub = program.hub || JSON.parse(fs.readFileSync('build/gsn/RelayHub.json')).address
const paymaster = program.paymaster || JSON.parse(fs.readFileSync('build/gsn/Paymaster.json')).address
const Web3 = require('web3')
const web3 = new Web3(nodeURL)

const { balance } = require('./src/balance')
const { fromWei } = require('./src/helpers')
balance(web3, {...lodash.pick(program, ['paymaster', 'hub']), hub, paymaster}).then(balance =>
console.error(`Account ${paymaster} has a GSN balance of ${fromWei(balance)} ETH`)
)
19 changes: 19 additions & 0 deletions helpers/gsn-deploy-relay-hub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const program = require('commander')
const lodash = require('lodash')

program
.option('-n, --ethereumNodeURL <url>', 'url to the local Ethereum node', 'http://localhost:8545')
.option('-f, --from <account>', 'account to send transactions from (defaults to first account with balance)')
.option('-w, --workdir <directory>', 'relative work directory (defaults to build/gsn/)', 'build/gsn')
.parse(process.argv)

const nodeURL = program.ethereumNodeURL !== undefined ? program.ethereumNodeURL : 'http://localhost:8545'

const Web3 = require('web3')
const web3 = new Web3(nodeURL)

const { deployRelayHub } = require('./src/deploy')

const opts = lodash.pick(program, ['from', 'workdir'])
opts.verbose = true
deployRelayHub(web3, opts).then(address => console.log(address))
24 changes: 24 additions & 0 deletions helpers/gsn-fund-paymaster.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const program = require('commander')
const lodash = require('lodash')
const fs = require('fs')

program
.option('-n, --ethereumNodeURL <url>', 'url to the local Ethereum node', 'http://localhost:8545')
.option('--paymaster <address>',
'address of the paymaster contract (defaults to address from build/gsn/Paymaster.json if exists')
.option('--amount <amount>', 'amount of funds to deposit for the paymaster contract, in wei (defaults to 1 Ether)')
.option('-f, --from <account>', 'account to send transactions from (defaults to first account with balance)')
.option('--hub <address>',
'address of the RelayHub contract (defaults to address from build/gsn/RelayHub.json if exists')
.parse(process.argv)

const nodeURL = program.ethereumNodeURL !== undefined ? program.ethereumNodeURL : 'http://localhost:8545'
const hub = program.hub || JSON.parse(fs.readFileSync('build/gsn/RelayHub.json')).address
const paymaster = program.paymaster || JSON.parse(fs.readFileSync('build/gsn/Paymaster.json')).address
const Web3 = require('web3')
const web3 = new Web3(nodeURL)

const { fundPaymaster } = require('./src/fund')
fundPaymaster(web3, { ...lodash.pick(program, ['from', 'paymaster', 'amount', 'hub']), hub, paymaster }).then(balance =>
console.error(`Paymaster ${paymaster} balance is now ${balance.toString()} wei`)
)
28 changes: 28 additions & 0 deletions helpers/gsn-register-relayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const program = require('commander')
const lodash = require('lodash')
const fs = require('fs')

program
.option('-n, --ethereumNodeURL <url>', 'url to the local Ethereum node', 'http://localhost:8545')
.option('--relayUrl <url>', 'url to advertise the relayer (defaults to localhost:8090)')
.option('--hub <address>',
'address of the RelayHub contract (defaults to address from build/gsn/RelayHub.json if exists')
.option('--stake <stake>', 'amount to stake for the relayer, in wei (defaults to 1 Ether)')
.option(
'--unstakeDelay <delay>',
'time to wait between deregistering and withdrawing the stake, in seconds (defaults to one week)'
)
.option(
'--funds <funds>',
'amount to transfer to the relayer to pay for relayed transactions, in wei (defaults to 5 Ether)'
)
.option('-f, --from <account>', 'account to send transactions from (defaults to first account with balance)')
.parse(process.argv)

const nodeURL = program.ethereumNodeURL !== undefined ? program.ethereumNodeURL : 'http://localhost:8545'
const hub = program.hub || JSON.parse(fs.readFileSync('build/gsn/RelayHub.json')).address
const Web3 = require('web3')
const web3 = new Web3(nodeURL)

const { registerRelay } = require('./src/register')
registerRelay(web3, { ...lodash.pick(program, ['relayUrl', 'hub', 'stake', 'unstakeDelay', 'funds', 'from']), hub })
25 changes: 25 additions & 0 deletions helpers/gsn-withdraw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const program = require('commander')
const lodash = require('lodash')

program
.option('-n, --ethereumNodeURL <url>', 'url to the local Ethereum node', 'http://localhost:8545')
.option('--from <address>', 'account to withdraw funds from (paymaster/relay manager)')
.option('--to <address>', 'account to send the withdrawn the funds to (defaults to --from)')
.option('--amount <amount>', 'how much to withdraw, in wei (defaults to the whole --from balance)')
.option('--hub <address>', 'address of the hub contract')
.parse(process.argv)

const nodeURL = program.ethereumNodeURL !== undefined ? program.ethereumNodeURL : 'http://localhost:8545'

const Web3 = require('web3')
const web3 = new Web3(nodeURL)

const { withdraw } = require('./src/withdraw')
const { fromWei } = require('./src/helpers')
withdraw(web3, lodash.pick(program, ['from', 'to', 'amount', 'hub'])).then(opts =>
console.error(
`Withdrew ${fromWei(opts.amount)} ETH from ${opts.from} and sent to ${opts.to}, remaining GSN balance is ${fromWei(
opts.remaining
)} ETH`
)
)
12 changes: 12 additions & 0 deletions helpers/gsn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env node

const program = require('commander')

program
.version(require('../package.json').version)
.command('deploy-relay-hub', 'deploy the singleton RelayHub instance')
.command('register-relayer', 'stake for a relayer and fund it')
.command('fund-paymaster', 'fund a paymaster contract so that it can receive relayed calls')
.command('balance', 'query a paymaster or relayer owner GSN balance')
.command('withdraw', 'withdraw a relayer\'s owner revenue')
.parse(process.argv)
21 changes: 21 additions & 0 deletions helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { getRelayHub, isRelayHubDeployed } = require('./src/helpers');
const _ = require('lodash');
const expectError = require('./src/expectError');
const { balance } = require('./src/balance');
const { deployRelayHub } = require('./src/deploy');
const { fundPaymaster } = require('./src/fund');
const { registerRelay } = require('./src/register');
const { relayHub } = require('./src/data');
const { withdraw } = require('./src/withdraw');

module.exports = {
balance,
deployRelayHub,
expectError,
fundPaymaster,
getRelayHub,
isRelayHubDeployed,
registerRelay,
relayHub: _.pick(relayHub, ['abi', 'address', 'bytecode']),
withdraw,
};
12 changes: 12 additions & 0 deletions helpers/src/balance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { getPaymasterAddress, getRelayHub } = require('./helpers')

async function balance (web3, options = {}) {
options.paymaster = getPaymasterAddress(options.paymaster)

const relayHub = getRelayHub(web3, options.hub)
return relayHub.methods.balanceOf(options.paymaster).call()
}

module.exports = {
balance
}
63 changes: 63 additions & 0 deletions helpers/src/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const data = require('./data')
const { defaultFromAccount, saveContractToFile, getRelayHub, getPenalizer, getStakeManager, getPaymaster } = require(
'./helpers')
const { merge } = require('lodash')

async function deployRelayHub (web3, options = {}) {
const defaultOptions = {
from: await defaultFromAccount(web3, options && options.from)
}

options = merge(defaultOptions, options)

if (options.verbose) console.error(`Deploying RelayHub instance`)
const stakeManager = getStakeManager(web3)
const sInstance = await stakeManager.deploy({
data: stakeManager.bytecode
}).send({
from: options.from,
gas: 1e8,
gasPrice: 1e9
})
saveContractToFile(sInstance, options.workdir, 'StakeManager.json')
const penalizer = getPenalizer(web3)
const pInstance = await penalizer.deploy({
data: penalizer.bytecode
}).send({
from: options.from,
gas: 1e8,
gasPrice: 1e9
})
saveContractToFile(pInstance, options.workdir, 'Penalizer.json')
const relayHub = getRelayHub(web3)
console.log('stakeManager ', sInstance.options.address)
console.log('penalizer ', pInstance.options.address)
const rInstance = await relayHub.deploy({
arguments: [16, sInstance.options.address, pInstance.options.address]
}).send({
from: options.from,
gas: 1e8,
gasPrice: 1e9
})
saveContractToFile(rInstance, options.workdir, 'RelayHub.json')
const paymaster = getPaymaster(web3)
const pmInstance = await paymaster.deploy({}).send({
from: options.from,
gas: 1e8,
gasPrice: 1e9
})
saveContractToFile(pmInstance, options.workdir, 'Paymaster.json')
await pmInstance.methods.setHub(rInstance.options.address).send({
from: options.from,
gas: 1e8,
gasPrice: 1e9
})
console.log('paymaster ', pmInstance.options.address)
if (options.verbose) console.error(`RelayHub deployed at ${rInstance.options.address}`)

return rInstance.options.address
}

module.exports = {
deployRelayHub
}
13 changes: 13 additions & 0 deletions helpers/src/expectError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { expect } = require('chai');

const expectError = async function(promise) {
try {
await promise;
} catch (error) {
return;
}

expect.fail('Expected a GSN exception but none was received');
};

module.exports = expectError;
36 changes: 36 additions & 0 deletions helpers/src/fund.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const { defaultFromAccount, ether, getPaymasterAddress, getRelayHub } = require('./helpers')
// const { deployRelayHub } = require('./deploy')
const { merge } = require('lodash')

async function fundPaymaster (web3, options = {}) {
const defaultOptions = {
amount: ether('1'),
from: await defaultFromAccount(web3, options && options.from),
relayHubAddress: options.hub
}

options = merge(defaultOptions, options)

options.paymaster = getPaymasterAddress(options.paymaster)

// // Ensure relayHub is deployed on the local network
// if (options.relayHubAddress.toLowerCase() === data.relayHub.address.toLowerCase()) {
// await deployRelayHub(web3, options);
// }
const relayHub = getRelayHub(web3, options.relayHubAddress)

// I hate js. Use Math.round() instead of parseInt() to support exponent i.e. 1e18
const targetAmount = new web3.utils.BN(Math.round(options.amount).toString())
const currentBalance = new web3.utils.BN(await relayHub.methods.balanceOf(options.paymaster).call())
if (currentBalance.lt(targetAmount)) {
const value = targetAmount.sub(currentBalance)
await relayHub.methods.depositFor(options.paymaster).send({ value, from: options.from })
return targetAmount
} else {
return currentBalance
}
}

module.exports = {
fundPaymaster
}
Loading

0 comments on commit 81955f9

Please sign in to comment.