MCPcopy Create free account
hub / github.com/CPChain/chain / Create

Method Create

core/vm/evm.go:337–410  ·  view source on GitHub ↗

Create creates a new contract using code as deployment code.

(caller ContractRef, code []byte, gas uint64, value *big.Int)

Source from the content-addressed store, hash-verified

335
336// Create creates a new contract using code as deployment code.
337func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
338 // Depth check execution. Fail if we're trying to execute above the
339 // limit.
340 if evm.depth > int(configs.CallCreateDepth) {
341 return nil, common.Address{}, gas, ErrDepth
342 }
343 if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
344 return nil, common.Address{}, gas, ErrInsufficientBalance
345 }
346 // Ensure there's no existing contract already at the designated address
347 nonce := evm.StateDB.GetNonce(caller.Address())
348 evm.StateDB.SetNonce(caller.Address(), nonce+1)
349
350 contractAddr = crypto.CreateAddress(caller.Address(), nonce)
351 contractHash := evm.StateDB.GetCodeHash(contractAddr)
352 if evm.StateDB.GetNonce(contractAddr) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) {
353 return nil, common.Address{}, 0, ErrContractAddressCollision
354 }
355 // Create a new account on the state
356 snapshot := evm.StateDB.Snapshot()
357 evm.StateDB.CreateAccount(contractAddr)
358 evm.StateDB.SetNonce(contractAddr, 1)
359 evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value)
360
361 // initialise a new contract and set the code that is to be used by the
362 // EVM. The contract is a scoped environment for this execution context
363 // only.
364 contract := NewContract(caller, AccountRef(contractAddr), value, gas)
365 contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
366
367 if evm.vmConfig.NoRecursion && evm.depth > 0 {
368 return nil, contractAddr, gas, nil
369 }
370
371 if evm.vmConfig.Debug && evm.depth == 0 {
372 evm.vmConfig.Tracer.CaptureStart(caller.Address(), contractAddr, true, code, gas, value)
373 }
374 start := time.Now()
375
376 ret, err = run(evm, contract, nil)
377
378 // check whether the max code size has been exceeded
379 maxCodeSizeExceeded := len(ret) > configs.MaxCodeSize
380 // if the contract creation ran successfully and no errors were returned
381 // calculate the gas required to store the code. If the code could not
382 // be stored due to not enough gas set an error and let it be handled
383 // by the error checking condition below.
384 if err == nil && !maxCodeSizeExceeded {
385 createDataGas := uint64(len(ret)) * configs.CreateDataGas
386 if contract.UseGas(createDataGas) {
387 evm.StateDB.SetCode(contractAddr, ret)
388 } else {
389 err = ErrCodeStoreOutOfGas
390 }
391 }
392
393 // When an error was returned by the EVM or when setting the creation code
394 // above we revert to the snapshot and consume any gas remaining. Additionally

Callers

nothing calls this directly

Calls 15

SetCallCodeMethod · 0.95
UseGasMethod · 0.95
NewContractFunction · 0.85
AccountRefTypeAlias · 0.85
runFunction · 0.70
AddressMethod · 0.65
GetNonceMethod · 0.65
SetNonceMethod · 0.65
GetCodeHashMethod · 0.65
SnapshotMethod · 0.65
CreateAccountMethod · 0.65
CaptureStartMethod · 0.65

Tested by

no test coverage detected