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 }