# Writing and editing program logic

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIcfn7EKGAWtylj%2Fsmartx-codewindow.jpg?generation=1575624774276345\&alt=media)

Once **SmartX** is up and running, this what the main window looks like.

Since we have selected the **OEP-4** template, the code is already present in the editor area. You may choose to edit this code as you please based on the logic that you're trying to implement. But for the sake of simplicity and staying within the scope of this tutorial we will use the code as it is to ensure uniformity.

It is worth taking some time to take a look at the code and the overall structure of the program that we'll be working with.

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIe86Or8PpmPbxb%2Fsmartx-vardec.jpg?generation=1575624774026968\&alt=media)

The variables declared in this section of the code define the protocol itself and the specifics that will govern its functionality.

Variables such as `NAME` and `SYMBOL` serve as identifiers for the token.

`FACTOR` is the base 10 value that dictates the precision of amounts that can be transferred. For example, if the value is set to 100, transfer amounts with values up to two levels of precision are supported by the system. `DECIMALS` stores the multiplier value for access convenience.

`OWNER` stores the **Base58** address of the entity or account that holds the authority over the totality of tokens and can choose to distribute them as and when needed.

`TOTAL_AMOUNT` stores the total number of tokens that exist. Always a fixed number.

`BALANCE_PREFIX` is an access modifier that is used with account addresses for authentication purposes. `APPROVE_PREFIX` serves the same purpose, but for the approve operation wherein the owner can authenticate another account to use tokens.

`SUPPLY_KEY` correlates directly to the total amount of tokens and is used for any operations that may be carried with the total tokens figure, since the value isn't directly accessible.

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIgUIWgos-SHO_i%2Fsmartx-getcontext.jpg?generation=1575624774256167\&alt=media)

This line immediately stands out in the upper section of the code.

`GetContext()` is a function that acts as the bridge between the smart contract and the blockchain. It is used when fetching and transmitting data from and to the chain by calling the `GET` and `PUT` functions which are a part of the **Storage API**.

We will go through the relevant APIs as we come across the respective functions, and the full set of available APIs in a later section of the tutorial.

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIiqZ61iZznZy3l%2Fsmartx-importedmethods.jpg?generation=1575624774131039\&alt=media)

Since we're working with the online SmartX IDE, all the APIs and functions are available for use and can be accessed directly by importing at the start of the program. Here, the functions that we import are `GetContext()`, `Get()`, `Put()`, and `Delete()` from the **Storage API**, `Notify()`, `CheckWitness()` and `Base58ToAddress()` from the **Runtime API** and the built-in function `concat()`.

{% hint style="info" %}
In later versions, built-in functions don't need to be imported and can be called directly.
{% endhint %}

Let us take a look at the `main()` function.

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIkXckDaetHHEP8%2Fsmartx-mainfunc.jpg?generation=1575624774114478\&alt=media)

The Main() function takes two arguments, `operation` and `args`. The *operation* argument is based on the operation to be performed and dictates the function to the executed. The `args` argument helps passing the important information that a function needs to carry out further execution, for example account addresses or input data.

Here, clearly there are 11 different functions that can be called depending upon the argument that is passed in Main(). SmartX passes these arguments using the "Options" pane on the bottom right.

* **init()** **:** The init() function serves as the starting point of the program logic. It initializes the definition variables declared at the top based on the values provided. Thus, this is the first function that needs to be executed post deployment.
* **name() :** This function returns the name assigned to the token, "My Token" in this case.
* **symbol() :** This function returns the symbol assigned to the token, "MYT" in this case.
* **decimals() :** Returns the number of decimal places that designate the precision of valid token values, 8 in this case.
* **totalSupply() :** Returns the total number of tokens assigned while initializing. Denotes the fixed number of tokens allocated for circulation. (Uses `SUPPLY_KEY` to fetch the value from the chain, stored earlier during initialization)
* **balanceOf(acct) :** Fetches the corresponding token balance of the account that identifies with the Base58 address passed as argument to the function.
* **transfer(from\_acc, to\_acc, amount) :** Transfers the equivalent token value passed as the amount argument to the `to_acc` address from the `from_acc` address.
* **transferMulti(args) :** The parameter here is an array that contains the same information, i.e., the sender's address, receiver's address, and the amount to be sent, in that sequence at the respective indices. It can be iterated for multiples transactions by passing the respective account addresses and the corresponding amount.
* **transferFrom(spender, from\_acc, to\_acc, amount) :** The spender here takes a certain amount of tokens from the `from_acc` address, and transfers them to the `to_acc` address.
* **approve(owner, spender, amount) :** The owner authorizes the spender to use a certain amount of tokens from their own account. Both the owner and spender arguments here are Base58 addresses and the amount specifies the amount that the spender is authorized to spend.
* **allowance(owner, spender) :** This function can be used to the amount that the owner account has authorized spender to use. Both arguments in this case are **Base58** addresses.

The functions above can be classified into two different types- access functions and utilities. Let us consider the flow of control as these functions are called.

**Access functions** are primarily used to fetch data post contract deployment. Functions such as `name()`, `symbol()`, `totalSupply()` and `balanceOf(acc)` allow us to achieve this by using `get()` function from the **Storage API** which fetches relevant data from the chain. Let us look at how it is implemented in program logic.

**name() function definition**

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVImX3x8yOVttqQV%2Fsmartx-namedefinition.jpg?generation=1575624774035347\&alt=media)

This is how a simple access function can be defined. The `name()` function takes no arguments. Even though functions such as `name()`, `symbol()` and `decimals()` do not explicitly call the `get()` function, after the contract is deployed, all the data is fetched from the chain.

**balanceOf(acc) function definition**

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIogzOsWw2iEcI1%2Fsmartx-balanceofdefinition.jpg?generation=1575624774125443\&alt=media)

The `balanceOf()` function takes one argument, a `Base58` address which denotes an account. There is a validity check in place that verifies the length of the address and raises an exception if the address is invalid. If the address is valid the `get()` function is called with two arguments, the account address prefixed with `BALANCE_PREFIX`, and the context.

The context allows for data reference on the chain to fetch the account balance value, while the prefixed account address ensures authenticated access. Next, `get()` returns this data to `Main()` where it is output to the log window using the `notify()` function. The `totalSupply()` function works in a similar fashion.

{% hint style="info" %}
The balance and approve prefixes are hexadecimal values in `ASCII` format and can be modified to support your own program logic.
{% endhint %}

Let us look at the utilities in the sample code.

Utilities are methods that have richer functionality and help modifying the on-chain data, which is the basis for transactions and tasks that may be carried out. The **OEP-4** token logic that the code template is using illustrates various use cases and scenarios in the form of functionality. This is to exhibit just how versatile smart contracts are in nature and the different kinds of business logic that they can be used to generate.

**transfer(from\_acc, to\_acc, amount)**

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIqQ_z1mdb1t3Sq%2Fsmartx-transferdefinition.jpg?generation=1575624774195302\&alt=media)

The `transfer()` function implements the most fundamental transaction feature, transferring tokens from one account to another. It takes three arguments, the sender's address, the receiver's address, and the amount to be transferred.

The function carries out verification by a simple length check, but a more complex logic can be developed based on individual needs.

Next, the `BALANCE_PREFIX` is concatenated to the sender's account address, and balance is retrieved by making a `get()` call using this address. A quick comparison is made in the next step where the sender account's balance is compared with the amount to be transferred. All three scenarios have been defined clearly.

If the balance is less than the transfer amount, the transaction fails, and the control returns to `Main()` directly.

If the amount equates to the balance amount exactly, the balance of sender account is set to 0 by calling the `delete()` method using the sender's prefixed address. This is practically equivalent to using the `put()` method to manually assign the value 0 to sender's account but using `put()` method in this case might give rise to security vulnerabilities.

If the balance is higher than the transfer amount, the amount is deducted from the balance by making a `put()` call and updating the sender accounts balance with the deducted value.

Next, the receiver's address is prefixed with the `BALANCE_PREFIX`, and the prefixed address is used to add the transfer amount to the receiver's account.

Finally, this transaction event is sent to the chain using the `RegisterAction()` method for recording in a ledger.

The `transfer()` function implements the most fundamental transaction feature, transferring tokens from one account to another. It takes three arguments, the sender's address, the receiver's address, and the amount to be transferred.

The function carries out verification by a simple length check, but a more complex logic can be developed based on individual needs.

Next, the `BALANCE_PREFIX` is concatenated to the sender's account address, and balance is retrieved by making a `get()` call using this address. A quick comparison is made in the next step where the sender account's balance is compared with the amount to be transferred. All three scenarios have been defined clearly.

If the balance is less than the transfer amount, the transaction fails, and the control returns to `Main()` directly.

If the amount equates to the balance amount exactly, the balance of sender account is set to **0** by calling the `delete()` method using the sender's prefixed address. This is practically equivalent to using the `put()` method to manually assign the value 0 to sender's account but using `put()` method in this case might give rise to security vulnerabilities.

If the balance is higher than the transfer amount, the amount is deducted from the balance by making a `put()` call and updating the sender accounts balance with the deducted value.

Next, the receiver's address is prefixed with the `BALANCE_PREFIX`, and the prefixed address is used to add the transfer amount to the receiver's account.

Finally, this transaction event is sent to the chain using the `RegisterAction()` method for recording in a ledger.

**TransferEvent** is the alias that `RegisterAction()` uses here. `RegisterAction()` is a method of the **Action API** and it takes four arguments that are transferred to the chain in order to record transaction details. The transaction hash and certain other details are output in the logs section.

The **transferMulti()** is works in a similar manner. The logic remains the same, since basically all that `transferMulti()` does is call `transfer()`, but it allows for multiple transfers to take place simultaneously. It takes one argument which is a nested array. is the alias that `RegisterAction()` uses here. `RegisterAction()` is a method of the **Action API** and it takes four arguments that are transferred to the chain in order to record transaction details. The transaction hash and certain other details are output in the logs section.

The **transferMulti()** is works in a similar manner. The logic remains the same, since basically all that `transferMulti()` does is call `transfer()`, but it allows for multiple transfers to take place simultaneously. It takes one argument which is a nested array.

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIsOh7kHt2dvZbS%2Fsmartx-transfermultidefinition.jpg?generation=1575624774267246\&alt=media)

The sub-array elements are processed in sets of three such that the first and second elements still represent the sender's and receiver's addresses, and the third element represents the transfer amount. The sub arrays are iterated till there are no more elements left in the `args[]` array.

Exception is thrown in case the sub-array does not contain exactly three elements, or the previous transaction fails for some reason, and the control comes out of the loop and goes back to `Main()`

**approve(owner, spender, amount)**

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIuoA7avBSypIpR%2Fsmartx-approvedefinition.jpg?generation=1575624774171125\&alt=media)

The approve function implements another complex logic wherein an account, namely the `spender` is given the permission to utilize a certain amount in tokens from another account, namely the `owner`.

The function first carries out address validation in terms of length, and user authentication for the `owner` who is about to perform the approval.

Next, the amount selected for approval is compared to the available balance in the `owner` account.

If the account does not have enough balance the process is terminated, and the control returns to `Main()`.

If the account has enough balance, a key is generated by concatenating the `owner` address prefixed with `APPROVAL_PREFIX` and the `spender` address. It is then added to the ledger using the `put()` method by passing the context, the above generated key, and the approval amount.

The transaction event is then recorded using the `ApprovalEvent()` method, and the result containing the transaction hash returned by the **NeoVM** engine is displayed in the logs section.

## **transferFrom(spender, from\_acc, to\_acc, amount)**

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIwPOdCUIAbbwZS%2Fsmartx-transferfromdefinition.jpg?generation=1575624774287270\&alt=media)

The `transferFrom()` function implements a more complex logic and carries out a task that may prove to be useful for certain applications.

This function allows a third party, namely the spender, to utilize a certain amount in tokens that are provided from an account that does not designate to their own credentials, basically implementing the same logic as that of the `approve()` function. It takes four arguments, which are three **Byte58** addresses and one transfer amount.

First, the function carries out the conventional address validation. Then it verifies whether the spender has the authorization to carry out this transaction using the `CheckWitness()` function which is a part of the **Runtime API**.

Next, the balance of the `from` account is fetched and cross-checked with the transaction amount to ensure the account has enough balance. The process to fetch the balance remains the same.

The spender's address is then prefixed with the `APPROVE_PREFIX` and the approved amount from is fetched using the prefixed address.

The transaction comes next. If the transaction amount is higher than the approved amount the transaction is aborted, and control returns to `Main()`.

If the amount is exactly equal to the approved amount, the transaction amount is deducted from the `from` accounts balance.

If the approved amount exceeds the transaction amount, the difference is calculated and stored in the ledger for future reference, and the transaction amount is deducted from the `from` account.

The transaction amount is then transferred to the `to` account using the `put()` function. The event is then recorded and the result with the transaction hash is displayed in the logs section of the **IDE**.

Another function that implements a similar logic has be defined as **allowance(owner, spender)** which facilitates querying the amount of allowance that has been allocated to the `spender` account from the `owner` account.

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LvPYTBbYX4L3mHx0vBh%2F-LvPYVIyTVwH7skr6lFq%2Fsmartx-allowancedefinition.jpg?generation=1575624774164391\&alt=media)

Practically speaking, this function cam be classified as an access function too in the sense that it returns the allowance value. But it also performs a `get()` query to fetch this result from the chain.

A key generated by concatenating the prefixed owner address and the spender address is passed to the `get()` method along with the context to fetch the required allowance value, which is then returned to `Main()`. The value can then be displayed or used to perform other tasks.
