Create creates a new contract using code as deployment code.
(caller ContractRef, code []byte, gas uint64, value *big.Int)
| 335 | |
| 336 | // Create creates a new contract using code as deployment code. |
| 337 | func (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 |
nothing calls this directly
no test coverage detected