How to do the SC right in Sophia?


#1

Hello guys,

I’m quite new to æternity blockchain and functional programming. I have some experience with imperative languages like C, JavaScript etc. Still, I decided to try Sophia and I’m stuck.

My goal is to write the contact that similar to this one written in Solidity:

pragma solidity ^0.4.25;

contract CryptoZombie {
    
    event NewZombie(uint hamsterId, string name, uint dna);
    
    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;
    
    struct Zombie {
        string name;
        uint dna;
    }
    
    Zombie[] public zombies;
    
    function _createZombie(string _name, uint _dna) private {
        uint id = hamsters.push(Hamster(_name, _dna)) - 1;
        emit NewHamster(id, _name, _dna);
        
    }
    
    function _generateRandomDna(string _str) private returns (uint) {
        uint rand = uint(keccak256(abi.encodePacked(_str)));
        return rand % dnaModulus;
    }
    
    function createRandomZombie(string _name) public {
        uint randDna = _generateRandomDna(_name);
        _createHamster(_name, randDna);
    }
}

I have only a very broad understanding of how to do it. Here’s what I’ve done so far:

contract CryptoZombie = 
    let dnaDigits = 16
    let dnaModulus = 10 % dnaDigits
    
    type Zombie {
        name: string,
        dna: uint
    }

    private function create_zombie(new_name:string, new_dna:int) =      

    private function generate_random_dna(str:string) =
        

    public function create_random_zombie(name:string) =

So, my questions are:

  1. Do Sophia supports modulus operator? Your contract editor shows me an error: “While calling compileContract (body), POST to //sdk-testnet.aepps.com/v2/debug/contracts/code/compile failed with 403: {case_clause,{error,{scan_error,{3,25},”% 16"}}}"
  2. For creating a struct in Sophia, should I use type or ‘record state’? I don’t have a good understanding which one to choose.
  3. How can I create the array of structs like in Solidity? I know that Sophia doesn’t support arrays, so what should I choose: lists or tuples, or maybe even maps?
  4. How to push a new zombie to the list/array/map? I mean, how to do it in the most correct way?
  5. How can I implement pseudo-random generation, e.g. uint rand = uint(keccak256(abi.encodePacked(_str))); in Sophia? Does it support any hash-function?
  6. I know that events aren’t implemented yet, but still, how to write them correctly and how to fire them in functions?

#2

Hey @nsw,

I’ve forwarded your question to our dev team, they will get back to you as soon as they can.
Keep playing with Sophia :wink:

Best,
Albena


#3

The easiest answer is go here Developing æpps for the æternity blockchain where, amongst many other things, Sophia is described with many examples . There are two mistakes in it: the the less-than-or-equals operator is =< and lists are typed with list(t). There is an example which does include events although they currently don’t exist. They’re on their way.

Some quick answers:

  1. The modulo operator is mod.
  2. You would use record for that. The state is also a record but with special meaning, it is persistent over function calls into the contract.
  3. I would use a map for this with the keys as numbers. Maps don’t have a predetermined size only type.

#4

Thanks for your answer, I’m now diving into functional programming (reading articles and books) because it’s crucial for writing code in Sophia.

However, here’s what I’ve done. And I have several new questions written as comments to the contract :slightly_smiling_face:

contract CryptoHamster = 
      let dnaDigits = 16
      let dnaModulus = 10000000000000000 // 10 ** dnaDigits == 10 ** 16. It seems Sophia does not support pow (power) operator
        
      type Hamster {
        name: string,
        dna: uint
      }

      type hamsters = map(int, Hamster) // is it okay?
      // how to make it smth like this one: event NewHamster(uint hamsterId, string name, uint dna) ???
      type event = 

      private function create_hamster(new_name:string, new_dna:int) =
        
        // I need smth like this: uint id = hamsters.push(Hamster(_name, _dna)) - 1;
        // How to do a push to the map right?
        event() // fire an event here

      private function generate_random_dna(str:string) =
        // I want to create a hash of the input str
        // let rand = int(str_hash))
        rand mod dnaDigits // is it right?
            
      public function create_random_hamster(name:string) =
        let randDna = int(generate_random_dna(name))
        create_hamster(name, randDna)