// ContractCall implements ContractCaller.ContractCall, executing the specified // contract with the given input data. func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) { // Create a copy of the current state db to screw around with var ( block *types.Block statedb *state.StateDB ) if pending { block, statedb = b.pendingBlock, b.pendingState.Copy() } else { block = b.blockchain.CurrentBlock() statedb, _ = b.blockchain.State() } // Set infinite balance to the a fake caller account from := statedb.GetOrNewStateObject(common.Address{}) from.SetBalance(common.MaxBig) // Assemble the call invocation to measure the gas usage msg := callmsg{ from: from, to: &contract, gasPrice: new(big.Int), gasLimit: common.MaxBig, value: new(big.Int), data: data, } // Execute the call and return vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil) gaspool := new(core.GasPool).AddGas(common.MaxBig) out, _, err := core.ApplyMessage(vmenv, msg, gaspool) return out, err }
// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the // requested code against the currently pending block/state and returning the used // gas. func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { // Create a copy of the currently pending state db to screw around with var ( block = b.pendingBlock statedb = b.pendingState.Copy() ) // Set infinite balance to the a fake caller account from := statedb.GetOrNewStateObject(sender) from.SetBalance(common.MaxBig) // Assemble the call invocation to measure the gas usage msg := callmsg{ from: from, to: contract, gasPrice: new(big.Int), gasLimit: common.MaxBig, value: value, data: data, } // Execute the call and return vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil) gaspool := new(core.GasPool).AddGas(common.MaxBig) _, gas, err := core.ApplyMessage(vmenv, msg, gaspool) return gas, err }
// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the // requested code against the currently pending block/state and returning the used // gas. func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { // Create a copy of the currently pending state db to screw around with var ( block = b.pendingBlock statedb = b.pendingState.Copy() ) // If there's no code to interact with, respond with an appropriate error if contract != nil { if code := statedb.GetCode(*contract); len(code) == 0 { return nil, bind.ErrNoCode } } // Set infinite balance to the a fake caller account from := statedb.GetOrNewStateObject(sender) from.SetBalance(common.MaxBig) // Assemble the call invocation to measure the gas usage msg := callmsg{ from: from, to: contract, gasPrice: new(big.Int), gasLimit: common.MaxBig, value: value, data: data, } // Execute the call and return vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{}) gaspool := new(core.GasPool).AddGas(common.MaxBig) _, gas, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() return gas, err }
// Call forms a transaction from the given arguments and tries to execute it on // a private VM with a copy of the state. Any changes are therefore only temporary // and not part of the actual state. This allows for local execution/queries. func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { block := be.bc.CurrentBlock() statedb, err := state.New(block.Root(), be.chainDb) if err != nil { return "", "", err } var from *state.StateObject if len(fromStr) == 0 { accounts, err := be.am.Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(accounts[0].Address) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetBalance(common.MaxBig) msg := callmsg{ from: from, gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if len(toStr) > 0 { addr := common.HexToAddress(toStr) msg.to = &addr } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) } header := be.bc.CurrentBlock().Header() vmenv := core.NewEnv(statedb, be.bc, msg, header) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) return common.ToHex(res), gas.String(), err }
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { statedb := self.State().State().Copy() var from *state.StateObject if len(fromStr) == 0 { accounts, err := self.backend.AccountManager().Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(accounts[0].Address) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetBalance(common.MaxBig) from.SetGasLimit(common.MaxBig) msg := callmsg{ from: from, gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if len(toStr) > 0 { addr := common.HexToAddress(toStr) msg.to = &addr } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = self.DefaultGasPrice() } header := self.CurrentBlock().Header() vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, header) res, gas, err := core.ApplyMessage(vmenv, msg, from) return common.ToHex(res), gas.String(), err }
// applies queued transactions originating from address onto the latest state // and creates a block // only used in tests // - could be removed in favour of mining on testdag (natspec e2e + networking) // + filters func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) { block := self.backend.ChainManager().NewBlock(address) coinbase := statedb.GetStateObject(address) coinbase.SetGasPool(big.NewInt(10000000)) txs := self.backend.TxPool().GetQueuedTransactions() for i := 0; i < len(txs); i++ { for _, tx := range txs { if tx.Nonce() == txc { _, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, block), tx, coinbase) if err != nil { panic(err) } txc++ } } } xeth := self.WithState(statedb) return txc, xeth }
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { statedb := self.State().State() //self.eth.ChainManager().TransState() var from *state.StateObject if len(fromStr) == 0 { accounts, err := self.backend.AccountManager().Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(common.BytesToAddress(accounts[0].Address)) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetGasPool(self.backend.ChainManager().GasLimit()) msg := callmsg{ from: from, to: common.HexToAddress(toStr), gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = DefaultGas() } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = DefaultGasPrice() } block := self.CurrentBlock() vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, block) res, gas, err := core.ApplyMessage(vmenv, msg, from) return common.ToHex(res), gas.String(), err }
func (self *testFrontend) applyTxs() { cb := common.HexToAddress(self.coinbase) block := self.ethereum.ChainManager().NewBlock(cb) coinbase := self.stateDb.GetStateObject(cb) coinbase.SetGasPool(big.NewInt(10000000)) txs := self.ethereum.TxPool().GetQueuedTransactions() for i := 0; i < len(txs); i++ { for _, tx := range txs { //self.t.Logf("%v %v %v", i, tx.Nonce(), self.txc) if tx.Nonce() == self.txc { _, gas, err := core.ApplyMessage(core.NewEnv(self.stateDb, self.ethereum.ChainManager(), tx, block), tx, coinbase) //self.ethereum.TxPool().RemoveSet([]*types.Transaction{tx}) self.t.Logf("ApplyMessage: gas %v err %v", gas, err) self.txc++ } } } //self.ethereum.TxPool().RemoveSet(txs) self.xeth = self.xeth.WithState(self.stateDb) }