github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/vm/contract.go (about)

     1  package vm
     2  
     3  import (
     4  	"math/big"
     5  
     6  	"github.com/quickchainproject/quickchain/common"
     7  )
     8  
     9  // ContractRef is a reference to the contract's backing object
    10  type ContractRef interface {
    11  	Address() common.Address
    12  }
    13  
    14  // AccountRef implements ContractRef.
    15  //
    16  // Account references are used during EVM initialisation and
    17  // it's primary use is to fetch addresses. Removing this object
    18  // proves difficult because of the cached jump destinations which
    19  // are fetched from the parent contract (i.e. the caller), which
    20  // is a ContractRef.
    21  type AccountRef common.Address
    22  
    23  // Address casts AccountRef to a Address
    24  func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
    25  
    26  // Contract represents an quickchain contract in the state database. It contains
    27  // the the contract code, calling arguments. Contract implements ContractRef
    28  type Contract struct {
    29  	// CallerAddress is the result of the caller which initialised this
    30  	// contract. However when the "call method" is delegated this value
    31  	// needs to be initialised to that of the caller's caller.
    32  	CallerAddress common.Address
    33  	caller        ContractRef
    34  	self          ContractRef
    35  
    36  	jumpdests destinations // result of JUMPDEST analysis.
    37  
    38  	Code     []byte
    39  	CodeHash common.Hash
    40  	CodeAddr *common.Address
    41  	Input    []byte
    42  
    43  	Gas   uint64
    44  	value *big.Int
    45  
    46  	Args []byte
    47  
    48  	DelegateCall bool
    49  }
    50  
    51  // NewContract returns a new contract environment for the execution of EVM.
    52  func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
    53  	c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
    54  
    55  	if parent, ok := caller.(*Contract); ok {
    56  		// Reuse JUMPDEST analysis from parent context if available.
    57  		c.jumpdests = parent.jumpdests
    58  	} else {
    59  		c.jumpdests = make(destinations)
    60  	}
    61  
    62  	// Gas should be a pointer so it can safely be reduced through the run
    63  	// This pointer will be off the state transition
    64  	c.Gas = gas
    65  	// ensures a value is set
    66  	c.value = value
    67  
    68  	return c
    69  }
    70  
    71  // AsDelegate sets the contract to be a delegate call and returns the current
    72  // contract (for chaining calls)
    73  func (c *Contract) AsDelegate() *Contract {
    74  	c.DelegateCall = true
    75  	// NOTE: caller must, at all times be a contract. It should never happen
    76  	// that caller is something other than a Contract.
    77  	parent := c.caller.(*Contract)
    78  	c.CallerAddress = parent.CallerAddress
    79  	c.value = parent.value
    80  
    81  	return c
    82  }
    83  
    84  // GetOp returns the n'th element in the contract's byte array
    85  func (c *Contract) GetOp(n uint64) OpCode {
    86  	return OpCode(c.GetByte(n))
    87  }
    88  
    89  // GetByte returns the n'th byte in the contract's byte array
    90  func (c *Contract) GetByte(n uint64) byte {
    91  	if n < uint64(len(c.Code)) {
    92  		return c.Code[n]
    93  	}
    94  
    95  	return 0
    96  }
    97  
    98  // Caller returns the caller of the contract.
    99  //
   100  // Caller will recursively call caller when the contract is a delegate
   101  // call, including that of caller's caller.
   102  func (c *Contract) Caller() common.Address {
   103  	return c.CallerAddress
   104  }
   105  
   106  // UseGas attempts the use gas and subtracts it and returns true on success
   107  func (c *Contract) UseGas(gas uint64) (ok bool) {
   108  	if c.Gas < gas {
   109  		return false
   110  	}
   111  	c.Gas -= gas
   112  	return true
   113  }
   114  
   115  // Address returns the contracts address
   116  func (c *Contract) Address() common.Address {
   117  	return c.self.Address()
   118  }
   119  
   120  // Value returns the contracts value (sent to it from it's caller)
   121  func (c *Contract) Value() *big.Int {
   122  	return c.value
   123  }
   124  
   125  // SetCode sets the code to the contract
   126  func (c *Contract) SetCode(hash common.Hash, code []byte) {
   127  	c.Code = code
   128  	c.CodeHash = hash
   129  }
   130  
   131  // SetCallCode sets the code of the contract and address of the backing data
   132  // object
   133  func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
   134  	c.Code = code
   135  	c.CodeHash = hash
   136  	c.CodeAddr = addr
   137  }