Coder Social home page Coder Social logo

trufflesuite / ganache Goto Github PK

View Code? Open in Web Editor NEW
2.6K 52.0 675.0 458.41 MB

:warning: The Truffle Suite is being sunset. For information on ongoing support, migration options and FAQs, visit the Consensys blog. Thank you for all the support over the years.

Home Page: https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat?utm_source=github&utm_medium=referral&utm_campaign=2023_Sep_truffle-sunset-2023_announcement_

License: MIT License

JavaScript 0.40% Solidity 7.79% TypeScript 91.75% Dockerfile 0.06%
ganache ethereum blockchain

ganache's Introduction

Ganache

A tool for creating a local blockchain for fast Ethereum development.

FeaturesGetting StartedDocumentationCommunityDockerContributingRelated


Features

Ganache is an Ethereum simulator that makes developing Ethereum applications faster, easier, and safer. It includes all popular RPC functions and features (like events) and can be run deterministically to make development a breeze.

  • console.log in Solidity
  • Zero-config Mainnet Forking
  • Fork any Ethereum network without waiting to sync
  • Ethereum JSON-RPC support
  • Snapshot/revert state
  • Mine blocks instantly, on demand, or at an interval
  • Fast-forward time
  • Impersonate any account (no private keys required!)
  • Listens for JSON-RPC 2.0 requests over HTTP/WebSockets
  • Programmatic use in Node.js
  • Pending Transactions
  • Flavors (aka Plugins), like Filecoin

Getting Started

Ganache can be used from the command line, programmatically via Node.js, or in the browser.

Command line use

You must first install Node.js >= v16.0.0 and npm >= 7.10.0.

To install Ganache globally, run:

$ npm install ganache --global

In case you're upgrading from a previous version of Ganache, we've also written up this handy guide on how to upgrade/install Ganache and to document all breaking changes to look out for.

Once installed globally, you can start ganache right from your command line:

ganache

Your output should look something like this:

Ganache CLI v6.12.1 (ganache-core: 2.13.1)

Available Accounts
==================
(0) 0xe261e26aECcE52b3788Fac9625896FFbc6bb4424 (100 ETH)
(1) 0xcE16e8eb8F4BF2E65BA9536C07E305b912BAFaCF (100 ETH)
(2) 0x02f1c4C93AFEd946Cce5Ad7D34354A150bEfCFcF (100 ETH)
(3) 0x0B75F0b70076Fab3F18F94700Ecaf3B00fE528E7 (100 ETH)
(4) 0x7194d1F1d43c2c58302BB61a224D41B649e65C93 (100 ETH)
(5) 0xC9A2d92c5913eDEAd9a7C936C96631F0F2241063 (100 ETH)
(6) 0xD79BcDE5Cb11cECD1dfC6685B65690bE5b6a611e (100 ETH)
(7) 0xb6D080353f40dEcA2E67108087c356d3A1AfcD64 (100 ETH)
(8) 0x31A064DeeaD74DE7B9453beB4F780416D8859d3b (100 ETH)
(9) 0x37524a360a40C682F201Fb011DB7bbC8c8A247c6 (100 ETH)

Private Keys
==================
(0) 0x7f109a9e3b0d8ecfba9cc23a3614433ce0fa7ddcc80f2a8f10b222179a5a80d6
(1) 0x6ec1f2e7d126a74a1d2ff9e1c5d90b92378c725e506651ff8bb8616a5c724628
(2) 0xb4d7f7e82f61d81c95985771b8abf518f9328d019c36849d4214b5f995d13814
(3) 0x941536648ac10d5734973e94df413c17809d6cc5e24cd11e947e685acfbd12ae
(4) 0x5829cf333ef66b6bdd34950f096cb24e06ef041c5f63e577b4f3362309125863
(5) 0x8fc4bffe2b40b2b7db7fd937736c4575a0925511d7a0a2dfc3274e8c17b41d20
(6) 0xb6c10e2baaeba1fa4a8b73644db4f28f4bf0912cceb6e8959f73bb423c33bd84
(7) 0xfe8875acb38f684b2025d5472445b8e4745705a9e7adc9b0485a05df790df700
(8) 0xbdc6e0a69f2921a78e9af930111334a41d3fab44653c8de0775572c526feea2d
(9) 0x3e215c3d2a59626a669ed04ec1700f36c05c9b216e592f58bbfd3d8aa6ea25f9

HD Wallet
==================
Mnemonic:      candy maple velvet cake sugar cream honey rich smooth crumble sweet treat
Base HD Path:  m/44'/60'/0'/0/{account_index}

Default Gas Price
==================
20000000000

Gas Limit
==================
6721975

Call Gas Limit
==================
9007199254740991

Listening on 127.0.0.1:8545

NPM project use

If you want to install Ganache into an npm project, run:

$ npm install ganache

You can then add Ganache to your package.json scripts:

"scripts": {
  "ganache": "ganache --wallet.seed myCustomSeed"
}

See Documentation for additional command line options.

Then start it:

$ npm run ganache

Programmatic use

You can use Ganache programmatically from Node.js. Install Ganache into your npm package:

$ npm install ganache

Then you can use ganache as an EIP-1193 provider only, an EIP-1193 provider and JSON-RPC web server, as a Web3 provider, an ethers provider, or a viem transport.

As an EIP-1193 provider only:

const ganache = require("ganache");

const options = {};
const provider = ganache.provider(options);
const accounts = await provider.request({ method: "eth_accounts", params: [] });

As an EIP-1193 provider and JSON-RPC web server:

const ganache = require("ganache");

const options = {};
const server = ganache.server(options);
const PORT = 0; // 0 means any available port
server.listen(PORT, async err => {
  if (err) throw err;

  console.log(`ganache listening on port ${server.address().port}...`);
  const provider = server.provider;
  const accounts = await provider.request({
    method: "eth_accounts",
    params: []
  });
});

As a web3.js provider:

To use ganache as a Web3 provider:

const Web3 = require("web3");
const ganache = require("ganache");

const web3 = new Web3(ganache.provider());

NOTE: depending on your web3 version, you may need to set a number of confirmation blocks

const web3 = new Web3(ganache.provider(), null, { transactionConfirmationBlocks: 1 });

As an ethers.js provider:

const ganache = require("ganache");

const provider = new ethers.providers.Web3Provider(ganache.provider());

As a viem transport:

To use a ganache provider as a viem transport:

import { createWalletClient, custom } from "viem";
import { localhost } from "viem/chains";
import ganache from "ganache";
const client = createWalletClient({
  chain: localhost,
  transport: custom(ganache.provider())
});

Browser Use

You can also use Ganache in the browser by adding the following script to your HTML:

<script src="https://cdn.jsdelivr.net/npm/ganache@{VERSION}/dist/web/ganache.min.js"></script>

NOTE: the {VERSION} in the above path needs to be replaced with a version number or tag that is listed in npm.

From there, Ganache is available in your browser for use:

const options = {};
const provider = Ganache.provider(options);

Documentation

See our Interactive Docs for a full list of Ganache's RPC methods.

Startup Options

The startup options are grouped in the chain, database, fork, logging, miner, wallet, and server namespaces, and should be used as such on startup, i.e.

ganache --namespace.option="value"

for CLI use, and

const options = { namespace: { option: "value"}};
const provider = ganache.provider(options);

for programmatic use.

The following options are listed for command line use, but can also be used when running Ganache programmatically in your project.

Chain:
  --chain.allowUnlimitedContractSize    Allows unlimited contract sizes while debugging. Setting this to true
                                        will cause ganache to behave differently than production environments.
                                                                                    [boolean] [default: false]

  --chain.allowUnlimitedInitCodeSize    Allows unlimited initcode sizes while debugging. Setting this to true
                                        will cause ganache to behave differently than production environments.
                                                                                    [boolean] [default: false]

  --chain.asyncRequestProcessing        When set to false only one request will be processed at a time.
                                                                                     [boolean] [default: true]

  --chain.chainId                       The currently configured chain id.            [number] [default: 1337]

  -i, --chain.networkId                 The id of the network returned by the RPC method net_version.
                                        deprecated aliases: --networkId
                                                            [number] [default: System time at process start or
                                                               Network ID of forked blockchain if configured.]

  -t, --chain.time                      Date that the first block should start.
                                        deprecated aliases: --time                                    [number]

  -k, --chain.hardfork                  Set the hardfork rules for the EVM.
                                        deprecated aliases: --hardfork
          [string] [choices: "constantinople", "byzantium", "petersburg", "istanbul", "muirGlacier", "berlin",
                           "london", "arrowGlacier", "grayGlacier", "merge", "shanghai"] [default: "shanghai"]

  --chain.vmErrorsOnRPCResponse         Whether to report runtime errors from EVM code as RPC errors.
                                                                                    [boolean] [default: false]


Database:
  --database.dbPath                     Specify a path to a directory to save the chain database.
                                        deprecated aliases: --db, --db_path                           [string]

Logging:
  --logging.debug                       Set to true to log EVM opcodes.             [boolean] [default: false]

  -q, --logging.quiet                   Set to true to disable logging.
                                        deprecated aliases: --quiet                 [boolean] [default: false]

  -v, --logging.verbose                 Set to true to log detailed RPC requests.
                                        deprecated aliases: --verbose               [boolean] [default: false]


Miner:
  -b, --miner.blockTime                 Sets the blockTime in seconds for automatic mining. A blockTime of 0
                                        enables "instamine mode", where new executable transactions will be
                                        mined instantly.
                                        deprecated aliases: --blockTime                  [number] [default: 0]

  -g, --miner.defaultGasPrice           Sets the default gas price in WEI for transactions if not otherwise
                                        specified.
                                        deprecated aliases: --gasPrice          [string] [default: 0x77359400]

  -l, --miner.blockGasLimit             Sets the block gas limit in WEI.
                                        deprecated aliases: --gasLimit            [string] [default: 0xb71b00]

  --miner.defaultTransactionGasLimit    Sets the default transaction gas limit in WEI. Set to "estimate" to
                                        use an estimate (slows down transaction execution by 40%+).
                                                                                   [string] [default: 0x15f90]

  --miner.difficulty                    Sets the block difficulty.                     [string] [default: 0x1]

  --miner.callGasLimit                  Sets the transaction gas limit in WEI for eth_call and eth_estimateGas
                                        calls.
                                                                                 [string] [default: 0x2faf080]
  --miner.instamine                     Set the instamine mode to either "eager" (default) or "strict". In
                                        "eager" mode a transaction will be included in a block before its hash
                                        is returned to the caller. In "strict" mode a transaction's hash is
                                        returned to the caller before the transaction is included in a block.
                                        This value has no effect if `blockTime` is *not* `0` (the default).`
                                                      [string] [choices: "eager", "strict"] [default: "eager"]

  --miner.coinbase                      Sets the address where mining rewards will go.
                                                         [default: 0x0000000000000000000000000000000000000000]

  --miner.extraData                     Set the extraData block header field a miner can include.
                                                                                        [string] [default: 0x]

  --miner.priceBump                     Minimum price bump percentage needed to replace a transaction that
                                        already exists in the transaction pool.         [string] [default: 10]


Wallet:
  --wallet.accounts                     Account data in the form <private_key>,<initial_balance>, can be
                                        specified multiple times. Note that private keys are 64 characters
                                        long and must be entered as an 0x-prefixed hex string. Balance can
                                        either be input as an integer, or as a 0x-prefixed hex string with
                                        either form specifying the initial balance in wei.
                                        deprecated aliases: --account                                  [array]

  -a, --wallet.totalAccounts            Number of accounts to generate at startup.
                                        deprecated aliases: --accounts                  [number] [default: 10]

  -d, --wallet.deterministic            Use pre-defined, deterministic seed.
                                        deprecated aliases: --deterministic         [boolean] [default: false]

  -s, --wallet.seed                     Seed to use to generate a mnemonic.
                                        deprecated aliases: --seed
                                                                                                      [string]
                                             [default: Random value, unless wallet.deterministic is specified]

  -m, --wallet.mnemonic                 Use a specific HD wallet mnemonic to generate initial addresses.
                                        deprecated aliases: --mnemonic                                [string]
                                                                         [default: Generated from wallet.seed]

  -u, --wallet.unlockedAccounts         Array of addresses or address indexes specifying which accounts should
                                        be unlocked.
                                        deprecated aliases: --unlock                                   [array]

  -n, --wallet.lock                     Lock available accounts by default (good for third party transaction
                                        signing).
                                        deprecated aliases: --secure, --lock        [boolean] [default: false]

  --wallet.passphrase                   Passphrase to use when locking accounts.
                                        deprecated aliases: --passphrase                              [string]

  --wallet.accountKeysPath              Specifies a file to save accounts and private keys to, for testing.
                                        deprecated aliases: --account_keys_path, --acctKeys           [string]

  -e, --wallet.defaultBalance           The default account balance, specified in ether.
                                        deprecated aliases: --defaultBalanceEther     [number] [default: 1000]

  --wallet.hdPath                       The hierarchical deterministic path to use when generating accounts.
                                                                            [string] [default: m,44',60',0',0]


Fork:
  -f, --fork.url                        Fork from another currently running Ethereum client at a given block.
                                        Input should be the URL of the node, e.g. "http://localhost:1337". You
                                        can optionally specify the block to fork from using an @ sign:
                                        "http://localhost:1337@8675309".

                                        You can specify Basic Authentication credentials in the URL as well.
                                        e.g., "wss://user:[email protected]/". If you need to use an Infura
                                        Project Secret, you would use it like this:
                                        "wss://:{YOUR-PROJECT-SECRET}@mainnet.infura.com/..."

                                        Alternatively, you can use the fork.username and fork.password
                                        options.
                                        deprecated aliases: --fork

  --fork.network                        A network name to fork from; uses Infura's archive nodes.

                                        Use the shorthand command ganache --fork to automatically fork from
                                        Mainnet at the latest block.
                                                            [choices: "mainnet", "goerli", "görli", "sepolia"]
  --fork.blockNumber                    Block number the provider should fork from.
                                                                                [default: Latest block number]

  --fork.preLatestConfirmations         When the fork.blockNumber is set to "latest" (default), the number of
                                        blocks before the remote node's "latest" block to fork from.
                                                                                         [number] [default: 5]

  --fork.username                       Username to use for Basic Authentication. Does not require setting
                                        fork.password.

                                        When combined with fork.password, is shorthand for fork: { headers: {
                                        "Authorization": "Basic {ENCODED-BASIC-HEADER}" } }

                                        If the fork.headers option specifies an "Authorization" header, it
                                        will be be inserted after this Basic token.

  --fork.password                       Password to use for Basic Authentication. Does not require setting
                                        fork.username.

                                        When combined with fork.username, is shorthand for fork: { headers: {
                                        "Authorization": "Basic {ENCODED-BASIC-HEADER}" } }

                                        If the fork.headers option specifies an "Authorization" header, it
                                        will be be inserted after this Basic token.

  --fork.jwt                            Encoded JSON Web Token (JWT) used for authenticating to some servers.

                                        Shorthand for fork:
                                          { headers: { "Authorization": "Bearer {YOUR-ENCODED-JWT}" } }

                                        If the fork.headers option specifies an "Authorization" header, it
                                        will be be inserted after the JWT Bearer token.

  --fork.userAgent                      The User-Agent header sent to the fork on each request.

                                        Sent as Api-User-Agent when used in the browser.

                                        Will be overridden by a "User-Agent" defined in the fork.headers
                                        option, if provided.

                                                                                [default: Ganache/7.0.0-beta.0
                                          (https://www.trufflesuite.com/ganache; ganache<at>trufflesuite.com)]

  --fork.origin                         The Origin header sent to the fork on each request.

                                        Ignored in the browser.

                                        Will be overridden by an "Origin" value defined in the fork.headers
                                        option, if provided.

  --fork.headers                        Headers to supply on each request to the forked provider.

                                        Headers set here override headers set by other options, unless
                                        otherwise specified.

                                                                    Defaults to: ["User-Agent: Ganache/VERSION
                                         (https://www.trufflesuite.com/ganache; ganache<at>trufflesuite.com)"]
                                                                                                       [array]

  --fork.requestsPerSecond              Restrict the number of requests per second sent to the fork provider.
                                        0 means no limit is applied.                     [number] [default: 0]

  --fork.disableCache                   Disables caching of all forking requests.   [boolean] [default: false]

  --fork.deleteCache                    Deletes the persistent cache before starting.
                                                                                    [boolean] [default: false]


Server:
  --server.ws                           Enable a websocket server.                   [boolean] [default: true]

  --server.wsBinary                     Whether or not websockets should response with binary data
                                        (ArrayBuffers) or strings.
                                                                            [choices: "true", "false", "auto"]
                                                                                               [default: auto]

  --server.rpcEndpoint                  Defines the endpoint route the HTTP and WebSocket servers will listen
                                        on.
                                                                                                [default: "/"]

  -h, --server.host                     Hostname to listen on.
                                        deprecated aliases: --host, --hostname
                                                                               [string] [default: "127.0.0.1"]

  -p, --server.port, --port             Port to listen on.
                                        deprecated aliases: --port
                                                                                      [number] [default: 8545]

Detached Instances

Ganache can be started as a background instance via the CLI by providing the following argument (along with any valid combination of the Ganache startup arguments above):

  -D, --detach, --😈                     Run Ganache in detached (daemon) mode.                       [boolean]

This will start Ganache as a background process, and return to the console as soon as Ganache has started and is ready to receive requests. A friendly name will be returned to STDOUT which can then be used to interact with the instance via the ganache instances command with the following arguments:

Commands:
  ganache instances list         List instances running in detached mode
  ganache instances stop <name>  Stop the instance specified by <name>

E.g., start Ganache on port 8544, with a block time of 10 seconds, and then stop the instance.

$ ganache --port=8544 --miner.blockTime=10 --detach
salted_caramel_ganache

$ ganache instances list
┌───────┬────────────────────────┬──────────┬─────────┬────────────────┬────────┐
│   PID │ Name                   │ Flavor   │ Version │ Host           │ Uptime │
├───────┼────────────────────────┼──────────┼─────────┼────────────────┼────────┤
│ 12182 │ salted_caramel_ganache │ ethereum │ 7.6.0   │ 127.0.0.1:8545 │    36s │
└───────┴────────────────────────┴──────────┴─────────┴────────────────┴────────┘

$ ganache instances stop salted_caramel_ganache
Process stopped

With the following command, you can start Ganache, run your tests, and stop Ganache when you are finished.

GANACHE=$(ganache --detach) && npm run test; ganache instances stop $GANACHE

Or if you are running PowerShell on Windows, you can do:

$GANACHE=ganache --detach; npm run test; ganache instances stop $GANACHE

Ganache Provider Events

In addition to EIP-1193's "message" event and the legacy "data" event, Ganache emits 4 additional events: "ganache:vm:tx:before", "ganache:vm:tx:step", "ganache:vm:tx:after", and "ganache:vm:tx:console.log".

These events can be used to observe the lifecycle of any transaction executed via *sendTransaction, eth_call, debug_traceTransaction, or debug_storageRangeAt.

These share the event paradigm that Truffle uses, but without any of the wildcard handling, i.e., no "vm:*" support (for now).

Each of these events will emit a context object which is a unique object that can be used to identify a transaction over the course of its lifecycle. For example:

interface StepEvent {
  account: {
    nonce: bigint;
    balance: bigint;
    stateRoot: Buffer;
    codeHash: Buffer;
  };
  address: Buffer;
  codeAddress: Buffer;
  depth: number;
  gasLeft: bigint;
  gasRefund: bigint;
  memory: Buffer;
  memoryWordCount: bigint;
  opcode: {
    name: string;
    fee: number;
  };
  pc: number;
  returnStack: Buffer[];
  stack: Buffer[];
}

const contexts = new Map();
provider.on("ganache:vm:tx:before", (event: { context: {} }) => {
  contexts.set(event.context, []);
});
provider.on("ganache:vm:tx:step", (event: { context: {}; data: StepEvent }) => {
  contexts.get(event.context).push(event.data);
});
provider.on(
  "ganache:vm:tx:console.log",
  (event: { context: {}; logs: (string | bigint | boolean)[] }) => {
    console.log(...event.logs);
  }
);
provider.on("ganache:vm:tx:after", (event: { context: {} }) => {
  doAThingWithThisTransactionsSteps(contexts.get(event.context));
  contexts.delete(event.context);
});

The reason this context is necessary is that Ganache may run multiple transactions simultaneously, so "ganache:vm:tx:step" events from different transactions could be intermingled.

The above events will be emitted for eth_call, *sendTransaction, debug_traceTransaction, and debug_storageRangeAt.

Currently, we do not await the event listener's return value, however, we'll likely enable this in the future.

console.log in Solidity

By default, Ganache logs to stdout when a contract executes a console.log Solidity statement during eth_call, eth_sendTransaction, personal_sendTransaction, and eth_sendRawTransaction. See the @ganache/console.log package for implementation and usage.

Community

Docker

The simplest way to get started with the Docker image:

$ docker run --detach --publish 8545:8545 trufflesuite/ganache:latest

To pass options to Ganache through Docker simply add the arguments to the end of the run command, e.g.,

$ docker run --detach --publish 8545:8545 trufflesuite/ganache:latest --accounts 10 --debug
                                                                      ^^^^^^^^^^^^^^^^^^^^^

The Docker container adds an environment variable DOCKER=true; when this variable is set to true (case insensitive), Ganache uses a default hostname IP of 0.0.0.0 instead of the normal default 127.0.0.1. You can still specify a custom hostname however:

$ docker run --detach --publish 8545:8545 trufflesuite/ganache:latest --host XXX.XXX.XXX.XXX
                                                                      ^^^^^^^^^^^^^^^^^^^^^^

To build and run the Docker container from source:

$ git clone https://github.com/trufflesuite/ganache.git && cd ganache

then:

$ docker build --tag trufflesuite/ganache --file ./packages/ganache/Dockerfile .
$ docker run --publish 8545:8545 trufflesuite/ganache

Contributing

See CONTRIBUTING.md for our guide to contributing to Ganache.

Related



Truffle

ganache's People

Contributors

aakilfernandes avatar area avatar axic avatar benjamincburns avatar ccowell avatar cgewecke avatar ckeenan avatar davidmurdoch avatar decanus avatar dependabot[bot] avatar eggplantzzz avatar eshaben avatar ewingrj avatar gnidan avatar iurimatias avatar jakub-wojciechowski avatar jeffsmale90 avatar kumavis avatar micaiahreid avatar mikeseese avatar mpolci avatar mrchico avatar nicholasjpaterno avatar rmeissner avatar simondlr avatar tcoulter avatar tenthirtyone avatar trufbot avatar unao avatar yusefnapora avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ganache's Issues

Allow LevelDOWN instance to be provided

We have a test suite that ends up generating loads of files in the TestRPC database. When this suite is run on our CI service, during a Docker build, it slows the build down tremendously.

It'd be great if we could provide our own LevelDOWN instance. We could use https://github.com/level/memdown so that TestRPC never has to touch the disk.

I'm filing this issue here first since TestRPC relies on this package.

testrpc doesn't work with Mist

Steps to Reproduce (for bugs)

  1. Start testrpc
  2. Start Mist with --rpc localhost:8545
  3. Select any account and try to send ether

Current Behavior

First in the tranasaction window threre's a warning:

It seems this transaction will fail. If you submit it, it may consume all the gas you send.

and

Estimated fee consumption: We couldn't estimate the gas.

Then after clicking on send transaction following message is displayed:

Error: RPC method personal_signAndSendTransaction not supported.
at GethApiDouble.handleRequest (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\lib\subproviders\geth_api_double.js:49:16)
at next (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\index.js:95:18)
at SolcSubprovider.handleRequest (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\subproviders\solc.js:28:7)
at next (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\index.js:95:18)
at VmSubprovider.handleRequest (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\subproviders\vm.js:40:12)
at next (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\index.js:95:18)
at GethDefaults.handleRequest (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\lib\subproviders\gethdefaults.js:17:12)
at next (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\index.js:95:18)
at FilterSubprovider.handleRequest (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\subproviders\filters.js:87:7)
at next (C:\Users\jondoe\AppData\Roaming\npm\node_modules\ethereumjs-testrpc\node_modules\web3-provider-engine\index.js:95:18)

Context

I'm trying to test my contracts using Mist started with --rpc localhost:8545 to connect to testrpc.
Test accounts are listed properly with their actual balance.
Problems starts when I try to create a contract or send ether.

Your Environment

  • Version used:
  • Environment name and version: TestRPC v3.0.3, Mist 0.8.7
  • Operating System and version: Windows 7 SP1
  • Link to your project:

Accounts balances not update after transactions are performed

I'm making a test in truffle with this solidity contract:

contract Cashbox{


    address public owner;

    uint public limit;
    address public beneficiary;

    function Cashbox( address _beneficiary , uint _limit  ){

        owner = msg.sender;
        beneficiary = _beneficiary;
        limit = _limit;

    }

    function withdraw() returns (bool){



        if(msg.sender != beneficiary )
            return false;


        if(this.balance > limit){

            var sent = beneficiary.send(this.balance);

        }
        else
            return false;


        if(sent)
            return true;
        else
            return false;
    }




}

Being the test file as follows:

contract("Cashbox" , function(accounts){

    var cashbox = null;


    it("constructor is OK" , function(done){

        var aLimit = null;
        var aBenef = null;


        Cashbox.at(Cashbox.deployed_address);


        Cashbox.new(  accounts[1] , 1000   )

        .then(function(c){
            cashbox = c;

            return cashbox.limit.call();

        })

        .then(function(lim){
            aLimit = lim;
            return cashbox.beneficiary.call();
        })


        .then(function(benef){

            aBenef = benef;


            return cashbox.owner.call();

        })


        .then(function(owner){

            assert.equal(aLimit.toNumber() , 1000 , "limit should be 1000");
            assert.equal(aBenef , accounts[1] , "beneficiary should be the second account");
            assert.equal(owner , accounts[0] , "The owner should be the default account");

        })

        .then(done).catch(done);
    });


    it("contract is persistent over tests" , function(done){


        cashbox.limit.call()

        .then(function(value){
            assert.equal(value.toNumber(), 1000 , "limit should have persisted form the first test");
        })

        .then(done).catch(done);

    });


    it("accounts work OK" , function(done){

        var balanceBeforeSend;
        var balanceAfterSend;
        var balanceAfterWithdraw;

        new Promise( function(resolve , error ){

                return web3.eth.getBalance(accounts[1], function(err, hashValue ){

                        if(err)
                            return error(err);
                        else {
                            return resolve(hashValue);
                        }
                }) ;
        } )

        .then(function(balance_beneficiary_before_send){


            balanceBeforeSend = balance_beneficiary_before_send;

            console.log("The beneficiary balance before sending funds is : " + balance_beneficiary_before_send.toNumber() );

            return new Promise( function(resolve , error ){

                    return web3.eth.getBalance(cashbox.address, function(err, hashValue ){

                            if(err)
                                return error(err);
                            else {
                                return resolve(hashValue);
                            }
                    }) ;
            } )
        })


        .then(function(balance_cashbox_before_send){

            console.log("Balance of cashbox contract before send is : " + balance_cashbox_before_send.toNumber() );


            return new Promise( function(resolve , reject){

                web3.eth.sendTransaction({  to : cashbox.address , value : "2000000000000000000" , from : accounts[1] }  , function(err , success ){

                    if (err)
                        return reject(err);
                    else
                        return resolve(success);

                });

            } );//end promise

        })

        .then(function(txResult){

            return new Promise( function(resolve , error ){

                    return web3.eth.getBalance(cashbox.address, function(err, hashValue ){

                            if(err)
                                return error(err);
                            else {
                                return resolve(hashValue);
                            }
                    }) ;
            } )
        })

        .then(function(balance_cashbox_after_send ){

            console.log("balance of contract cashbox after ether send : " + balance_cashbox_after_send.toNumber() );

            return new Promise( function(resolve , error ){

                    return web3.eth.getBalance(accounts[1], function(err, hashValue ){

                            if(err)
                                return error(err);
                            else {
                                return resolve(hashValue);
                            }
                    }) ;
            } )

        })

        .then(function(balance_beneficiary_after_send){

            balanceAfterSend = balance_beneficiary_after_send;
            console.log("balance of beneficiary after the send transaction : " + balance_beneficiary_after_send.toNumber() );

            return cashbox.withdraw({from : accounts[1] });
        })

        .then(function(withdrawResult){

            return new Promise( function(resolve , error ){

                    return web3.eth.getBalance(accounts[1], function(err, hashValue ){

                            if(err)
                                return error(err);
                            else {
                                return resolve(hashValue);
                            }
                    }) ;
            } )
        })


        .then(function( balance_beneficiary_after_withdraw){
            balanceAfterWithdraw = balance_beneficiary_after_withdraw;
            console.log("balance of beneficiary after witdraw : " + balance_beneficiary_after_withdraw.toNumber() );

            return new Promise( function(resolve , error ){

                    return web3.eth.getBalance(cashbox.address, function(err, hashValue ){

                            if(err)
                                return error(err);
                            else {
                                return resolve(hashValue);
                            }
                    }) ;
            } )
        })

        .then(function(balance_cashbox_after_withdraw){

            console.log("balance of cashbox after witdraw : " + balance_cashbox_after_withdraw.toNumber() );

            assert.equal(balance_cashbox_after_withdraw.toNumber() , 0 , "Contract balance should be 0 after a withdraw");
            assert.notEqual(balanceBeforeSend.toNumber() , balanceAfterSend.toNumber() , "beneficiary address balance should not remain equal after a deposit" );
        }).then(done).catch(done);



    })

});

Basically is just to send some ether from an account to a contract and then send that same ether back to the same account.

The second assertion of the third test is failing, stating that the balance of the account is not changed between transactions (but the contract balance does change as it would). It can also be viewed in the console logs.

I'm not sureif I'm doing the things right with all the Promises, I'm not used to them, but the fact that the test is working right with the contract balance but failing with the accounts balance could suggest that all the issue can be a testrpc problem.

Hope this is useful, thanks in advance.

debug_traceTransaction fails on forked chain

Forking a chain and calling "debug_traceTransaction" throws exception "Error: Number can only safely store up to 53 bits" with a simple transaction.

Expected Behavior

debug_traceTransaction should return trace

Current Behavior

after calling debug_traceTransaction genache-cli throws error "Error: Number can only safely store up to 53 bits"

Steps to Reproduce (for bugs)

  1. Run parity/geth full node with tracing
  2. Fork: ganache-cli --fork http://localhost:8545@100 --port 9999 --debug --db chain/
  3. Send test transaction and try to trace it:
    from web3 import Web3, HTTPProvider, TestRPCProvider
    web3 = Web3(HTTPProvider("http://127.0.0.1:9999")
    message = {
    "from": public_address,
    "to": address,
    "value": 1
    }
    result = web3.eth.sendTransaction(message)
    trace = web3.manager.request_blocking("debug_traceTransaction", [result])

Your Environment

  • Version used: Ganache CLI v6.0.3 (ganache-core: 2.0.2)
  • Server type and version: Geth 1.7.3, Parity/1.8.3/1.20.0/wi, web3py
  • Operating System and version: Windows 10

eth_newFilter returns malformed ids with trailing zeroes

Expected Behavior

When a new filter is created using eth_newFilter, the ID returned should be formed correctly according to this description on how to encode quantities, i.e., no trailing zeroes like "0x03"

Current Behavior

The ID returned after filter creation contains leading zeroes like "0x03" instead of "0x3", also only accepting the same string when the filter changes are queried. So querying filter changes for "0x3" will result in the error message "FilterSubprovider - no filter with that id: 0x3". So, if the ID is stored as an integer and (de-)serialized before calls are made, the previous error occurs.

Context

I stumbled upon the problem using the rust-web3 library and also opened an issue there which resulted in a temporary workaround. Nevertheless I think the root cause is here and it should be fixed.

My Environment

  • Version used: Ganache v1.0.2 / [email protected]
  • Operating System and version: Ubuntu 16.04.3 LTS

eth_sign API out of sync with ethapi

As of ethereum/go-ethereum#2940, eth_sign api has changed. It is now eth_sign(address, msg), accepting arbitrary input and putting it through keccak256.

Expected Behavior

Upstream eth_api introduced a breaking change where eth_sign now accepts the actual message, rather than a 32 byte hash digest. Signature is now eth_sign(address, msg)

Current Behavior

testrpc currently emulates existing eth_sign(address, sha3(msg)) behavior

Possible Solution

Change ethereumjs-util.ecsign to call keccak256 before calling secp256k1.sign

Context

We need to sign statements with web3, which is now incompatible between testrpc and real ethapi.

Your Environment

--db Option Requires Same Mnemonic and Network ID

Dear all,

I am just in the process of testing the latest version of testrpc (4.1.3) and the --db option still appears to not be working correctly as reported in earlier versions by users.

In summary, the chain data appears to be saved but when closing and starting testrpc again, my test contract is no longer deployed.

Has anyone been able to get this feature to work in v4.1.3?

Many Thanks,

Pete

Incorrect ChainID in Transaction Hash Serialization

Transaction hashes for submitted transactions incorrectly use 0x1c (28) as the chain_id, regardless of the actual chain_id. This leads to incorrect transaction hashes being generated / returned via JSON-RPC for sendRawTransaction and likely sendTransaction.

Expected Behavior

When a transaction is submitted, it should use the correct chain ID when generating the transaction hash according to EIP-155.

Examples transaction in serialized form:

[ '0x0',
    '0x09184e72a000',
    '0x0f4240',
    '0x0',
    '0x0',
    '0x0',
    '0x1c', // this should be `chain_id * 2 + 35 + <recovery_bit>`, instead it's hard-coded
    '0x0',
    '0x0' ]

Current Behavior

See above, we're generating the hash from an incorrectly serialized transaction. One could argue that pre-EIP-155 transactions (see the Yellow Paper Appendix F), are okay, but we're still not properly encoding the recovery bit (e.g. it should be 27 or 28, not hard-coded at 27). The current behavior is strictly incorrect according to the Ethereum standard.

Possible Solution

We need to make sure chain_id is set when calling transaction.hash() after a transaction is submitted via sendRawTransaction or sendTransaction. This is strictly required to match the official Ethereum specifications for transaction serialization (defined in Eq.(214) and Eq.(215) of the Yellow Paper and EIP-155).

Steps to Reproduce (for bugs)

  1. Generate a valid transaction (T).
  2. Build the EIP-155 transaction hash of T ("trx_hash")
  3. Serialize T and submit to TestRPC via sendRawTransaction
  4. Verify that the returned trx_hash does not match what was calculated above.

Context

Transaction hashes must be consistently generated based on input. Otherwise, clients will not be able to check on the status of transactions.

Your Environment

  • Version used: [email protected]
  • Environment name and version (e.g. PHP 5.4 on nginx 1.9.1):
  • Server type and version:
  • Operating System and version: Darwin 10.12.6
  • Link to your project:

Number can only safely store up to 53 bits error on debug.traceTransaction on a forked TestRPC

Expected Behavior

web3 traceTransaction should go through on a forked TestRPC

Current Behavior

get Error: Number can only safely store up to 53 bits

Should be able to handle traceTransaction when testRPC is forked. traceTransaction on a non-forked TestRPC works fine.

Steps to Reproduce (for bugs)

  • Run ./cli.js with default options
  • Create a new Ganache Instance with Fork Options (from my setup):
const ForkOptions = {
  port: '8546',
  hostname: 'localhost',
  debug: false,
  seed: null,
  mnemonic: null,
  total_accounts: null,
  blocktime: null,
  gasPrice: null,
  gasLimit: 3000000, // 3mil gas
  accounts: null, // was parseAccounts(accounts)
  unlocked_accounts: [0],
  fork: 'http://localhost:8545',
  network_id: null,
  verbose: false,
  secure: null,
  db_path: null,
  account_keys_path: null,
  logger: console,
};
  • try sending traceTransaction to forked TestRPC as such:
var options = {
  disableStorage: true,
  disableMemory: false,
  disableStack: false,
  fullStorage: false,
 };
 web3.debug.traceTransaction(<YOUR_TX_HASH>, options, function (error, result) {
    callback(error, result);
 });

Context

Building a Debugger for Solidity. One of the options is to run debugger on a forked TestRPC.

Your Environment

  • Version used: Latest Ganche-core
  • Environment name and version (e.g. PHP 5.4 on nginx 1.9.1): Node.JS V 9.1.0
  • Server type and version: N/A
  • Operating System and version: ArchLinux 4.14.3-1-ARCH

WebSocket - requires non-standard message format

Expected Behavior

WebSocket should receive message and forward RPC request.

Current Behavior

~/node_modules/ganache-cli/build/cli.node.js:95750
var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&"function"==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONME

TypeError: connection.reject is not a function
    at WebSocketConnection.<anonymous> (~/node_modules/ganache-cli/build/webpack:/node_modules/ganache-core/lib/webSocketServer.js:50:1)
    at emitOne (events.js:116:13)
    at WebSocketConnection.emit (events.js:211:7)
    at WebSocketConnection.processFrame (~/node_modules/ganache-cli/build/webpack:/node_modules/websocket/lib/WebSocketConnection.js:548:1)
    at ~/node_modules/ganache-cli/build/cli.node.js:25355:40
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

Possible Solution

It appears the WebSocket service expects a non-standard message format (dictated by the websocket library).

This requirement should either be documented or, preferably, relaxed to allow a standard stringified message eg. var payload = JSON.parse(message)

Steps to Reproduce

  1. Install ganache-cli@beta
  2. Run ganache-cli
  3. Connect to WS and send a standard message
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>🔌</title>
  </head>
  <body>
    <script type="text/javascript">
      const socket = new WebSocket('ws://localhost:8545');

      socket.addEventListener('open', function (event) {
        socket.send('{"jsonrpc":"2.0","method":"eth_coinbase","params":[],"id":1}');
      });
    </script>
  </body>
</html>
  1. Observe console error (shown above)

Context

Trying to send an RPC request to Ganache WebSocket server.

Your Environment

  • Version used: Ganache CLI v6.1.0-beta.2 (ganache-core: 2.1.0-beta.1)

Should use a default network ID which is easily recognized as a TestRPC/Ganache network

Testrpc responds to web3.version.getNetwork with an increasing number (the time when the testrpc was started).

Although this prevents people from thinking they are running against mainnet etc, it's actually not useful to have it be non-deterministic and a different value on every startup.

It's also surprising since real clients return 1 for mainnet etc.

Expected Behavior

Calls to web3.version.getNetwork should always return a value that is reserved to indicate that it is testrpc running.

Current Behavior

Calls to web3.version.getNetwork return a timestamp set when testrpc starts up.

Possible Solution

Chose a particular value to represent a testrpc network, or prefix the timestamp with some agreed upon value like 888.

Steps to Reproduce (for bugs)

  1. window.web3.version.getNetwork(function(err, d) { console.log(d) })

Support WebSockets

Since Web3 1.0.0 the HTTP provider no longer supports subscriptions (e.g listening for events).

Instead it is expected that developers use the new WebSocket provider or the IPC provider. Neither of these are supported by Ganache, and thus they are not supported in testrpc either.

Expected Behavior

  • Ganache should expose a WebSocket that accepts JSON-RPC as usual.
  • Subscriptions should work as they did before Web3 1.0.0, but over WebSockets.

Current Behavior

  • WebSockets are unsupported.

Context

It is impossible to use testrpc with Web3 1.0.0. Instead developers are forced to use Parity or geth.

Filters and getLogs supports only single address, not an array

It seems multiple addresses for eth_newFilter and eth_getLogs are not supported. Unlike geth (which has address: DATA|Array), ganache is only capable of filtering on a single address. If an array is passed (even with only a single item in it), ganache will always return an empty list, not matching anything.

Here's the relevant code:

https://github.com/trufflesuite/ganache-core/blob/d1646364d7e4ad667e4c522e0d7877bc962ba949/lib/statemanager.js#L601

As you can see, it only has equality check, so it would fail in presence of array. An obvious fix would be to check for type - e.g. do something in lines of

return expectedAddress == null || (
    Array.isArray(expectedAddress)
        ? expectedAddress.includes(log.address)
        : log.address == expectedAddress);

But - sorry - I'm to lazy to make a proper pull request.

(Copied from #322 (comment) where I've originally posted it. Found the relevant code in this project, so posting it here.)

Discrepancy between geth and TestRPC with extcodesize()

The following solidity inline assembly returns a different value on TestRPC compared to other ethereum implementations:

function getCodeSize(address _address) returns (uint256 _codesize) {
   uint256 _codesize;
   assembly { _codesize := extcodesize(_address) }
   return _codesize
}

In geth it will return 0 when passed the address of an externally owned account but in TestRPC this returns 1

Expected Behavior

The code above should return 0 when passed the address of an externally owned account.

Please see geth results from here

Current Behavior

It returns 1 on TestRPC. Could possibly cause problems with other contracts

Steps to Reproduce (for bugs)

  1. Deploy the code.
  2. Pass it the address of an externally owned account.

Context

Your Environment

  • Version used: 3.0.3
  • Environment name and version (e.g. PHP 5.4 on nginx 1.9.1): node v7.5.0
  • Server type and version: Tried on OSX, Linux, FreeBSD

Use new network ID for forked chain

Metamask uses the network id to determine what tx history to show.
I think it makes the most sense to show a new network id to indicate modeling a separate chain (that has been seeded with existing data).

this does not affect on-chain behavior.

a user could always override the network id to be the same as the original, if desired

relevant issue in metamask:
MetaMask/metamask-extension#783

Warnings during a webpack build

Expected Behavior

Build should be silent with no warnings

Current Behavior

WARNING in /home/circleci/repo/node_modules/ethereumjs-vm/lib/runJit.js
13:16-23 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
 @ /home/circleci/repo/node_modules/ethereumjs-vm/lib/runJit.js
 @ /home/circleci/repo/node_modules/ethereumjs-vm/lib/index.js
 @ /home/circleci/repo/node_modules/ethereumjs-vm/index.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/statemanager.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/subproviders/geth_api_double.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/provider.js
 @ /home/circleci/repo/node_modules/ganache-core/index.js
 @ ../subproviders/lib/src/subproviders/ganache.js
 @ ../subproviders/lib/src/index.js
 @ ./ts/blockchain.ts
 @ ./ts/components/portal.tsx
 @ ./ts/containers/portal.ts
 @ ./ts/index.tsx
 @ multi ./ts/index.tsx

ERROR in /home/circleci/repo/node_modules/ganache-core/lib/database/filedown.js
Module not found: Error: Can't resolve 'fs' in '/home/circleci/repo/node_modules/ganache-core/lib/database'
 @ /home/circleci/repo/node_modules/ganache-core/lib/database/filedown.js 4:9-22
 @ /home/circleci/repo/node_modules/ganache-core/lib/database.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/blockchain_double.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/statemanager.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/subproviders/geth_api_double.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/provider.js
 @ /home/circleci/repo/node_modules/ganache-core/index.js
 @ ../subproviders/lib/src/subproviders/ganache.js
 @ ../subproviders/lib/src/index.js
 @ ./ts/blockchain.ts
 @ ./ts/components/portal.tsx
 @ ./ts/containers/portal.ts
 @ ./ts/index.tsx
 @ multi ./ts/index.tsx

ERROR in /home/circleci/repo/node_modules/rustbn.js/lib/index.asm.js
Module not found: Error: Can't resolve 'fs' in '/home/circleci/repo/node_modules/rustbn.js/lib'
 @ /home/circleci/repo/node_modules/rustbn.js/lib/index.asm.js 1:1297-1310 1:150825-150838
 @ /home/circleci/repo/node_modules/rustbn.js/index.js
 @ /home/circleci/repo/node_modules/ethereumjs-vm/lib/precompiled/07-ecmul.js
 @ /home/circleci/repo/node_modules/ethereumjs-vm/lib/index.js
 @ /home/circleci/repo/node_modules/ethereumjs-vm/index.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/statemanager.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/subproviders/geth_api_double.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/provider.js
 @ /home/circleci/repo/node_modules/ganache-core/index.js
 @ ../subproviders/lib/src/subproviders/ganache.js
 @ ../subproviders/lib/src/index.js
 @ ./ts/blockchain.ts
 @ ./ts/components/portal.tsx
 @ ./ts/containers/portal.ts
 @ ./ts/index.tsx
 @ multi ./ts/index.tsx

ERROR in /home/circleci/repo/node_modules/tmp/lib/tmp.js
Module not found: Error: Can't resolve 'fs' in '/home/circleci/repo/node_modules/tmp/lib'
 @ /home/circleci/repo/node_modules/tmp/lib/tmp.js 13:11-24
 @ /home/circleci/repo/node_modules/ganache-core/lib/database.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/blockchain_double.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/statemanager.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/subproviders/geth_api_double.js
 @ /home/circleci/repo/node_modules/ganache-core/lib/provider.js
 @ /home/circleci/repo/node_modules/ganache-core/index.js
 @ ../subproviders/lib/src/subproviders/ganache.js
 @ ../subproviders/lib/src/index.js
 @ ./ts/blockchain.ts
 @ ./ts/components/portal.tsx
 @ ./ts/containers/portal.ts
 @ ./ts/index.tsx
 @ multi ./ts/index.tsx

Possible Solution

Steps to Reproduce (for bugs)

  1. Create a webpack project
  2. Include ganache-core as a dependency
  3. Build

Context

I now have a bunch of warnings in my build after including ganache-core as a dependency.

Your Environment

Support synchronous calls

In relation to #11, one way I thought I could avoid using WebSockets would be to use the provider from ganache-core directly in my tests.

This did not work, since Web3 1.0.0 heavily relies on synchronous calls for things that are not subscriptions, but ganache-core does not support synchronous calls.

Expected Behavior

  • Synchronous calls should be implemented.

Current Behavior

  • They are not.

Steps to Reproduce (for bugs)

  1. Install Web3 1.0.0.
  2. Create a new instance of Web3 using the provider from ganache-core (ganache.provider()).
  3. Use any method that is not a subscription, e.g. web3.eth.getAccounts()

Context

I am trying to use ganache or testrpc for my integration tests, but ganache does not support WebSockets or IPC (which is required for subscriptions since Web3 1.0.0), and ganache does not work by using the provider directly either, since synchronous calls will not work this way.

This sort of traps me in two ways. Either I...

  • ... use testrpc but cannot test subscriptions (e.g. events) because I can only rely on the HTTP provider
  • ... use ganache.provider() but cannot use any methods that do not result in a subscription

Issues embedding random data in the ethereum transactions data field

I'm embedding a Merkle root in the data field of an ethereum transaction. this works fine for e.g. Parity.

On Ganache, however, I'm hit with this function that thinks I'm doing a contract call when I do a transaction that has a to and a data field. https://github.com/trufflesuite/ganache-core/blob/a48a99d2d5609f7e5a05c222fab8727b179c8f60/lib/statemanager.js#L811

        const sendTransaction = Promise.promisify(
          web3.eth.sendTransaction
        )
        const tx = await sendTransaction({
          to: address,
          from: address,
          data: merkleRoot,
        })

Tx hash invalid

I trying to simplify the situation but I cannot reproduce more simple:
I'm using account with default balance (with auto mine on every transaction), send 1 eth to one address, 1 eth to an other address, and form this two address two transaction on an other.
capture d ecran 2018-02-12 a 03 49 26

The bug is tx 3 et 4 in my schema have the same tx hash, wallet 3 have right balance (tx 3 + tx 4) when I call getBlock with web 3 I find one ( and bug is same) tx in two last block. This bug appear only if tx3 and 4 have the same amount, if it's different value hash is correct.

createAccount happens even if you have a database

Expected Behavior

Reuse accounts when persisting the database to disk.

Current Behavior

Even if you store to a database with the --db_path flag, when you reload the server it will create new accounts.
I would expect it would keep the same wallets from before, not create new accounts every time you run testrpc.

Possible Solution

Save the accounts/private keys to a json file, and reload them on next start.

Steps to Reproduce (for bugs)

node cli.js --db testdata
kill it
node cli.js --db testdata

I understand the cli is from testrpc package, but the actual code is in this package

Context

Trying to have a semi reusable test blockchain, that can persist to disk and be reloaded. For testing out code.

Your Environment

  • Version used: Ganacha-core 1.1.4 and testRPC master GIT 29c5115609b909b32774bbaa820c8744db50a74e
  • Environment name and version: Node 8.6.0
  • Operating System and version: OSX
  • Link to your project: http://loomx.io

Support in browser

It seems like Ganache core is close to being able to run in-browser. It's dependency 'leveldown' require a node environment, this could be swapped out for level-js when in a browser environment. There may be other issues when I dig into this.

Expected Behaviour

Ganache-core runs on html5

Actual Behaviour

Ganache throws an exception when required(), cannot initialize it's leveldown dependency.

Context

It'd be nice to run a private chain in-browser to allow users to testdrive a dapps functionality without using a test network and with minimal or no network usage. Alternatives are to run a websocket to a node server running ganache, or to abstract over the web3 layer entirely.

I'm going to tinker with this idea soon.

Incorrect RPC response when eth_call fails

Expected Behavior

When an eth_call is made, and the call fails, a valid JSON response should be received, with the default ('empty') values for the return types in the result field. with a result field of 0x.

Current Behavior

Currently, the JSON response is of the form:

{"id":284,"jsonrpc":"2.0"}

This is missing the result field, as defined in the spec, and so web3 rejects it with Error: Invalid JSON RPC response.

Possible Solution

I think this is because result is undefined when the response is serialized, and gets removed entirely. I don't think returning undefined would be appropriate either though.

Steps to Reproduce (for bugs)

Deploy a contract with the below function, and run eth_call against it:

    function someFunction() public view returns (bool){
        require(false);
        return true;
    }

Your Environment

EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2) on OSX 10.13.2, Node v8.4.0

There is no way to undo evm_increaseTime

Expected Behavior

There is no way to undo evm_increaseTime. See "Current Behavior".

Current Behavior

  • evm_increaseTime does not accept negative values, treats them as 0.
  • evm_snapshot does not capture current BlockchainDouble.timeAdjustment , so...
  • ... evm_revert does not undo effects of evm_increaseTime

Possible Solution

Either:

  • add evm_setTime geth API.
  • make evm_increaseTime to accept negative values.
  • make evm_snapshot capture current BlockchainDouble.timeAdjustment and evm_revert to restore snapshot including time.

Steps to Reproduce (for bugs)

  1. Start testrpc
  2. Note current time
  3. issue evm_snapshot
  4. issue evm_increaseTime(365 * 86400)
  5. issue evm_revert
  6. observe current testrpc time, which is still 365 days from now in future.

Context

We make snapshots and do some test pieces inside these snapshots.
Calls to evm_increaseTime alters times outside of snapshots, affecting other tests.

Your Environment

  • Version used: EthereumJS TestRPC v4.0.1 (ganache-core: 1.0.1)
  • Environment name and version: NodeJS v6.11.0
  • Server type and version: Truffle v3.4.3 (core: 3.4.1)
  • Operating System and version: Linux 4.10.0-28-generic #32~16.04.2-Ubuntu SMP Thu Jul 20 10:19:48 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Browser support

Hi there!

Sorry if this is a dup or has been discussed before, but what would be the blocker (if any) for running testrpc directly in the browser (without server)?

From my research I found out ethereumjs-vm needed to be run in node, so i compiled it and imported it directly and tried to run it, but Meteor would get stuck while building when trying to compile it when including testrpc.

Thanks for your work!

Error "unexpected EOF" when connecting to WebSocket endpoint

Trying to connect to websocket endpoint but get an unexpected error

Expected Behavior

Current Behavior

unexpected EOF

Possible Solution

Steps to Reproduce (for bugs)

var Ganache = require('ganache-core')
var server = Ganache.server({
  ws: true,
  port: 8545
})
var port = 8545
server.listen(port, (err) => {
  console.log(`Listening on ${port}`)
})

Context

Trying to listen to events

Your Environment

  • Version used: 2.1.0-beta.0
  • Environment name and version: node v7.9.0
  • Operating System and version: Darwin computer.local 16.7.0 Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64 x86_64

Allow multiple blocks to be specified in evm_mine.

Too lazy to do a PR, but this works:

Change this:

GethApiDouble.prototype.evm_mine = function(callback) {
  this.state.processBlocks(1, function(err) {
    callback(err, '0x0');
  });
};

To this:

GethApiDouble.prototype.evm_mine = function(numBlocks, callback) {
  if (callback==undefined) { //backwards compatibility
     callback = numBlocks;
     numBlocks = 1;
  }
  this.state.processBlocks(numBlocks, function(err) {
    callback(err, '0x0');
  });
};

getFilterChanges seems to treat the hexId as a string literal and not a value

Expected Behavior

If I call getFilterChanges with 0x7 id it should work for a filter with an id 0x07.

Current Behavior

If one creates a filter and it returns an id with a leading "0" i.e "0x07",
If one subsequently calls getFilterChanges with "0x7" it will fail with:
FilterSubprovider - no filter with that id: 0x7

Possible Solution

Test for numeric value equivalence or remove leading "0"'s to test for equality when responding to getFilterChanges requests

Accept a genesis.json file

The genesis.json file format specifies an initial state for the blockchain, including balances of account numbers.

This could be very useful for development environments where a client has a wallet on it, and we want them to have a balance even on the simulated blockchain.

Lets clients operate in the development environment with nothing but the RPC address and an account that they've generated.

(I'm talking about Metamask here).

sample genesis.json here.

The basic format is this:

{
"nonce": "0x0000000000000042",
"difficulty": "0x400000000",
"alloc": {
  "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": {
    "balance": "1337000000000000000000"
    }
  },
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1388"
}

The part I care the most about is the alloc hash, which includes a map of accounts to an object containing their initial balance.

An aside: A lot of pre-sale purchasers picked 1337... as their initial balance :)

Accept CLI args via config file

Splitting off from trufflesuite/ganache-cli-archive#24.

As suggested in https://github.com/ethereumjs/testrpc/issues/23 parsing a genesis.json would be a useful feature and in #24 we discussed perhaps it is better to have a separate configuration file and/or commandline parameters (for a subset or all options).

Given there are two other PRs in the pipeline (trufflesuite/ganache-cli-archive#28 (gasLimit) and trufflesuite/ganache-cli-archive#36 (gasPrice)) as well as the --seed and perhaps lightwallet options, I think it would be useful to discuss and make a decision on how configuration should work.

I would vote for having a comprehensive configuration file and including some frequently used options in the commandline.

Support IPC endpoint

Some tools (i.e. Mist, Solidity tests, etc.) have switched to use IPC instead of the HTTP-RPC.

Would it be hard adding IPC support? (That would need to replace the http server when the option is turned on. Ideally listening on both an IPC file and HTTP would be nice.)

Ability to specify zero accounts created/unlocked

Expected Behavior

I would like to be able to specify zero accounts created/unlocked when starting ganache.

Current Behavior

Setting options = { total_accounts: 0 } does not work as it will default to 10 accounts if set to 0 due to this line: https://github.com/trufflesuite/ganache-core/blob/develop/lib/statemanager.js#L42.

Context

I am trying to test situations where a user signs out of MetaMask. If a user goes from a logged-in state to a logged-out state in MetaMask, the web3 object persists in the browser but the number of unlocked accounts available goes to zero. I would like to be able to test this behaviour in my code.

Creating Ganache server with specified accounts (private key and balance) creates accounts with zero balance

Initially found when using ganache-cli, I tracked it down to ganache-core.

var options = { accounts: [{ sekretKey: <secret>, balance: <balance> }] }
var server = Ganache.server(options);

Accounts created this way always have zero balance even though it's specified.

UPDATE: Further testing shows that accounts are being created with 100 ETH balance when the balance is not specified; when it's specified then the accounts are created with zero balance, which is still a bug.

`now` not respected in solidity during calls directly after `increaseTime` is called

If you call evm_increaseTime, then call a function using eth_call that includes the now variable in Solidity, the value of now won't respect the increased time. Big thanks to @mzeitlin8 for pointing it out.

To reproduce:

  • Compile and deploy a contract with the following function:
    function getCurrentTime() returns (uint){
        return now;
    }
    
  • Call evm_increaseTime to change the time to some astronomical amount
  • Without making a transaction, call eth_call to getCurrentTime(). You'll notice the astronomical time change isn't respected.

Workaround

Call evm_mine before calling getCurrentTime(), or make any transaction before calling getCurrentTime(). This will ensure the time change is respected.

When >1 transactions in a block, all logs are included in all transactions.

Expected Behavior

Each transaction's logs should contain logs only relevant to that transaction, and not other transactions in the same block.

Current Behavior

Each transaction's logs will contain all logs of all transactions that occurred on the block.

Possible Solution

Steps to Reproduce (for bugs)

Create two transactions in one block and look at the logs.

Context

Your Environment

  • Version used:
  • Environment name and version (e.g. PHP 5.4 on nginx 1.9.1):
  • Server type and version:
  • Operating System and version:
  • Link to your project:

ETH_CALL doesn't respect past block numbers correctly

when running ETH_CALL there is an option to provide a block number (QUANTITY) (https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call). It seems like ganache always returns the call on the 'latest' block - it should at least throw if this option is not supported.

Steps to Reproduce

add this to requests.js :

    it("should call a method on a past block (eth_call)", function(done){
      var exampleOutput = solc.compile(source).contracts[":Example"]
      web3.eth.contract(JSON.parse(exampleOutput.interface)).new({ data: exampleOutput.bytecode, from: accounts[0], gas: 3141592 }, function(err, example){
        if(err) return done(err)
        if(!example.address) return
        example.setValue(26, {from: accounts[0], gas: 3141592}, function(err, tx) {
          if (err) return done(err);
          web3.eth.getBlock('latest', false, function(err, blockAfterSet26){
            if (err) return done(err);
            example.setValue(30, {from: accounts[0], gas: 3141592}, function(err, tx) {
              if (err) return done(err);
              example.value.call(blockAfterSet26.number, function(err, value) {
                if (err) return done(err)
                assert.equal(value.toNumber(), 26);
                done()
              })
            })
          })
        })
      })
    })

returns:

Uncaught AssertionError [ERR_ASSERTION]: 30 == 26

Context

I was trying to test a code that uses this ETH_CALL feature and the test failed

Your Environment

  • Version used: 2.0.2
  • Operating System and version: macOs 10.13.2

Transaction Hashes are Computed Incorrectly

ganache-core uses EIP-155 hashes to identify transactions. This causes JSON-RPC calls like eth_sendRawTransaction to return unexpected values. The EIP-155 hash should be used to generate a signature. It should not be used to identify the transaction in the RPC mechanism.

Expected Behavior

$ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xf86b808504e3b2920082520894a3bd45f7b000a6d3d2359b0577ed34adbdfc25eb87038d7ea4c68000802aa0dec7e8ff13c93cdc9a75432f01730bdc3a20fc0eaf820a7234c1aabdbf6ccb64a0601845af5cbd02e9c443f870bdbee61c93a5533c4c3f84931a0e1dfab30d39ab"],"id":1}' https://ropsten.infura.io
{"jsonrpc":"2.0","id":1,"result":"0xe1ba8a320f9fc6846127b244faf9825028d7298c4d34c4aa0fc57d48b85a7ab3"}

Current Behavior

$ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0xf86b808504e3b2920082520894a3bd45f7b000a6d3d2359b0577ed34adbdfc25eb87038d7ea4c68000802aa0dec7e8ff13c93cdc9a75432f01730bdc3a20fc0eaf820a7234c1aabdbf6ccb64a0601845af5cbd02e9c443f870bdbee61c93a5533c4c3f84931a0e1dfab30d39ab"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":"0x56860ff2721668edd33f5f86abdbd44fe1a8e8f3efba1a12dc76f2c9da53b836"}

Notice that the hash is 0x56860ff2721668edd33f5f86abdbd44fe1a8e8f3efba1a12dc76f2c9da53b836 instead of sha3(data) = 0xe1ba8a320f9fc6846127b244faf9825028d7298c4d34c4aa0fc57d48b85a7ab3

Possible Solution

Always use sha3(rawData) to identify signed transactions, including over json rpc.

Steps to Reproduce (for bugs)

Run gananche-cli in the background using this:

const secretKey = Buffer.from('8874F01D72E7BE5D5417B55E0F21698692704F408C1AFF382641DB0423F1B2E1', "hex");
const config = {
  "accounts": [
    { "balance": 1000000 * 1000000000000000000,
      "secretKey": secretKey
    }, ], };

require("ganache-cli").server(config).listen(8545);

Then run curl as above.

Context

Transaction hashes computed outside of ganache-core/ganache-cli do not match those expected or returned by ganache-X. This makes it difficult to use ganache-X for testing applications that interact with other Ethereum nodes.

Your Environment

  • Version used: Ganache CLI v7.0.0-beta.0 (ganache-core: 3.0.0-beta.0)
  • Operating System and version: macOS 10.13.2

Add build instructions

Would be helpful to have build instructions for those that might want to contribute to the project.

estimateGas returns invalid value when tx has a gasRefund

When calling eth_estimateGas, the returned value is incorrect for the following cases:

  1. transaction set a non-0 state variable to 0 thus resulting in a gas refund. The returned value is the transaction receipt gasUsed value, but in reality you need the tx receipt gasUsed + gasRefund to execute the tx, as gas is refunded at the end of the tx.

  2. If there is a strange gas check in the contract function. ex:

contract FunkyGasPattern {
	string public field;

	function SetField(string value) {
	    // This check will screw gas estimation! Good, good!
   	    if (msg.gas < 100000) {
		    throw;
	    }
	    field = value;
        }
}

Expected Behavior

estimateGas provides the correct gas to successfully execute a tx.

Current Behavior

estimateGas does not always provide the correct gas to successfully execute a tx.

Possible Solution

A simple fix for case 1 is in statemanager.processGasEstimate return the following:
return callback(null, to.hex(results.gasUsed.iadd(results.vm.gasRefund)))

A more thorough solution would be to implement a binary search for estimate gas as geth & metamask do. Possibly just updating the web3-provider-engine version and using their estimateGas method would work, assuming it doesn't break anything else

ethereum/go-ethereum#3587
https://github.com/MetaMask/provider-engine/pull/119/files

I'd be happy to implement either, but thought I'd post for feedback to see what would be preferred.

Steps to Reproduce (for bugs)

Context

Your Environment

  • Version used:
  • Environment name and version (e.g. PHP 5.4 on nginx 1.9.1):
  • Server type and version:
  • Operating System and version:
  • Link to your project:

Allow List of Addresses in Filter

Expected Behavior

Filters are used to track changes (e.g. new logs from a given contract address). According to the JSON-RPC spec for eth_newFilter, the address field should be:

address: DATA|Array, 20 Bytes - (optional) Contract address or a list of addresses from which logs should originate.

The address is allowed to be either:

  • null (to watch everything)
  • a single address to watch
  • an array of addresses to watch

Current Behavior

Currently in ganache, filters work for null or for a single address. When an array of addresses is passed in to eth_newFilter to ganache-core, the resulting filter always return blank (no matches). This is in violation of the spec above.

Possible Solution

StateManager.prototype.getLogs should allow filter.address to be an array and handle that case appropriately. This should be a minor change.

Steps to Reproduce (for bugs)

  1. Deploy any contract with any public function which produces a log (event)
  2. Create a new filter with address=<address from above>
  3. View logs associated with that filter
  4. Created a new filter with address=[<address from above>] (that is, an array)
  5. See no logs associated with that filter

Context

Implementing JSON-RPC / web3 correctly is an important goal for ganache and Truffle.

Your Environment

  • Version used: Truffle v4.0.1 (core: 4.0.1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.