@@ -12,6 +12,7 @@ import (
12
12
13
13
"github.com/ethereum/go-ethereum/common"
14
14
"github.com/ethereum/go-ethereum/core/vm"
15
+ "github.com/ethereum/go-ethereum/crypto"
15
16
"github.com/ethereum/go-ethereum/libevm"
16
17
"github.com/ethereum/go-ethereum/libevm/ethtest"
17
18
"github.com/ethereum/go-ethereum/libevm/hookstest"
@@ -289,3 +290,65 @@ func contractCode(ops []vm.OpCode) []byte {
289
290
}
290
291
return ret
291
292
}
293
+
294
+ func TestCanCreateContract (t * testing.T ) {
295
+ rng := ethtest .NewPseudoRand (142857 )
296
+ account := rng .Address ()
297
+ slot := rng .Hash ()
298
+
299
+ const gasLimit uint64 = 1e6
300
+ gasUsage := rng .Uint64n (gasLimit )
301
+
302
+ makeErr := func (cc * libevm.AddressContext , stateVal common.Hash ) error {
303
+ return fmt .Errorf ("Origin: %v Caller: %v Contract: %v State: %v" , cc .Origin , cc .Caller , cc .Self , stateVal )
304
+ }
305
+ hooks := & hookstest.Stub {
306
+ CanCreateContractFn : func (cc * libevm.AddressContext , gas uint64 , s libevm.StateReader ) (uint64 , error ) {
307
+ return gas - gasUsage , makeErr (cc , s .GetState (account , slot ))
308
+ },
309
+ }
310
+ hooks .Register (t )
311
+
312
+ origin := rng .Address ()
313
+ caller := rng .Address ()
314
+ value := rng .Hash ()
315
+ code := []byte {byte (vm .STOP )}
316
+ salt := rng .Hash ()
317
+
318
+ create := crypto .CreateAddress (caller , 0 )
319
+ create2 := crypto .CreateAddress2 (caller , salt , crypto .Keccak256 (code ))
320
+
321
+ tests := []struct {
322
+ name string
323
+ create func (* vm.EVM ) ([]byte , common.Address , uint64 , error )
324
+ wantErr error
325
+ }{
326
+ {
327
+ name : "Create" ,
328
+ create : func (evm * vm.EVM ) ([]byte , common.Address , uint64 , error ) {
329
+ return evm .Create (vm .AccountRef (caller ), code , gasLimit , uint256 .NewInt (0 ))
330
+ },
331
+ wantErr : makeErr (& libevm.AddressContext {Origin : origin , Caller : caller , Self : create }, value ),
332
+ },
333
+ {
334
+ name : "Create2" ,
335
+ create : func (evm * vm.EVM ) ([]byte , common.Address , uint64 , error ) {
336
+ return evm .Create2 (vm .AccountRef (caller ), code , gasLimit , uint256 .NewInt (0 ), new (uint256.Int ).SetBytes (salt [:]))
337
+ },
338
+ wantErr : makeErr (& libevm.AddressContext {Origin : origin , Caller : caller , Self : create2 }, value ),
339
+ },
340
+ }
341
+
342
+ for _ , tt := range tests {
343
+ t .Run (tt .name , func (t * testing.T ) {
344
+ state , evm := ethtest .NewZeroEVM (t )
345
+ state .SetState (account , slot , value )
346
+ evm .TxContext .Origin = origin
347
+
348
+ _ , _ , gasRemaining , err := tt .create (evm )
349
+ require .EqualError (t , err , tt .wantErr .Error ())
350
+ // require prints uint64s in hex
351
+ require .Equal (t , int (gasLimit - gasUsage ), int (gasRemaining ), "gas remaining" )
352
+ })
353
+ }
354
+ }
0 commit comments