Jump to content
Sign in to follow this  
RandyArl

I want to learn to create dApps on Elrond. Where should I start?

Recommended Posts

mascot9.png.01acb6642004a9afa68e3ea7cadc34a1.png

I know mainnet is still months ahead, but I'd like to prepare myself and learn about making dApps first.

Do you have any suggestion on what language should I learn? Which platform should I use? 
I've done my own research but I think community will have a better suggestion which can bring better future potentials. Thank you  😁

Share this post


Link to post
Share on other sites

Hi Randy!

That is wonderful. We are open and will support and help members who want to write and deploy smart contracts on Elrond. What kind of languages are you familiar with ? We have several VMs which support several programming languages. (IELE, C, C++, RUST, TYPESCRIPT, even Solidity with transcompiler). We already have an extention for Visual Studio Code through which you can test and debug your smart contract - currently supporting C, C++ and RUST. https://github.com/ElrondNetwork/vscode-elrond-c

In this repository you can see  contract examples written in IELE: https://github.com/ElrondNetwork/elrond-vm/tree/master/iele/elrond/tests

I would suggest for you to write either in IELE or in RUST. We are compatible with EVM, so you can even use the ethereum Environment Interface, but we started creating our own Environment Interface which might be easier to use: https://github.com/ElrondNetwork/arwen-wasm-vm/blob/master/arwen/elrondei.go

Here is an example of an ERC20 type of contract written in C which can be compiled to wasm and run on our VM. Feel free to try it out. It is a more complicated version as you have to control all the memory and pointer. It is much easier on RUST.

// to avoid includes from libc, just hard-code things
typedef unsigned char uint8_t;
typedef int int32_t;
typedef int uint32_t;
typedef unsigned long long uint64_t;

// types used for Ethereum stuff
typedef uint8_t* bytes; // an array of bytes with unrestricted length
typedef uint8_t bytes32[32]; // an array of 32 bytes
typedef uint8_t address[32]; // an array of 20 bytes
typedef unsigned __int128 u128; // a 128 bit number, represented as a 16 bytes long little endian unsigned integer in memory
//typedef uint256_t u256; // a 256 bit number, represented as a 32 bytes long little endian unsigned integer in memory
typedef uint32_t i32; // same as i32 in WebAssembly
typedef uint32_t i32ptr; // same as i32 in WebAssembly, but treated as a pointer to a WebAssembly memory offset
typedef uint64_t i64; // same as i64 in WebAssembly

// functions for ethereum stuff
void getCaller(i32ptr* resultOffset);
int32_t getArgument(i32 id, i32ptr* argOffset);
int32_t getNumArguments();
void signalError();
void finish(i32ptr* dataOffset, i32 dataLength);
i32 storageStore(i32ptr* pathOffset, i32ptr* resultOffset, i32 dataLength);
i32 storageLoad(i32ptr* pathOffset, i32ptr* resultOffset);
long long storageLoadAsInt64(i32ptr* keyOffset);
i32 storageStoreAsInt64(i32ptr* keyOffset, long long value);
i32 getCallValue(i32ptr* resultOffset);
uint64_t getArgumentAsInt64(i32 id);
   //the memory offset to load the path from (bytes32), the memory offset to store/load the result at (bytes32)


i64 reverse_bytes(i64 a){
  i64 b = 0;
  b += (a & 0xff00000000000000)>>56;
  b += (a & 0x00ff000000000000)>>40;
  b += (a & 0x0000ff0000000000)>>24;
  b += (a & 0x000000ff00000000)>>8;
  b += (a & 0x00000000ff000000)<<8;
  b += (a & 0x0000000000ff0000)<<24;
  b += (a & 0x000000000000ff00)<<40;
  b += (a & 0x00000000000000ff)<<56;
  return b;
}


// global data used in next function, will be allocated to WebAssembly memory
bytes32 addy[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
bytes32 balance[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void do_balance() {
  if (getNumArguments() < 1)
    signalError();

  // get address to check balance of, note: padded to 32 bytes since used as key
  getArgument(0, (i32ptr*)addy);

  // get balance
  storageLoad((i32ptr*)addy, (i32ptr*)balance);
  // return balance
  finish((i32ptr*)balance, 8);
}


// global data used in next function, will be allocated to WebAssembly memory
bytes32 sender[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
bytes32 recipient[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
bytes32 value[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
bytes32 recipient_balance[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
bytes32 sender_balance[1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void transfer() {
  if (getNumArguments() < 2)
    signalError();

  // get caller
  getCaller((i32ptr*)sender);

  getArgument(0, (i32ptr*)recipient);
  getArgument(1, (i32ptr*)value);

  // get balances
  storageLoad((i32ptr*)sender, (i32ptr*)sender_balance);
  storageLoad((i32ptr*)recipient, (i32ptr*)recipient_balance);
  *(i64*)sender_balance = reverse_bytes(*(i64*)sender_balance);
  *(i64*)recipient_balance = reverse_bytes(*(i64*)recipient_balance);
  // make sure sender has enough
  if (*(i64*)sender_balance < *(i64*)value)
    signalError();

  // adjust balances
  * (i64*)sender_balance -= * (i64*)value;
  * (i64*)recipient_balance += * (i64*)value;

  *(i64*)sender_balance = reverse_bytes(*(i64*)sender_balance);
  *(i64*)recipient_balance = reverse_bytes(*(i64*)recipient_balance);
  storageStore((i32ptr*)sender, (i32ptr*)sender_balance, 8);
  storageStore((i32ptr*)recipient, (i32ptr*)recipient_balance, 8);
}

void topUp() {
  // getPlayer
  getCaller((i32ptr*)sender);
  // getJoinValue
  getCallValue((i32ptr*)value);

  // get balances
  storageLoad((i32ptr*)sender, (i32ptr*)sender_balance);
  *(i64*)sender_balance = reverse_bytes(*(i64*)sender_balance);

  // adjust balances
  *(i64*)sender_balance += * (i64*)value;
  *(i64*)sender_balance = reverse_bytes(*(i64*)sender_balance);
  storageStore((i32ptr*)sender, (i32ptr*)sender_balance, 8);
}

// global data used in next function, will be allocated to WebAssembly memory
i32 selector[1] = {0};
void _main(void) {
}

  • Like 1

Share this post


Link to post
Share on other sites

I think you send the binary payload as data on a transaction to an address with lots or all zeros. It should create a smart contract.

Please correct me if I'm wrong, it's all I can remember on this topic, I haven't tried it myself.

Edited by Sorin Pop

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...