From dd707f00784dff2e3abe94d86f2cd6b6eacc627f Mon Sep 17 00:00:00 2001 From: Richard Meissner Date: Tue, 2 Oct 2018 15:48:56 +0200 Subject: [PATCH] add check if nonce or code at address --- lib/opFns.js | 11 ++++++---- lib/runCall.js | 55 ++++++++++++++++++++++++++++++++------------------ package.json | 2 +- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/lib/opFns.js b/lib/opFns.js index 039530de5b..2d94414b20 100644 --- a/lib/opFns.js +++ b/lib/opFns.js @@ -520,7 +520,7 @@ module.exports = { checkOutOfGas(runState, options) makeCall(runState, options, localOpts, done) }, - CREATE2: function (value, offset, length, runState, done) { + CREATE2: function (value, offset, length, salt, runState, done) { if (!runState._common.gteHardfork('constantinople')) { trap(ERROR.INVALID_OPCODE) } @@ -534,17 +534,20 @@ module.exports = { // set up config var options = { value: value, - data: data + data: data, + salt: salt.toBuffer('be', 32) } var localOpts = { inOffset: offset, inLength: length, outOffset: new BN(0), - outLength: new BN(0), - salt: salt + outLength: new BN(0) } + // Deduct gas costs for hashing + // TODO this is not yet part of the tests + // subGas(runState, new BN(runState._common.param('gasPrices', 'sha3Word')).imul(length.divCeil(new BN(32)))) checkCallMemCost(runState, options, localOpts) checkOutOfGas(runState, options) makeCall(runState, options, localOpts, done) diff --git a/lib/runCall.js b/lib/runCall.js index bdc23750b4..709cd1e488 100644 --- a/lib/runCall.js +++ b/lib/runCall.js @@ -5,6 +5,7 @@ const BN = ethUtil.BN const exceptions = require('./exceptions.js') const ERROR = exceptions.ERROR +const EMPTY_CODE_HASH = ethUtil.keccak256() /** * runs a CALL operation @@ -69,39 +70,53 @@ module.exports = function (opts, cb) { code = txData txData = undefined var newNonce = new BN(account.nonce).subn(1) - + if (salt) { createdAddress = toAddress = ethUtil.generateAddress2(caller, salt, code) } else { createdAddress = toAddress = ethUtil.generateAddress(caller, newNonce.toArray()) } - stateManager.clearContractStorage(createdAddress, function (err) { + stateManager.getAccount(createdAddress, function (err, account) { if (err) { done(err) + return } - async.series([ - newContractEvent, - getAccount - ], done) - - function newContractEvent (callback) { - self.emit('newContract', { - address: createdAddress, - code: code - }, callback) + if ((account.nonce && new BN(account.nonce) > 0) || account.codeHash.compare(EMPTY_CODE_HASH) != 0) { + done(ERROR.INVALID_OPCODE) + return } - function getAccount (callback) { - stateManager.getAccount(createdAddress, function (err, account) { - toAccount = account - const NONCE_OFFSET = 1 - toAccount.nonce = new BN(toAccount.nonce).addn(NONCE_OFFSET).toArrayLike(Buffer) - callback(err) - }) - } + stateManager.clearContractStorage(createdAddress, function (err) { + if (err) { + done(err) + return + } + + async.series([ + newContractEvent, + getAccount + ], done) + + function newContractEvent (callback) { + self.emit('newContract', { + address: createdAddress, + code: code + }, callback) + } + + function getAccount (callback) { + stateManager.getAccount(createdAddress, function (err, account) { + toAccount = account + const NONCE_OFFSET = 1 + toAccount.nonce = new BN(toAccount.nonce).addn(NONCE_OFFSET).toArrayLike(Buffer) + callback(err) + }) + } + }) }) + } else { // else load the `to` account toAccount = stateManager.cache.get(toAddress) diff --git a/package.json b/package.json index 3f1e5c9229..0767b4385c 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "ethereumjs-account": "^2.0.3", "ethereumjs-block": "~2.0.1", "ethereumjs-common": "~0.4.0", - "ethereumjs-util": "git+https://github.com/ethereumjs/ethereumjs-util#create2", + "ethereumjs-util": "git+https://github.com/ethereumjs/ethereumjs-util.git#create2", "fake-merkle-patricia-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1", "merkle-patricia-tree": "^2.1.2",