mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge branch 'master' of github.com:MetaMask/metamask-extension into openlinkinnewwindow
This commit is contained in:
commit
29bad56410
@ -2,6 +2,15 @@
|
||||
|
||||
## Current Master
|
||||
|
||||
## 4.5.3 Wed Apr 04 2018
|
||||
|
||||
- Fix bug where checksum address are messing with balance issue [#3843](https://github.com/MetaMask/metamask-extension/issues/3843)
|
||||
- new ui: fix the confirm transaction screen
|
||||
|
||||
## 4.5.2 Wed Apr 04 2018
|
||||
|
||||
- Fix overly strict validation where transactions were rejected with hex encoded "chainId"
|
||||
|
||||
## 4.5.1 Tue Apr 03 2018
|
||||
|
||||
- Fix default network (should be mainnet not Rinkeby)
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "__MSG_appName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "4.5.1",
|
||||
"version": "4.5.3",
|
||||
"manifest_version": 2,
|
||||
"author": "https://metamask.io",
|
||||
"description": "__MSG_appDescription__",
|
||||
|
@ -131,7 +131,11 @@ function documentElementCheck () {
|
||||
}
|
||||
|
||||
function blacklistedDomainCheck () {
|
||||
var blacklistedDomains = ['uscourts.gov', 'dropbox.com']
|
||||
var blacklistedDomains = [
|
||||
'uscourts.gov',
|
||||
'dropbox.com',
|
||||
'webbyawards.com',
|
||||
]
|
||||
var currentUrl = window.location.href
|
||||
var currentRegex
|
||||
for (let i = 0; i < blacklistedDomains.length; i++) {
|
||||
|
@ -185,7 +185,8 @@ module.exports = class TransactionController extends EventEmitter {
|
||||
|
||||
async addUnapprovedTransaction (txParams) {
|
||||
// validate
|
||||
await this.txGasUtil.validateTxParams(txParams)
|
||||
this._validateTxParams(txParams)
|
||||
this._normalizeTxParams(txParams)
|
||||
// construct txMeta
|
||||
let txMeta = this.txStateManager.generateTxMeta({txParams})
|
||||
this.addTx(txMeta)
|
||||
@ -215,7 +216,6 @@ module.exports = class TransactionController extends EventEmitter {
|
||||
}
|
||||
txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16))
|
||||
txParams.value = txParams.value || '0x0'
|
||||
if (txParams.to === null) delete txParams.to
|
||||
// set gasLimit
|
||||
return await this.txGasUtil.analyzeGasUsage(txMeta)
|
||||
}
|
||||
@ -314,6 +314,61 @@ module.exports = class TransactionController extends EventEmitter {
|
||||
// PRIVATE METHODS
|
||||
//
|
||||
|
||||
_normalizeTxParams (txParams) {
|
||||
delete txParams.chainId
|
||||
|
||||
if ( !txParams.to ) {
|
||||
delete txParams.to
|
||||
} else {
|
||||
txParams.to = ethUtil.addHexPrefix(txParams.to)
|
||||
}
|
||||
txParams.from = ethUtil.addHexPrefix(txParams.from).toLowerCase()
|
||||
|
||||
if (!txParams.data) {
|
||||
delete txParams.data
|
||||
} else {
|
||||
txParams.data = ethUtil.addHexPrefix(txParams.data)
|
||||
}
|
||||
|
||||
if (txParams.value) txParams.value = ethUtil.addHexPrefix(txParams.value)
|
||||
|
||||
if (txParams.gas) txParams.gas = ethUtil.addHexPrefix(txParams.gas)
|
||||
if (txParams.gasPrice) txParams.gas = ethUtil.addHexPrefix(txParams.gas)
|
||||
}
|
||||
|
||||
_validateTxParams (txParams) {
|
||||
this._validateFrom(txParams)
|
||||
this._validateRecipient(txParams)
|
||||
if ('value' in txParams) {
|
||||
const value = txParams.value.toString()
|
||||
if (value.includes('-')) {
|
||||
throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`)
|
||||
}
|
||||
|
||||
if (value.includes('.')) {
|
||||
throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_validateFrom (txParams) {
|
||||
if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`)
|
||||
if (!ethUtil.isValidAddress(txParams.from)) throw new Error('Invalid from address')
|
||||
}
|
||||
|
||||
_validateRecipient (txParams) {
|
||||
if (txParams.to === '0x' || txParams.to === null ) {
|
||||
if (txParams.data) {
|
||||
delete txParams.to
|
||||
} else {
|
||||
throw new Error('Invalid recipient address')
|
||||
}
|
||||
} else if ( txParams.to !== undefined && !ethUtil.isValidAddress(txParams.to) ) {
|
||||
throw new Error('Invalid recipient address')
|
||||
}
|
||||
return txParams
|
||||
}
|
||||
|
||||
_markNonceDuplicatesDropped (txId) {
|
||||
this.txStateManager.setTxStatusConfirmed(txId)
|
||||
// get the confirmed transactions nonce and from address
|
||||
|
@ -4,7 +4,7 @@ const {
|
||||
BnMultiplyByFraction,
|
||||
bnToHex,
|
||||
} = require('./util')
|
||||
const { addHexPrefix, isValidAddress } = require('ethereumjs-util')
|
||||
const { addHexPrefix } = require('ethereumjs-util')
|
||||
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
|
||||
|
||||
/*
|
||||
@ -100,37 +100,4 @@ module.exports = class TxGasUtil {
|
||||
// otherwise use blockGasLimit
|
||||
return bnToHex(upperGasLimitBn)
|
||||
}
|
||||
|
||||
async validateTxParams (txParams) {
|
||||
this.validateFrom(txParams)
|
||||
this.validateRecipient(txParams)
|
||||
if ('value' in txParams) {
|
||||
const value = txParams.value.toString()
|
||||
if (value.includes('-')) {
|
||||
throw new Error(`Invalid transaction value of ${txParams.value} not a positive number.`)
|
||||
}
|
||||
|
||||
if (value.includes('.')) {
|
||||
throw new Error(`Invalid transaction value of ${txParams.value} number must be in wei`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validateFrom (txParams) {
|
||||
if ( !(typeof txParams.from === 'string') ) throw new Error(`Invalid from address ${txParams.from} not a string`)
|
||||
if (!isValidAddress(txParams.from)) throw new Error('Invalid from address')
|
||||
}
|
||||
|
||||
validateRecipient (txParams) {
|
||||
if (txParams.to === '0x' || txParams.to === null ) {
|
||||
if (txParams.data) {
|
||||
delete txParams.to
|
||||
} else {
|
||||
throw new Error('Invalid recipient address')
|
||||
}
|
||||
} else if ( txParams.to !== undefined && !isValidAddress(txParams.to) ) {
|
||||
throw new Error('Invalid recipient address')
|
||||
}
|
||||
return txParams
|
||||
}
|
||||
}
|
@ -143,7 +143,7 @@ module.exports = class TransactionStateManager extends EventEmitter {
|
||||
// validate types
|
||||
switch (key) {
|
||||
case 'chainId':
|
||||
if (typeof value !== 'number') throw new Error(`${key} in txParams is not a Number. got: (${value})`)
|
||||
if (typeof value !== 'number' && typeof value !== 'string') throw new Error(`${key} in txParams is not a Number or hex string. got: (${value})`)
|
||||
break
|
||||
default:
|
||||
if (typeof value !== 'string') throw new Error(`${key} in txParams is not a string. got: (${value})`)
|
||||
|
45
app/scripts/migrations/024.js
Normal file
45
app/scripts/migrations/024.js
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
const version = 24
|
||||
|
||||
/*
|
||||
|
||||
This migration ensures that the from address in txParams is to lower case for
|
||||
all unapproved transactions
|
||||
|
||||
*/
|
||||
|
||||
const clone = require('clone')
|
||||
|
||||
module.exports = {
|
||||
version,
|
||||
|
||||
migrate: function (originalVersionedData) {
|
||||
const versionedData = clone(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
const state = versionedData.data
|
||||
const newState = transformState(state)
|
||||
versionedData.data = newState
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
||||
function transformState (state) {
|
||||
const newState = state
|
||||
const transactions = newState.TransactionController.transactions
|
||||
|
||||
newState.TransactionController.transactions = transactions.map((txMeta, _, txList) => {
|
||||
if (
|
||||
txMeta.status === 'unapproved' &&
|
||||
txMeta.txParams &&
|
||||
txMeta.txParams.from
|
||||
) {
|
||||
txMeta.txParams.from = txMeta.txParams.from.toLowerCase()
|
||||
}
|
||||
return txMeta
|
||||
})
|
||||
return newState
|
||||
}
|
@ -34,4 +34,5 @@ module.exports = [
|
||||
require('./021'),
|
||||
require('./022'),
|
||||
require('./023'),
|
||||
require('./024'),
|
||||
]
|
||||
|
37
test/unit/migrations/024-test.js
Normal file
37
test/unit/migrations/024-test.js
Normal file
@ -0,0 +1,37 @@
|
||||
const assert = require('assert')
|
||||
const migration24 = require('../../../app/scripts/migrations/024')
|
||||
const properTime = (new Date()).getTime()
|
||||
const storage = {
|
||||
"meta": {},
|
||||
"data": {
|
||||
"TransactionController": {
|
||||
"transactions": [
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const transactions = []
|
||||
|
||||
|
||||
while (transactions.length <= 10) {
|
||||
transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'unapproved' })
|
||||
transactions.push({ txParams: { from: '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675' }, status: 'confirmed' })
|
||||
}
|
||||
|
||||
|
||||
storage.data.TransactionController.transactions = transactions
|
||||
|
||||
describe('storage is migrated successfully and the txParams.from are lowercase', () => {
|
||||
it('should lowercase the from for unapproved txs', (done) => {
|
||||
migration24.migrate(storage)
|
||||
.then((migratedData) => {
|
||||
const migratedTransactions = migratedData.data.TransactionController.transactions
|
||||
migratedTransactions.forEach((tx) => {
|
||||
if (tx.status === 'unapproved') assert.equal(tx.txParams.from, '0x8acce2391c0d510a6c5e5d8f819a678f79b7e675')
|
||||
else assert.equal(tx.txParams.from, '0x8aCce2391c0d510a6c5E5d8f819a678f79b7e675')
|
||||
})
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
})
|
@ -210,31 +210,98 @@ describe('Transaction Controller', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#validateTxParams', function () {
|
||||
it('does not throw for positive values', function (done) {
|
||||
describe('#_validateTxParams', function () {
|
||||
it('does not throw for positive values', function () {
|
||||
var sample = {
|
||||
from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
value: '0x01',
|
||||
}
|
||||
txController.txGasUtil.validateTxParams(sample).then(() => {
|
||||
done()
|
||||
}).catch(done)
|
||||
txController._validateTxParams(sample)
|
||||
})
|
||||
|
||||
it('returns error for negative values', function (done) {
|
||||
it('returns error for negative values', function () {
|
||||
var sample = {
|
||||
from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
value: '-0x01',
|
||||
}
|
||||
txController.txGasUtil.validateTxParams(sample)
|
||||
.then(() => done('expected to thrown on negativity values but didn\'t'))
|
||||
.catch((err) => {
|
||||
try {
|
||||
txController._validateTxParams(sample)
|
||||
} catch (err) {
|
||||
assert.ok(err, 'error')
|
||||
done()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('#_normalizeTxParams', () => {
|
||||
it('should normalize txParams', () => {
|
||||
let txParams = {
|
||||
chainId: '0x1',
|
||||
from: 'a7df1beDBF813f57096dF77FCd515f0B3900e402',
|
||||
to: null,
|
||||
data: '68656c6c6f20776f726c64',
|
||||
}
|
||||
|
||||
txController._normalizeTxParams(txParams)
|
||||
|
||||
assert(!txParams.chainId, 'their should be no chainId')
|
||||
assert(!txParams.to, 'their should be no to address if null')
|
||||
assert.equal(txParams.from.slice(0, 2), '0x', 'from should be hexPrefixd')
|
||||
assert.equal(txParams.data.slice(0, 2), '0x', 'data should be hexPrefixd')
|
||||
|
||||
txParams.to = 'a7df1beDBF813f57096dF77FCd515f0B3900e402'
|
||||
|
||||
txController._normalizeTxParams(txParams)
|
||||
assert.equal(txParams.to.slice(0, 2), '0x', 'to should be hexPrefixd')
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
describe('#_validateRecipient', () => {
|
||||
it('removes recipient for txParams with 0x when contract data is provided', function () {
|
||||
const zeroRecipientandDataTxParams = {
|
||||
from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
to: '0x',
|
||||
data: 'bytecode',
|
||||
}
|
||||
const sanitizedTxParams = txController._validateRecipient(zeroRecipientandDataTxParams)
|
||||
assert.deepEqual(sanitizedTxParams, { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', data: 'bytecode' }, 'no recipient with 0x')
|
||||
})
|
||||
|
||||
it('should error when recipient is 0x', function () {
|
||||
const zeroRecipientTxParams = {
|
||||
from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
to: '0x',
|
||||
}
|
||||
assert.throws(() => { txController._validateRecipient(zeroRecipientTxParams) }, Error, 'Invalid recipient address')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('#_validateFrom', () => {
|
||||
it('should error when from is not a hex string', function () {
|
||||
|
||||
// where from is undefined
|
||||
const txParams = {}
|
||||
assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`)
|
||||
|
||||
// where from is array
|
||||
txParams.from = []
|
||||
assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`)
|
||||
|
||||
// where from is a object
|
||||
txParams.from = {}
|
||||
assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`)
|
||||
|
||||
// where from is a invalid address
|
||||
txParams.from = 'im going to fail'
|
||||
assert.throws(() => { txController._validateFrom(txParams) }, Error, `Invalid from address`)
|
||||
|
||||
// should run
|
||||
txParams.from ='0x1678a085c290ebd122dc42cba69373b5953b831d'
|
||||
txController._validateFrom(txParams)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addTx', function () {
|
||||
it('should emit updates', function (done) {
|
||||
const txMeta = {
|
||||
|
@ -11,46 +11,4 @@ describe('Tx Gas Util', function () {
|
||||
provider,
|
||||
})
|
||||
})
|
||||
|
||||
it('removes recipient for txParams with 0x when contract data is provided', function () {
|
||||
const zeroRecipientandDataTxParams = {
|
||||
from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
to: '0x',
|
||||
data: 'bytecode',
|
||||
}
|
||||
const sanitizedTxParams = txGasUtil.validateRecipient(zeroRecipientandDataTxParams)
|
||||
assert.deepEqual(sanitizedTxParams, { from: '0x1678a085c290ebd122dc42cba69373b5953b831d', data: 'bytecode' }, 'no recipient with 0x')
|
||||
})
|
||||
|
||||
it('should error when recipient is 0x', function () {
|
||||
const zeroRecipientTxParams = {
|
||||
from: '0x1678a085c290ebd122dc42cba69373b5953b831d',
|
||||
to: '0x',
|
||||
}
|
||||
assert.throws(() => { txGasUtil.validateRecipient(zeroRecipientTxParams) }, Error, 'Invalid recipient address')
|
||||
})
|
||||
|
||||
it('should error when from is not a hex string', function () {
|
||||
|
||||
// where from is undefined
|
||||
const txParams = {}
|
||||
assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`)
|
||||
|
||||
// where from is array
|
||||
txParams.from = []
|
||||
assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`)
|
||||
|
||||
// where from is a object
|
||||
txParams.from = {}
|
||||
assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address ${txParams.from} not a string`)
|
||||
|
||||
// where from is a invalid address
|
||||
txParams.from = 'im going to fail'
|
||||
assert.throws(() => { txGasUtil.validateFrom(txParams) }, Error, `Invalid from address`)
|
||||
|
||||
// should run
|
||||
txParams.from ='0x1678a085c290ebd122dc42cba69373b5953b831d'
|
||||
txGasUtil.validateFrom(txParams)
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -32,10 +32,10 @@ EnsInput.prototype.render = function () {
|
||||
const network = this.props.network
|
||||
const networkHasEnsSupport = getNetworkEnsSupport(network)
|
||||
|
||||
if (!networkHasEnsSupport) return
|
||||
|
||||
props.onChange(recipient)
|
||||
|
||||
if (!networkHasEnsSupport) return
|
||||
|
||||
if (recipient.match(ensRE) === null) {
|
||||
return this.setState({
|
||||
loadingEns: false,
|
||||
|
@ -237,6 +237,7 @@ ConfirmSendEther.prototype.getData = function () {
|
||||
const { identities } = this.props
|
||||
const txMeta = this.gatherTxMeta()
|
||||
const txParams = txMeta.txParams || {}
|
||||
const account = identities ? identities[txParams.from] || {} : {}
|
||||
const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH, gasFeeInHex } = this.getGasFee()
|
||||
const { FIAT: amountInFIAT, ETH: amountInETH } = this.getAmount()
|
||||
|
||||
@ -252,7 +253,7 @@ ConfirmSendEther.prototype.getData = function () {
|
||||
return {
|
||||
from: {
|
||||
address: txParams.from,
|
||||
name: identities[txParams.from].name,
|
||||
name: account.name,
|
||||
},
|
||||
to: {
|
||||
address: txParams.to,
|
||||
|
Loading…
Reference in New Issue
Block a user