@ -123,19 +123,20 @@ func (evm *EVM) Cancel() {
atomic . StoreInt32 ( & evm . abort , 1 )
atomic . StoreInt32 ( & evm . abort , 1 )
}
}
// Call executes the contract associated with the addr with the given input as parameters. It also handles any
// Call executes the contract associated with the addr with the given input as
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
// parameters. It also handles any necessary value transfer required and takes
// case of an execution error or failed value transfer.
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func ( evm * EVM ) Call ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 , value * big . Int ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
func ( evm * EVM ) Call ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 , value * big . Int ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
return nil , gas , nil
return nil , gas , nil
}
}
// Depth check execution. Fail if we're trying to execute above the
// Fail if we're trying to execute above the call depth limit
// limit.
if evm . depth > int ( params . CallCreateDepth ) {
if evm . depth > int ( params . CallCreateDepth ) {
return nil , gas , ErrDepth
return nil , gas , ErrDepth
}
}
// Fail if we're trying to transfer more than the available balance
if ! evm . Context . CanTransfer ( evm . StateDB , caller . Address ( ) , value ) {
if ! evm . Context . CanTransfer ( evm . StateDB , caller . Address ( ) , value ) {
return nil , gas , ErrInsufficientBalance
return nil , gas , ErrInsufficientBalance
}
}
@ -173,21 +174,23 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
return ret , contract . Gas , err
return ret , contract . Gas , err
}
}
// CallCode executes the contract associated with the addr with the given input as parameters. It also handles any
// CallCode executes the contract associated with the addr with the given input
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
// as parameters. It also handles any necessary value transfer required and takes
// case of an execution error or failed value transfer.
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
//
//
// CallCode differs from Call in the sense that it executes the given address' code with the caller as context.
// CallCode differs from Call in the sense that it executes the given address'
// code with the caller as context.
func ( evm * EVM ) CallCode ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 , value * big . Int ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
func ( evm * EVM ) CallCode ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 , value * big . Int ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
return nil , gas , nil
return nil , gas , nil
}
}
// Depth check execution. Fail if we're trying to execute above the
// Fail if we're trying to execute above the call depth limit
// limit.
if evm . depth > int ( params . CallCreateDepth ) {
if evm . depth > int ( params . CallCreateDepth ) {
return nil , gas , ErrDepth
return nil , gas , ErrDepth
}
}
// Fail if we're trying to transfer more than the available balance
if ! evm . CanTransfer ( evm . StateDB , caller . Address ( ) , value ) {
if ! evm . CanTransfer ( evm . StateDB , caller . Address ( ) , value ) {
return nil , gas , ErrInsufficientBalance
return nil , gas , ErrInsufficientBalance
}
}
@ -211,18 +214,16 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
return ret , contract . Gas , err
return ret , contract . Gas , err
}
}
// DelegateCall executes the contract associated with the addr with the given input as parameters.
// DelegateCall executes the contract associated with the addr with the given input
// It reverses the state in case of an execution error.
// as parameters. It reverses the state in case of an execution error.
//
//
// DelegateCall differs from CallCode in the sense that it executes the given address' code with the caller as context
// DelegateCall differs from CallCode in the sense that it executes the given address'
// and the caller is set to the caller of the caller.
// code with the caller as context and the caller is set to the caller of the caller.
func ( evm * EVM ) DelegateCall ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
func ( evm * EVM ) DelegateCall ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
return nil , gas , nil
return nil , gas , nil
}
}
// Fail if we're trying to execute above the call depth limit
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm . depth > int ( params . CallCreateDepth ) {
if evm . depth > int ( params . CallCreateDepth ) {
return nil , gas , ErrDepth
return nil , gas , ErrDepth
}
}
@ -232,7 +233,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
to = AccountRef ( caller . Address ( ) )
to = AccountRef ( caller . Address ( ) )
)
)
// Ii nitialise a new contract and make initialise the delegate values
// Initialise a new contract and make initialise the delegate values
contract := NewContract ( caller , to , nil , gas ) . AsDelegate ( )
contract := NewContract ( caller , to , nil , gas ) . AsDelegate ( )
contract . SetCallCode ( & addr , evm . StateDB . GetCodeHash ( addr ) , evm . StateDB . GetCode ( addr ) )
contract . SetCallCode ( & addr , evm . StateDB . GetCodeHash ( addr ) , evm . StateDB . GetCode ( addr ) )
@ -245,18 +246,19 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
return ret , contract . Gas , err
return ret , contract . Gas , err
}
}
// StaticCall executes the contract associated with the addr with the given input
// as parameters while disallowing any modifications to the state during the call.
// Opcodes that attempt to perform such modifications will result in exceptions
// instead of performing the modifications.
func ( evm * EVM ) StaticCall ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
func ( evm * EVM ) StaticCall ( caller ContractRef , addr common . Address , input [ ] byte , gas uint64 ) ( ret [ ] byte , leftOverGas uint64 , err error ) {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
if evm . vmConfig . NoRecursion && evm . depth > 0 {
return nil , gas , nil
return nil , gas , nil
}
}
// Fail if we're trying to execute above the call depth limit
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm . depth > int ( params . CallCreateDepth ) {
if evm . depth > int ( params . CallCreateDepth ) {
return nil , gas , ErrDepth
return nil , gas , ErrDepth
}
}
// Make sure the readonly is only set if we aren't in readonly yet
// make sure the readonly is only set if we aren't in readonly yet
// this makes also sure that the readonly flag isn't removed for
// this makes also sure that the readonly flag isn't removed for
// child calls.
// child calls.
if ! evm . interpreter . readonly {
if ! evm . interpreter . readonly {
@ -268,23 +270,18 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
to = AccountRef ( addr )
to = AccountRef ( addr )
snapshot = evm . StateDB . Snapshot ( )
snapshot = evm . StateDB . Snapshot ( )
)
)
if ! evm . StateDB . Exist ( addr ) {
// Initialise a new contract and set the code that is to be used by the
return nil , gas , nil
// EVM. The contract is a scoped environment for this execution context
}
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped evmironment for this execution context
// only.
// only.
contract := NewContract ( caller , to , new ( big . Int ) , gas )
contract := NewContract ( caller , to , new ( big . Int ) , gas )
contract . SetCallCode ( & addr , evm . StateDB . GetCodeHash ( addr ) , evm . StateDB . GetCode ( addr ) )
contract . SetCallCode ( & addr , evm . StateDB . GetCodeHash ( addr ) , evm . StateDB . GetCode ( addr ) )
ret , err = evm . interpreter . Run ( snapshot , contract , input )
// When an error was returned by the EVM or when setting the creation code
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
// when we're in Homestead this also counts for code storage gas errors.
ret , err = run ( evm , snapshot , contract , input )
if err != nil {
if err != nil {
contract . UseGas ( contract . Gas )
contract . UseGas ( contract . Gas )
evm . StateDB . RevertToSnapshot ( snapshot )
evm . StateDB . RevertToSnapshot ( snapshot )
}
}
return ret , contract . Gas , err
return ret , contract . Gas , err