CallCode executes the contract associated with the addr with the given input as parameters. It also handles any necessary value transfer required and takes the necessary steps to create accounts and reverses the state in case of an execution error or failed value transfer. CallCode differs from Cal
(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int)
| 219 | // CallCode differs from Call in the sense that it executes the given address' |
| 220 | // code with the caller as context. |
| 221 | func (evm *EVM) callCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { |
| 222 | if evm.vmConfig.NoRecursion && evm.depth > 0 { |
| 223 | return nil, gas, nil |
| 224 | } |
| 225 | |
| 226 | // Fail if we're trying to execute above the call depth limit |
| 227 | if evm.depth > int(configs.CallCreateDepth) { |
| 228 | return nil, gas, ErrDepth |
| 229 | } |
| 230 | // Fail if we're trying to transfer more than the available balance |
| 231 | if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { |
| 232 | return nil, gas, ErrInsufficientBalance |
| 233 | } |
| 234 | |
| 235 | var ( |
| 236 | snapshot = evm.StateDB.Snapshot() |
| 237 | to = AccountRef(caller.Address()) |
| 238 | ) |
| 239 | // initialise a new contract and set the code that is to be used by the |
| 240 | // EVM. The contract is a scoped environment for this execution context |
| 241 | // only. |
| 242 | contract := NewContract(caller, to, value, gas) |
| 243 | contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) |
| 244 | |
| 245 | ret, err = run(evm, contract, input) |
| 246 | if err != nil { |
| 247 | evm.StateDB.RevertToSnapshot(snapshot) |
| 248 | if err != errExecutionReverted { |
| 249 | contract.UseGas(contract.Gas) |
| 250 | } |
| 251 | } |
| 252 | return ret, contract.Gas, err |
| 253 | } |
| 254 | |
| 255 | func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { |
| 256 | realAddress := GetRealContractAddress(evm, caller, addr, gas) |
no test coverage detected