@@ -5,6 +5,7 @@ const BN = ethUtil.BN
5
5
const exceptions = require ( './exceptions.js' )
6
6
7
7
const ERROR = exceptions . ERROR
8
+ const EMPTY_CODE_HASH = ethUtil . keccak256 ( )
8
9
9
10
/**
10
11
* runs a CALL operation
@@ -47,6 +48,7 @@ module.exports = function (opts, cb) {
47
48
var selfdestruct = opts . selfdestruct || opts . suicides
48
49
var delegatecall = opts . delegatecall || false
49
50
var isStatic = opts . static || false
51
+ var salt = opts . salt || null
50
52
51
53
txValue = new BN ( txValue )
52
54
@@ -77,41 +79,14 @@ module.exports = function (opts, cb) {
77
79
code = txData
78
80
txData = undefined
79
81
var newNonce = new BN ( account . nonce ) . subn ( 1 )
80
- createdAddress = toAddress = ethUtil . generateAddress ( caller , newNonce . toArray ( ) )
81
- stateManager . clearContractStorage ( createdAddress , function ( err ) {
82
- if ( err ) {
83
- done ( err )
84
- }
85
82
86
- async . series ( [
87
- newContractEvent ,
88
- getAccount
89
- ] , done )
90
-
91
- function newContractEvent ( callback ) {
92
- /**
93
- * The `newContract` event when a contract is created
94
- *
95
- * @event Event: newContract
96
- * @type {Object }
97
- * @property {Buffer } address the created address for the new contract (type `Buffer | Uint8Array`)
98
- * @property {Buffer } code the deployment bytecode for reference (type `Buffer | Uint8Array`)
99
- */
100
- self . emit ( 'newContract' , {
101
- address : createdAddress ,
102
- code : code
103
- } , callback )
104
- }
83
+ if ( salt ) {
84
+ createdAddress = toAddress = ethUtil . generateAddress2 ( caller , salt , code )
85
+ } else {
86
+ createdAddress = toAddress = ethUtil . generateAddress ( caller , newNonce . toArray ( ) )
87
+ }
105
88
106
- function getAccount ( callback ) {
107
- stateManager . getAccount ( createdAddress , function ( err , account ) {
108
- toAccount = account
109
- const NONCE_OFFSET = 1
110
- toAccount . nonce = new BN ( toAccount . nonce ) . addn ( NONCE_OFFSET ) . toArrayLike ( Buffer )
111
- callback ( err )
112
- } )
113
- }
114
- } )
89
+ checkAccountState ( createdAddress , setupNewContract , done )
115
90
} else {
116
91
// else load the `to` account
117
92
stateManager . getAccount ( toAddress , function ( err , account ) {
@@ -121,6 +96,53 @@ module.exports = function (opts, cb) {
121
96
}
122
97
}
123
98
99
+ function checkAccountState ( address , next , done ) {
100
+ stateManager . getAccount ( address , function ( err , account ) {
101
+ if ( err ) {
102
+ done ( err )
103
+ return
104
+ }
105
+
106
+ if ( ( account . nonce && new BN ( account . nonce ) > 0 ) || account . codeHash . compare ( EMPTY_CODE_HASH ) !== 0 ) {
107
+ toAccount = account
108
+ code = new Buffer ( '0xfe' , 'hex' ) // Invalid init code
109
+ done ( )
110
+ return
111
+ }
112
+
113
+ next ( address , done )
114
+ } )
115
+ }
116
+
117
+ function setupNewContract ( address , done ) {
118
+ stateManager . clearContractStorage ( address , function ( err ) {
119
+ if ( err ) {
120
+ done ( err )
121
+ return
122
+ }
123
+
124
+ async . series ( [
125
+ newContractEvent ,
126
+ getAccount
127
+ ] , done )
128
+
129
+ function newContractEvent ( callback ) {
130
+ self . emit ( 'newContract' , {
131
+ address : address ,
132
+ code : code
133
+ } , callback )
134
+ }
135
+
136
+ function getAccount ( callback ) {
137
+ stateManager . getAccount ( address , function ( err , account ) {
138
+ toAccount = account
139
+ toAccount . nonce = new BN ( toAccount . nonce ) . addn ( 1 ) . toArrayLike ( Buffer )
140
+ callback ( err )
141
+ } )
142
+ }
143
+ } )
144
+ }
145
+
124
146
function subTxValue ( cb ) {
125
147
if ( delegatecall ) {
126
148
cb ( )
0 commit comments