Begining SC with Sophia


#1

Hi everyone,
I’m trying to learn to create a SC with Sophia, but I’m stuck when trying to compile.
I’m learning with 3 different documentations :

  • /dev.aepps.com/aepp-sdk-docs/Sophia.html
  • /github.com/aeternity/protocol/blob/master/contracts/sophia.md
  • /github.com/aeternity/epoch/tree/master/apps/aesophia/test/contracts

But it seems that some docs are not up to date (about map() or events, for example), and I’m not sure about how much is implemented in the app https://contracts.aepps.com/

It also possible that my code is wrong, I don’t know, but can someone confirm that I can create events, and Map.lookup is a implemented function ?

Thank you.


#2

Hey, I have forwarded your question to the dev team :slight_smile:


#3

Sophia是用来写合约的,不是用来创建状态通道的,你应该用JsSDK或者pySdk来创建


#4

:+1: waiting for their answer :grin:


#5

Hi @zorg

Events are not yet merged (they’re in a PR now) as you can see in protocol/contracts/sophia.md#events. This repo is probably the best source of truth since the core developers that create Sophia, continuously update it.

There again, at protocol/contracts/sophia.md#builtin-functions-on-maps there is a list of all built-ins for maps. Map.lookup is one of them and it is working.

What relates to github.com/aeternity/epoch/tree/master/apps/aesophia/test/contracts - there are a lot of different approaches for contract language design that had been tried out there. Most of those concepts had later on been refined in what currently Sophia is but some concepts had not yet made it in. So these are proto-contracts and some of them ado not compile at all. Please use them as a source of inspiration and not as a source of truth.


#6

Hi @Dimitar.Ivanov
Thanks for your answer. It’s a little more clear for me.
Can you confirm me that uint are not yet implemented ? Some compilations didn’t worked for me with it ?

I tried to clean up my code, but now I don’t know if I’m wrong because of my lack of knowledge of Sophia of because I’m trying something not yet implemented.

Thanks to tell me if it’s better to create another topic instead of using this one, but can someone correct me this code ?

contract SomeToken =
    type balances = map(address, int)

    public function memberOf(owner : address) : int = 
        switch(Map.member(owner, balances))
            true => balances[owner]
            _    => 0

    public function lookupOf(owner : address) : int = 
        switch(Map.lookup(owner, balances))
            None 	=> 0
            Some(n) => n

I got a 403 : type_errors so I suppose it is Sophia grammar related…?


#7

Hi @zorg

Main reason your contract does not compile is misunderstanding of types and state. You can have a lot of different types and records and play with those. Only one could represent your state but it can get as complex as you need it to be.

I took the liberty of refactoring your code a bit.

contract SomeToken =

  type balances_t = map(address, int)

  record state = { balances : balances_t }

  public function init() : state =
    { balances = {}
      }


  public function memberOf(owner : address) : int =
    switch(Map.member(owner, state.balances))
      true => state.balances[owner]
      _    => 0

  public function lookupOf(owner : address) : int =
    switch(Map.lookup(owner, state.balances))
      None  => 0
      Some(n) => n

Main things changed:

  1. Renamed the balances type to balances_t - this does not hold state, it is just an alias for the map(address, int)
  type balances_t = map(address, int)
  1. Created a new record to hold the state - state. It has a member balances of type balances_t that will hold all balances. You can extend the record to have other members as well. If you want to store something and later modify it or look it up - this is the place to add it.
  record state = { balances : balances_t }
  1. Introduced a public function init(). As described in the protocol - if you plan on having a state, you must have an init function. It can take any number of arguments but it must return the initial state. In the example bellow the initial balances map is empty.
  public function init() : state =
    { balances = {}
      }
  1. Modified the functions to use the balances from the state (replaced balances with state.balances :wink:). In your code you were looking up into the balances which used to be a type and this doesn’t make much sense as types are stateless. If you want to use a state - that’s what contract state is for.

At the moment please use int. The uint type still needs some polish :slight_smile:


#8

Haaaa ok, I totally missed the part type/state. Seems more clear now.
So if I have understood, when events will be available, I’ll have something like that :

type balances_t = map(address, int)
type canTransfer_e (e : event) = (address, int)

record state = { balances : balances_t, canTransfer : canTransfer_e }

public function init() : state =
  { balances = {}
    }

 public function memberOf(owner : address) : int =
    switch(Map.member(owner, state.balances))
      true => 
            state.transfer(owner, someValue)
            state.balances[owner]
      _    => 0

BUT I can also use events in another record ? Not necessarily in this state.

I hope I’m right… :sweat:


#9

I am afraid events are something completely different. They are a means to provide a list of this happened during the call messages. Events are emitted subsequently, one by one, and thus form a chronologically ordered list. You might think of them as a form of a log regarding the contract call. Once the call had been executed - you can read the list of events from the call object that had been produced. Or you can filter microblocks by certain events that happened in them. Events (will) provide a lot of different mechanisms to be exposed to users.

Although syntax around them is yet to be done, most probably events are going to be emitted by built-in functions (that you can further customize). After being emitted - they’d go in the call object for that call. Once emitted - contract will have no control over them anymore. From this perspective - it doesn’t make sense to have an event’s structure in your contract’s state (as events are handled for you by the virtual machine).

Stay tuned for events. Once they’re done, the protocol document will be updated accordingly.


#10

Thanks. All clear for me, and waiting for more news about events. :+1: