// 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 defer statedb.RevertToSnapshot(statedb.Snapshot()) } else { block = b.blockchain.CurrentBlock() statedb, _ = b.blockchain.State() } // If there's no code to interact with, respond with an appropriate error if code := statedb.GetCode(contract); len(code) == 0 { return nil, bind.ErrNoCode } // 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, chainConfig, b.blockchain, msg, block.Header(), vm.Config{}) gaspool := new(core.GasPool).AddGas(common.MaxBig) out, _, err := core.ApplyMessage(vmenv, msg, gaspool) return out, err }
func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error { // validate post state accounts in test file against what we have in state db for addrString, acct := range t.postAccounts { // XXX: is is worth it checking for errors here? addr, err := hex.DecodeString(addrString) if err != nil { return err } code, err := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) if err != nil { return err } balance, ok := new(big.Int).SetString(acct.Balance, 0) if !ok { return err } nonce, err := strconv.ParseUint(prepInt(16, acct.Nonce), 16, 64) if err != nil { return err } // address is indirectly verified by the other fields, as it's the db key code2 := statedb.GetCode(common.BytesToAddress(addr)) balance2 := statedb.GetBalance(common.BytesToAddress(addr)) nonce2 := statedb.GetNonce(common.BytesToAddress(addr)) if !bytes.Equal(code2, code) { return fmt.Errorf("account code mismatch for addr: %s want: %s have: %s", addrString, hex.EncodeToString(code), hex.EncodeToString(code2)) } if balance2.Cmp(balance) != 0 { return fmt.Errorf("account balance mismatch for addr: %s, want: %d, have: %d", addrString, balance, balance2) } if nonce2 != nonce { return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addrString, nonce, nonce2) } } return nil }