
Hello everyone!
Recently, Waves Labs held a competition for developers timed to the launch of the test network extension of the RIDE smart contract language for decentralized applications Ride4Dapps!
We chose the DAO case, because plans to develop a dApp with social features: voting, fundraising, trust management, etc.
We started with a simple example in and in — an example with .
Let's analyze this example, test our hypotheses, and consider some peculiarities:
Let’s have Alice — the dApp Owner
Boob and Cooper — Alice's partners, co-founders of the Alice-BC DAO
Neli — a business owner in need of funding
Bank — the bank distributing tokens
Stage 1. Initializing balances
To obtain tokens in the Waves test network, you need to contact and specify the address to which the tokens should be sent.
You can find the address in the IDE by revealing account details.
We allocate 10 WAVES to the Bank. After that, we check that they have arrived via the block and transaction explorer:
Now let's distribute tokens from the Bank to the other participants. (Notes: All transactions on the Waves network are not free, so a minimal positive balance is necessary for all participants to perform transactions).
1 WAVES = 100000000 units (wavelets), since amounts can only be integers
0.01 WAVES (Transaction Fee) = 1000000
Bank -> [3 WAVES] -> Alice, via TransferTransaction (Type: 4).
We check that env.SEED, from which the transactions are signed, corresponds to our Bank:


If you do not have the corresponding seed phrase, just switch to it in the Accounts tab and check again.
After this, we create, announce, and sign the transaction for transferring 3 WAVES to Alice.
Alice's data can also be obtained via the env.accounts variable. Numbering starts from 0, so Alice is env.accounts[1].

broadcast(transfer({recipient:address(env.accounts[1]), amount: 300000000, fee: 1000000}))The result can also be observed in the explorer; the link to it will be returned to us immediately after the transaction is executed. .
We verify that Alice's balance has increased by 3 WAVES and that the Bank's balance is 10 — 3 — 0.01 = 0.699.


We send Boob and Cooper 3 WAVES each, and Neli, Xena, and Mark 0.2 WAVES in the same way.
(Notes: We made a mistake by one digit and sent Neli 0.02 WAVES. Be careful!)
broadcast(transfer({recipient:address(env.accounts[4]), amount: 20000000, fee: 1000000}))After replenishing all participants' balances, we see:

Stage 2. Creating a dApp account
We agreed that Alice will be the creator and owner of the decentralized application.
In Accounts, we set her as SEED and check that env.SEED matches Alice.
Let's try to install the simplest script (contract) possible on Alice's account.
Smart contracts in Waves are predicates that restrict or allow a certain type of outgoing transaction to occur under specific conditions. In this case, the condition is ALWAYS. The contract code is true. We call deploy().

The fee for the setScript transaction is 1400000/100000000 = 0.014 WAVES. Alice now has 2.986 WAVES left in her balance.
Now, let's try to install a more complex logic for the smart contract on Alice's account, as described in
Ride4Dapps now includes 2 new types of annotations:
- @Callable(i) — accepts as a parameter i, which contains data about which account called/signed the transaction. The result of this function determines the change of state of the dApp account. Other accounts can create transactions and execute functions with this annotation and change the state of the dApp account.
- @Verifier(tx) — A transaction verifier with a parameter tx for the transaction. It corresponds to the predicate logic from RIDE. In this expression, you can allow or prohibit further changes to the logic of smart contracts on the dApp account.
Let’s create a dApp account as a shared wallet for all participants.

To check which contract is currently active on the account, you can copy the base64 code of the smart contract in the block explorer and decode it through a decompiler ()



We make sure that the logic of the smart contract corresponds to our expectations.
Alice now has 2.972 WAVES left in her balance.
This dApp keeps track of how much each participant contributes to the common fund through the mechanism of data transaction — DataEntry(currentKey, newAmount), where currentKey is the account calling the deposit function, and newAmount is the added balance amount.
Bob and Cooper deposit their contributions of 1 WAVES each into the dApp account.

We make a mistake and the transaction does not go through. Even though we ensured that we were making the transaction on behalf of Bob, we mistakenly entered the Bank account index, where there is no smart contract. It is important to note that for failed transaction attempts, the fee is not charged! Alice now has 2.972 WAVES left. Bob has 3 WAVES.
Bob sent 1 WAVES to the dApp Account.
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"deposit",args:[]}, payment: [{amount: 100000000, asset:null }]}))
Bob has 1.99 WAVES left. This means Bob paid a fee of 0.01 WAVES.

Alice had a balance of 2.972 WAVES, which increased to 3.972. There is also a transaction registered on Alice's account, but no fee was charged from the dApp Account (Alice).
After Cooper also topped up Alice's account, her balance became 4.972 WAVES.

You can find out how many WAVES belong to whom in the overall wallet by checking the Data tab in the block explorer.
Cooper changed his mind about leaving 1 WAVES in the joint wallet and decided to withdraw half of the funds. To do this, he must call the withdraw function.

However, we made a mistake again because the withdraw function has completely different parameters and a different signature. When designing smart contracts on RIDE4DAPPS, you should pay attention to this detail.

Cooper's balance became 2.48 WAVES. Therefore, 3 WAVES - 1 - 0.01, and then + 0.5 - 0.01. Thus, each call to deposit and withdraw costs 0.01 WAVES. As a result, the records in the dApps ownership table changed as follows.

Bob also decided to withdraw some money from the joint wallet, but he made a mistake and tried to withdraw 1.5 WAVES.

However, the smart contract had a check for such a situation.
Xena is a fraudster; she tried to withdraw 1 WAVES from the joint account.

She also failed.
In the next part, we will discuss more complex issues related to the imperfections of Alice's dApp Account.
Source: habr.com
