Fix Metamasks' signatures following EIP 712

This commit is contained in:
apanizo 2018-09-27 10:57:44 +02:00
parent 7fdf94f824
commit c6ff0801fb
2 changed files with 22 additions and 15 deletions

View File

@ -60,19 +60,21 @@ export const executeTransaction = async (
const sigs = getSignaturesFrom(safeAddress, nonce) const sigs = getSignaturesFrom(safeAddress, nonce)
const threshold = await safe.getThreshold() const threshold = await safe.getThreshold()
const gas = await estimateDataGas(safe, to, valueInWei, data, operation, txGasEstimate, 0, nonce, Number(threshold)) const gas =
await estimateDataGas(safe, to, valueInWei, data, operation, txGasEstimate, 0, nonce, Number(threshold), 0)
const numOwners = await safe.getOwners() const numOwners = await safe.getOwners()
const gasIncludingRemovingStoreUpfront = gas + txGasEstimate + (numOwners.length * 15000) const gasIncludingRemovingStoreUpfront = gas + txGasEstimate + (numOwners.length * 15000)
const txReceipt = await safe.execTransactionAndPaySubmitter( const txReceipt = await safe.execTransaction(
to, to,
valueInWei, valueInWei,
data, data,
operation, operation,
txGasEstimate, txGasEstimate,
0, 0, // dataGasEstimate
0, 0, // gasPrice
0, 0, // txGasToken
0, // refundReceiver
sigs, sigs,
{ from: sender, gas: gasIncludingRemovingStoreUpfront, gasPrice }, { from: sender, gas: gasIncludingRemovingStoreUpfront, gasPrice },
) )

View File

@ -32,6 +32,7 @@ export const estimateDataGas = (
gasToken: number, gasToken: number,
nonce: number, nonce: number,
signatureCount: number, signatureCount: number,
refundReceiver: number,
) => { ) => {
// numbers < 256 are 192 -> 31 * 4 + 68 // numbers < 256 are 192 -> 31 * 4 + 68
// numbers < 65k are 256 -> 30 * 4 + 2 * 68 // numbers < 65k are 256 -> 30 * 4 + 2 * 68
@ -41,8 +42,8 @@ export const estimateDataGas = (
const signatureCost = signatureCount * (68 + 2176 + 2176) // array count (3 -> r, s, v) * signature count const signatureCost = signatureCount * (68 + 2176 + 2176) // array count (3 -> r, s, v) * signature count
const sigs = getSignaturesFrom(safe.address, nonce) const sigs = getSignaturesFrom(safe.address, nonce)
const payload = safe.contract.execTransactionAndPaySubmitter const payload = safe.contract.execTransaction
.getData(to, valueInWei, data, operation, txGasEstimate, 0, gasPrice, gasToken, sigs) .getData(to, valueInWei, data, operation, txGasEstimate, 0, gasPrice, gasToken, refundReceiver, sigs)
let dataGasEstimate = estimateDataGasCosts(payload) + signatureCost let dataGasEstimate = estimateDataGasCosts(payload) + signatureCost
if (dataGasEstimate > 65536) { if (dataGasEstimate > 65536) {
@ -95,6 +96,7 @@ const generateTypedDataFrom = async (
// estimateDataGas(safe, to, valueInWei, data, operation, txGasEstimate, txGasToken, nonce, threshold) // estimateDataGas(safe, to, valueInWei, data, operation, txGasEstimate, txGasToken, nonce, threshold)
const dataGasEstimate = 0 const dataGasEstimate = 0
const gasPrice = 0 const gasPrice = 0
const refundReceiver = 0
const typedData = { const typedData = {
types: { types: {
EIP712Domain: [ EIP712Domain: [
@ -103,7 +105,7 @@ const generateTypedDataFrom = async (
name: 'verifyingContract', name: 'verifyingContract',
}, },
], ],
PersonalSafeTx: [ SafeTx: [
{ type: 'address', name: 'to' }, { type: 'address', name: 'to' },
{ type: 'uint256', name: 'value' }, { type: 'uint256', name: 'value' },
{ type: 'bytes', name: 'data' }, { type: 'bytes', name: 'data' },
@ -112,23 +114,25 @@ const generateTypedDataFrom = async (
{ type: 'uint256', name: 'dataGas' }, { type: 'uint256', name: 'dataGas' },
{ type: 'uint256', name: 'gasPrice' }, { type: 'uint256', name: 'gasPrice' },
{ type: 'address', name: 'gasToken' }, { type: 'address', name: 'gasToken' },
{ type: 'address', name: 'refundReceiver' },
{ type: 'uint256', name: 'nonce' }, { type: 'uint256', name: 'nonce' },
], ],
}, },
domain: { domain: {
verifyingContract: safeAddress, verifyingContract: safeAddress,
}, },
primaryType: 'PersonalSafeTx', primaryType: 'SafeTx',
message: { message: {
to, to,
value: valueInWei, value: Number(valueInWei),
data, data,
operation, operation,
safeTxGas: txGasEstimate, safeTxGas: txGasEstimate,
dataGas: dataGasEstimate, dataGas: dataGasEstimate,
gasPrice, gasPrice,
gasToken: txGasToken, gasToken: txGasToken,
nonce, refundReceiver,
nonce: Number(nonce),
}, },
} }
@ -149,11 +153,12 @@ export const generateMetamaskSignature = async (
const web3 = getWeb3() const web3 = getWeb3()
const typedData = const typedData =
await generateTypedDataFrom(safe, safeAddress, to, valueInWei, nonce, data, operation, txGasEstimate) await generateTypedDataFrom(safe, safeAddress, to, valueInWei, nonce, data, operation, txGasEstimate)
const jsonTypedData = JSON.stringify(typedData)
const signedTypedData = { const signedTypedData = {
jsonrpc: '2.0', method: 'eth_signTypedData_v3',
method: 'eth_signTypedData', params: [jsonTypedData, sender],
params: [sender, typedData], from: sender,
id: Date.now(),
} }
const txSignedResponse = await promisify(cb => web3.currentProvider.sendAsync(signedTypedData, cb)) const txSignedResponse = await promisify(cb => web3.currentProvider.sendAsync(signedTypedData, cb))