After Width: | Height: | Size: 269 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 287 KiB |
After Width: | Height: | Size: 265 KiB |
After Width: | Height: | Size: 283 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 265 KiB |
After Width: | Height: | Size: 270 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 249 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 117 KiB |
@ -0,0 +1,205 @@ |
|||||||
|
Debugging a Transaction |
||||||
|
======================= |
||||||
|
|
||||||
|
.. _tutorial-debug: |
||||||
|
|
||||||
|
The goal of this tutorial is to explain how to debug transaction using Remix. |
||||||
|
|
||||||
|
Start debugging |
||||||
|
--------------- |
||||||
|
|
||||||
|
There are two different ways to start debugging, each way correspond to a different use case. |
||||||
|
|
||||||
|
From the Transaction GUI |
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
We will not explain in detail here how to write or deploy contract. |
||||||
|
Let us start with a basic contract (replace this one by yours): |
||||||
|
|
||||||
|
.. code-block:: none |
||||||
|
|
||||||
|
contract Donation { |
||||||
|
address owner; |
||||||
|
event fundMoved(address _to, uint _amount); |
||||||
|
modifier onlyowner { if (msg.sender == owner) _; } |
||||||
|
address[] _giver; |
||||||
|
uint[] _values; |
||||||
|
|
||||||
|
function Donation() { |
||||||
|
owner = msg.sender; |
||||||
|
} |
||||||
|
|
||||||
|
function donate() payable { |
||||||
|
addGiver(msg.value); |
||||||
|
} |
||||||
|
|
||||||
|
function moveFund(address _to, uint _amount) onlyowner { |
||||||
|
uint balance = this.balance; |
||||||
|
uint amount = _amount; |
||||||
|
if (_amount <= this.balance) { |
||||||
|
if (_to.send(this.balance)) { |
||||||
|
fundMoved(_to, _amount); |
||||||
|
} else { |
||||||
|
throw; |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function addGiver(uint _amount) internal { |
||||||
|
_giver.push(msg.sender); |
||||||
|
_values.push(_amount); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
For the purpose of this tutorial we will run the ``JavaScript VM`` (that's the default mode if you don't use Remix with Mist or Metamask) which simulates a custom blockchain. You could do the same using a proper backend node. |
||||||
|
|
||||||
|
Let's deploy the contract: |
||||||
|
|
||||||
|
Right panel / Red button ``Create`` |
||||||
|
|
||||||
|
.. image:: remix1.png |
||||||
|
|
||||||
|
Then we should call the ``Donate`` function (that will send Ether to the contract). |
||||||
|
|
||||||
|
Let's set the amount of Ether: |
||||||
|
|
||||||
|
Right panel / second tab from the left - fill in the ´´value´´ input (´1 ether´ for instance) |
||||||
|
|
||||||
|
.. image:: remix_valueinput.png |
||||||
|
|
||||||
|
Then click on ``Donate``. As we are using the ``JavaScript VM``, everything goes almost instantly. |
||||||
|
|
||||||
|
Remix displays also some information related to each transaction result. On the right of each transaction result |
||||||
|
you can start debugging the corresponding transaction. |
||||||
|
|
||||||
|
.. image:: remix_startdebugging.png |
||||||
|
|
||||||
|
From the Debugger |
||||||
|
~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
The debugger can be found in the right panel / 5th tab from the left. |
||||||
|
|
||||||
|
You can start a debug session by providing either a ``transaction hash`` or a ``block number`` and ``transaction index`` |
||||||
|
|
||||||
|
.. image:: remix3.png |
||||||
|
|
||||||
|
Click the ``play`` button to start debugging. |
||||||
|
|
||||||
|
Using the debugger |
||||||
|
------------------ |
||||||
|
|
||||||
|
The debugger allows to see detailed informations about the transaction execution. It uses the editor (left panel) to display the location |
||||||
|
in the source code where the current execution is. |
||||||
|
|
||||||
|
First the transaction panel display basic and simple information about the current transaction. |
||||||
|
|
||||||
|
.. image:: remix_debugtransactioninfo.png |
||||||
|
|
||||||
|
The navigation part contains a slider and buttons that can be used to step through the transaction execution. |
||||||
|
|
||||||
|
From the left to the right: |
||||||
|
|
||||||
|
step over back, step into back, step into forward, step over forward, jump out (jump out of the current call), jump to the previous breakpoint, jump to the next breakpoint. |
||||||
|
|
||||||
|
.. image:: remix_navigation.png |
||||||
|
|
||||||
|
11 panels give detailed informations about the execution: |
||||||
|
|
||||||
|
Instructions |
||||||
|
~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. image:: remix_debuginstructions.png |
||||||
|
|
||||||
|
This panel displays the bytecode of the current executing contract, the current step is highlighted. |
||||||
|
|
||||||
|
Important note: |
||||||
|
When this panel is hidden, the slider will have a courser granularity and only stop at expression boundaries, even if they are compiled into multiple EVM instructions. |
||||||
|
When the panel is diplayed, it will be possible to step over every instruction, even those that refers to the same expression. |
||||||
|
|
||||||
|
Solidity Locals |
||||||
|
~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. image:: remix_soliditylocals.png |
||||||
|
|
||||||
|
That panel displays local variables associated with the current context. |
||||||
|
|
||||||
|
Solidity State |
||||||
|
~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
.. image:: remix_soliditystate.png |
||||||
|
|
||||||
|
That panel displays state variables of the current executing contract. |
||||||
|
|
||||||
|
Low level panels |
||||||
|
~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
These panels display low level informations about the execution: |
||||||
|
|
||||||
|
- Stack |
||||||
|
- Storages Changes |
||||||
|
- Memory |
||||||
|
- Call Data |
||||||
|
- Call Stack |
||||||
|
- Return Value (only if the current step is a RETURN opcode) |
||||||
|
- Full Storages Changes (only at the end of the execution - display every storage change of every modified contract) |
||||||
|
|
||||||
|
Reverted Transaction |
||||||
|
~~~~~~~~~~~~~~~~~~~~ |
||||||
|
|
||||||
|
A transaction could be reverted (either because of out of gas exception, Solidity ``throw`` or low level exception). |
||||||
|
|
||||||
|
In that case it is important to be aware of the exception and to locate where the exception is in the source code. |
||||||
|
|
||||||
|
Remix will warn you when the execution throws an exception. The ``warning`` button will jump to the last opcode before the exception happened. |
||||||
|
|
||||||
|
.. image:: remix_executionexception.png |
||||||
|
|
||||||
|
Breakpoints |
||||||
|
~~~~~~~~~~~ |
||||||
|
|
||||||
|
The two last buttons from the navigation area are used to jump either back to the previous breakpoint or forward to the next breakpoint. |
||||||
|
|
||||||
|
Breakpoints can be added and removed by clicking on the line number. |
||||||
|
|
||||||
|
.. image:: remix_breakpoint.png |
||||||
|
|
||||||
|
When a debug session is started, the execution will jump to the first encountered breakpoint. |
||||||
|
|
||||||
|
Important note: |
||||||
|
If you add a breakpoint to a line that declares a variable, it might be triggered twice: Once for initializing the |
||||||
|
variable to zero and second time for assigning the actual value. |
||||||
|
As an example, assume you are debugging the following contract: |
||||||
|
|
||||||
|
.. code-block:: none |
||||||
|
|
||||||
|
contract ctr { |
||||||
|
function hid () { |
||||||
|
uint p = 45; |
||||||
|
uint m; |
||||||
|
m = 89; |
||||||
|
uint l = 34; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
And let's says that breakpoints are set for the lines |
||||||
|
|
||||||
|
``uint p = 45;`` |
||||||
|
|
||||||
|
``m = 89;`` |
||||||
|
|
||||||
|
``uint l = 34;`` |
||||||
|
|
||||||
|
|
||||||
|
then clicking on ``Jump to next breakpoint`` will stop at the following lines in the given order: |
||||||
|
|
||||||
|
``uint p = 45;`` (declaration of p) |
||||||
|
|
||||||
|
``uint l = 34;`` (declaration of l) |
||||||
|
|
||||||
|
``uint p = 45;`` (45 assigned to p) |
||||||
|
|
||||||
|
``m = 89;`` (89 assigned to m) |
||||||
|
|
||||||
|
``uint l = 34;`` (34 assigned to l) |
@ -0,0 +1,35 @@ |
|||||||
|
Importing Source Files in Solidity |
||||||
|
================================== |
||||||
|
|
||||||
|
.. _tutorial-import: |
||||||
|
|
||||||
|
This tutorial will show you how to import local and external files. |
||||||
|
|
||||||
|
The compilation result will also contain contracts implemented in the imported files. |
||||||
|
|
||||||
|
For a detailed explanation of the ``import`` keyword see the ``Solidity`` |
||||||
|
`documentation <http://solidity.readthedocs.io/en/develop/layout-of-source-files.html?highlight=import#importing-other-source-files>`_ |
||||||
|
|
||||||
|
Importing a local file |
||||||
|
---------------------- |
||||||
|
|
||||||
|
Other files in Remix can be imported just by specifying their path. |
||||||
|
Please use `./` for relative paths to increase portability. |
||||||
|
|
||||||
|
.. image:: tuto_basicimport.png |
||||||
|
|
||||||
|
Importing from Github |
||||||
|
---------------------- |
||||||
|
|
||||||
|
It is possible to import files directly from github with URLs like |
||||||
|
``http://github.com/<owner>/<repo>/<path to the file>``. |
||||||
|
|
||||||
|
.. image:: tuto_importgit.png |
||||||
|
|
||||||
|
Importing from Swarm |
||||||
|
-------------------- |
||||||
|
|
||||||
|
Files can be imported using all URLs supported by swarm. If you do not have a swarm |
||||||
|
node, swarm-gateways.net will be used instead. |
||||||
|
|
||||||
|
.. image:: tuto_importswarm.png |