Contract Debugging

Debugging Environment

In order to debug smart contract, you need setup a local full node and perform contract debugging through your node's RPC interface.

We provide 2 debugging environments: development and testing. The difference is that account balance will not be examined before sending transaction in development environment, and each transaction has 1,000,000 quota automatically. In testing environment, checks for quota and balance will be the same as Vite TestNet. It's necessary to maintain sufficient balance or quota when debugging.

In development environment, it is also possible to debug your smart contract in Microsoft Visual Studio Code(aka VS Code).

Debugging in VS Code

Soliditypp extension for VS Code supports debugging solidity++ smart contract in local development environment.

Following features are supported:

  • solidity++ syntax highlighting
  • solidity++ code auto completion
  • Auto compilation when saving .solpp file
  • Compilation error highlighting
  • Detailed error message displaying when mouse over
  • One-click smart contract deployment and debugging
  • Support for multiple smart contract interaction
  • Deployment/debugging result displaying
  • Example solidity++ code

Install the Extension

Search for "Soliditypp" in VS Code and install.

Create HelloWorld.solpp

Open VS Code workbench, press ⇧⌘P(or F1) in Mac(or Ctrl+Shift+P in Windows) to bring Command Palette, and then execute command soliditypp: Generage HelloWorld.solpp. This will generate HelloWorld.solpp under current folder as an example.

Write Smart Contract

Write your contract in a new .solpp file and then save it by pressing ⌘S in Mac(or Ctrl+S in Windows). Your source file will be automatically compiled each time it is saved. Lines with compilation error in the code will be marked with red underscore. Detailed error message will be displayed when you mouse over.

VS Code will recognize .solpp file as solidity++ source by default.

Deploy/Debug Smart Contract

In Debug panel, start debugging and choose Soliditypp environment. This will launch a local gvite node and all following deployment and debugging steps will take place on this node. Please note that all data will be cleared from the node after debugging is complete.

  • Section 1: soliditypp source code panel
  • Section 2: shows current account address that will be used for contract deployment and debugging. Additional address can be created by clicking +. Use droplist in right side to switch to a different address if necessary
  • Section 3: deployment panel. Field amount can be used to send a certain amount of VITE tokens in attov(1 VITE = 1e18 attov) when deploying the contract. Click deploy button to deploy the contract in local development environment.
  • Section 4: list of contracts deployed. Multiple contracts will be displayed if more than one are deployed
  • Section 5: list of contract methods deployed. Multiple methods will be displayed if more than one are present. Parameter amount is used to send VITE tokens(in attov) to contract when calling the method. In our example, click call "SayHello" button will call SayHello of contract HelloWorld
  • Section 6: deployment/debugging result. Request and Response sections will show the information of request or response transaction respectively. New request transaction will be displayed in Response if the method still calls other function. Please note that transactions in Vite are executed asynchronously. User may need wait for a while before response transaction is generated, after a request is sent out. More information about Request and Response please see AccountBlock

Debugging in Command Line

Development Environment

Download Gvite Debugging Package in development environment and install

Install

## Unzip
tar -xzvf contractdev-v1.3.1-darwin.tar.gz
## Enter folder extracted
cd contract_dev
## Start gvite debugging environment
sh run.sh

Check gvite.log to see if gvite debugging environment has been started successfully

cat gvite.log

Following messages show a successful startup

t=2018-11-09T17:44:48+0800 lvl=info msg=NodeServer.DataDir:/home/ubuntu/contract_dev/ledger/devdata module=gvite/node_manager
t=2018-11-09T17:44:48+0800 lvl=info msg=NodeServer.KeyStoreDir:/home/ubuntu/contract_dev/ledger/devdata/wallet module=gvite/node_manager
Prepare the Node success!!!
Start the Node success!!!

Create Contract

First write contract in Solidity++ and save into a ".solpp" file under the same directory with start script

Compile contract

## Compile contract using solppc, and genereate binary code and ABI
./solppc --bin --abi HelloWorld.solpp

Deploy contract in local debugging environment

## Create contract from HelloWorld.solpp with test account(created during startup)
sh create_contract.sh HelloWorld.solpp
## Below script shows how to create contract with passed-in parameters
curl -X POST \
  http://127.0.0.1:48132/ \
  -H 'content-type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 0,
    "method": "vmdebug_createContract",
    "params": [
        {
          "fileName":"'`pwd`/AsyncCall.solpp'",
          "params":{
            "A":{
              "amount":"0",
              "params":[]
            },
            "B":{
              "amount":"0",
              "params":["1"]
            }
          }
        }
    ]
}'

The parameters are explained below

{
  // Create contract from AsyncCall.solpp under current directory
  "fileName":"'`pwd`/AsyncCall.solpp'",
  "params":{
    // Passed-in parameters for contracts. This example shows two contracts - A and B
    "A":{
      // Transfer amount when creating contract
      "amount":"0",
      "params":[]
    },
    "B":{
      "amount":"0",
      // Passed-in parameters for contructor. In this example, it passes in a uint value for contract B's contructor
      "params":["1"]
    }
  }
}

Following return message shows the contract has been created successfully

{
  "jsonrpc": "2.0", 
  "id": 0, 
  "result": [
    {
      "accountAddr": "vite_21483c46a64799c7db0cba88cf7b007a2d1a37e863f7be94b7", 
      "accountPrivateKey": "b18bcd61db171fb0c97712c24dbfc4fe7d279a6e9f40be2a81f5e279206887237ee77ed82025fbe821a969cc8321c139ed69dde16bed9c5dfabbc6343868bb68", 
      "contractAddr": "vite_d624b0bead067237700a86314287849163e4a0fb6139fdff42", 
      "sendBlockHash": "265930575e035976f0e89b7b4ad00c5e91fefc9230647b47dadd7c7274797d3b", 
      "methodList": [
        {
          "contractAddr": "vite_d624b0bead067237700a86314287849163e4a0fb6139fdff42", 
          "accountAddr": "vite_21483c46a64799c7db0cba88cf7b007a2d1a37e863f7be94b7", 
          "amount": "0", 
          "methodName": "SayHello", 
          "params": [
            "address"
          ]
        }
      ]
    }
  ]
}

Explained below

{
  "jsonrpc":"2.0",
  "id":0,
  "result":[ 
    // List of contracts created. If multiple contracts exist in the .solpp file, they will all be listed here
    {
      // Test account address
      "accountAddr":"vite_21483c46a64799c7db0cba88cf7b007a2d1a37e863f7be94b7",  
      // Test account private key
      "accountPrivateKey":"b18bcd61db171fb0c97712c24dbfc4fe7d279a6e9f40be2a81f5e279206887237ee77ed82025fbe821a969cc8321c139ed69dde16bed9c5dfabbc6343868bb68",
      // Contract account address
      "contractAddr":"vite_d624b0bead067237700a86314287849163e4a0fb6139fdff42",
      // Hash of request transaction that created the contract
      "sendBlockHash":"265930575e035976f0e89b7b4ad00c5e91fefc9230647b47dadd7c7274797d3b",
      // Method list of the contract
      "methodList":[
        {
          // Contract account address
          "contractAddr":"vite_d624b0bead067237700a86314287849163e4a0fb6139fdff42",
          // Test account address 
          "accountAddr":"vite_21483c46a64799c7db0cba88cf7b007a2d1a37e863f7be94b7",
          // Transfer amount when the method is called
          "amount":"0",
          // Method name
          "methodName":"SayHello",
          // Parameter list with pseudo value. Multiple parameters are displayed if the method requires more than one pararmeter.
          "params":["address"]
        }
      ]
    }
  ]
}

Call Contract

## Call a contract method. Remember to specify the right parameters that match your testing environment
curl -X POST \
  http://127.0.0.1:48132/ \
  -H 'content-type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 0,
    "method": "vmdebug_callContract",
    "params": [
        {
          "contractAddr":"vite_d624b0bead067237700a86314287849163e4a0fb6139fdff42",
          "accountAddr":"vite_21483c46a64799c7db0cba88cf7b007a2d1a37e863f7be94b7",
          "amount":"0",
          "methodName":"SayHello",
          "params":["vite_21483c46a64799c7db0cba88cf7b007a2d1a37e863f7be94b7"]
        }
    ]
}'

Return message is explained below

{
    "jsonrpc": "2.0", 
    "id": 0, 
    "result": {
        // Contract account address
        "contractAddr": "vite_0a49d38e769162f05d0df645b890ac450f80cb49d52e8765ab", 
        // Test account address that called the contract. This account was created automatically when your created the contract
        "accountAddr": "vite_a4aa32b30a4564d3c5ffac1f7416d09cd4dd36bbf365df5be5", 
        // Test account private key
        "accountPrivateKey": "2bef2ba485ed3e4de8b93bd0fb8746db47a91f4bdde0c007127b5bc6548ff49642d4138c403cc26e20299a2f145687bf562f6ba1e7d0d45a75d7c7f58de42b25", 
        // Hash of request transaction that called the contract
        "sendBlockHash": "eea88399209cd5abdedec1128b8bdfd1a28e2d6ac6ade6d5cee72e997a800893"
    }
}

Script call.sh shows an example how to call a contract

Verify Execution Result

Since the response transactions of creating or calling contract are processed asynchronously, we have to wait for a while(1~6s in local environment) after sending out the request. Executing steps and results are recorded in two separate logs.

Logs are under /ledger/devdata/vmlog in the folder unzipped

  • vm.log:Contains logs of contract execution entrance, result and events
  • interpreter.log:Contains detailed info of contract execution steps, including VM instructions, status of stack, memory, storage and etc.

It's also feasible to query contract account chain to check contract execution result

sh query_block.sh vite_0a49d38e769162f05d0df645b890ac450f80cb49d52e8765ab

Testing Environment

Download Gvite Debugging Package in testing environment and install

Install

Installation steps in testing environment are similar as in development environment. See Install.

Initialize

Since account balance and quota will be verified in testing environment, additional initialization is required for the first boot-up.

Following steps are finished during initialization

  • A total supply of VITE tokens are sent to genesis account. This step needs calculate a PoW, so it may take some time
  • Waiting for a new snapshot block
  • Genesis account stakes for itself(in the purpose of sending subsequent transactions). This step needs calculate a PoW, so it may take some time
  • Waiting until quota is received
sh init.sh

Create Test Account

Remember to create new test account and stake for the account each time gvite has been rebooted. The test account will be used to create or call contract.

Following steps are finished during account creation

  • Creating new test account address
  • A amount of tokens are sent out from genesis account to test account
  • Tokens are received by test account
  • Genesis account stakes for test account to obtain quota
  • Test account waits to receive quota
sh create_account.sh

Create Contract

Compared with in development environment, additional test account address should be specified when running create_contract.sh

sh create_contract.sh HelloWorld.solpp vite_d5fe580d0ba8fa4002e2a33af2cd10645a58ad1552d4562c0a

Run pledge_for_contract.sh to stake for contract account created

sh pledge_for_contract.sh vite_8739653f7fee7e39c3fbeee14e8c17fe4f7ff20e8607fb05ab

Call Contract

See Call Contract in development environment