Deploy Your First Solidity Contract on Dune Network

Steven de Oliveira
Dune Network
Published in
5 min readOct 8, 2020


Thanks to David Declerck.

TL;DR This is a step-by-step tutorial that explains how to deploy and interact with Solidity smart contracts on Dune Network blockchain.

Photo by Louis Hansel @shotsoflouis on Unsplash

As announced in this non technical post, the Solidity language has landed on Dune Network. The feature is still in beta phase and under heavy testing. Nonetheless, you can already deploy your solidity contracts on Dune’s development network (Devnet). In this post, we explain how to achieve this task via a step-by-step tutorial.

Caution : The Devnet is intended for Dune Network development team and is reset frequently. We strongly advise you to not start a long-term project on it.

You will need the latest version of the Dune Network with the Solidity extension, available on GitLab in the solidity branch. All the instructions for building the sources are in the file. If you have opam installed, it should be as simple as that:

bash$ git clone
bash$ cd dune-network
bash$ git checkout solidity
bash$ make build-deps
bash$ make
bash$ ./dune-client --help

The Smart Contract

We will deploy the following Solidity smart contract on the Devnet:

#soliditypragma solidity ^0.7.0;// The Player interface. Each player has an opponent that he can
// "ping".
contract Player {
uint pings = 0; // Number of times I have been pinged
address payable opponent; // The player I ping
// Sets the player I will ping
function setOpponent (address payable o) external {
if (opponent == payable(0)){
opponent = o;
// What to call to ping me
function get() public payable {
pings += 1;

// What to call to ping my opponent
function send() public payable{
//Contract initializing opponents
contract Main {
Player ping;
Player pong;
constructor () {
ping = new Player();
pong = new Player();

function call_ping() public {
function call_pong() public {

This main contract’s constructor creates two instances of contract Player, called ping and pong, and an instance of Main. Each player is initialized with the address of its opponent, and can call him. Each player registers the amount of times it has been called by its opponent.

Main has two entry points, call_ping and call_pong, respectively asking ping or pong to call its opponent. For example, if I call the call_ping entrypoint , ping will calls the function get of the pong contract. As a result, the pings field of the latter contract will be incremented by 1.

NB. The smart contract above starts with #solidity directive instead of the usual pragma. This is only a header used in Dune Network to indicate the language of the contract. For instance, Love contracts start with #love.


First of all, you’ll need some “fake” DUNs to start. Download a faucet account (JSON file with some data) and activate it on Devnet as follows:

./dune-client -A -P 80 \
activate account faucet_name with "dn1....json"

To check that/if the activation when correctly (ie. you got some DUN tokens), ask for the balance of your freshly activated account as follows:

./dune-client -A -P 80
get balance for faucet_name

If the activation is successful, you can originate the contract by running the following command (assuming your contract is stored in a file called test.sol):

./dune-client -A -P 80 \
originate contract your_contract \
transferring 0 from faucet_name \
running test.sol \
--init "#solidity:Main()" \
--burn-cap 4

The burn-cap option is set to block originations that would cost more than the option argument (here, the maximum origination cost is set to 4 DUN, which is enough for our small contract).

If everything went well, you should get something like this at the end (of course, the contract addresses will be different from the ones below):

New contract KT1PTXyY6vU5xe2DxBBBsqnDEWMjPYJ4UyaU originated.
New contract KT1RX5jW6SuSEQfLTSkuMP6i3p5jrRJkyywQ originated.
New contract KT18ppTKf37xZzmmQ3ZDL1ZF6r9uwPdHh4iY originated.

In my case, the identifier of my Main contract is


The Ping and Pong instances are respectively (information read from the log output):


Now that the contract(s) have been deployed, you can check them on DunScan by visiting their respective pages at:’the_KT1_address_of_your_contract’.

The page of our KT1 in DunScan

DunScan has seen that our Main contract originated two Player contracts. We can check the origination script.

The Smart Contract we originated

The two other contracts, “ping” and “pong” were also originated with their specific storage.

The storage of “ping”
The storage of “pong”

Interacting with the contract

The generic syntax to call an entry-point of a Solidity smart contract is:

./dune-client -A -P 80 \
transfer <amount in DUN> \
from <account-alias> \
to <contract-alias-or-address> \
--entrypoint <name-of-ep> \
--arg '#solidity:(arg1,arg2, ...)' \
--burn-cap <amount in DUN>

For instance, calling the call_ping entry-point of our main contract can be achieved as follows:

./dune-client -A -P 80 \
transfer 0 \
from faucet_name \
to your_contract \
--entrypoint call_ping \
--arg '#solidity:()' \
--burn-cap 0

If everything went well, you should see this message displayed in the logs:

The operation has only been included 0 blocks ago.

The intended effect of this transaction is to increment the pings field of the pong smart contract. Just visit the page of the contract on DunScan, and inspect its storage to realize that the field has been incremented as expected.

The pong storage after calling “call_ping”. Because “call_ping” calls “ping” that calls “pong”.

Stay Duned for Part II : Differences between Solidity on Ethereum & Dune !

Connect with us: