# Smart Contracts

eckoDAO is a bespoke system comprised of a pair of smart contracts that interact with each other to accomplish different tasks related to governance. These are referred to as \
\&#xNAN;*'<mark style="color:yellow;">The Librarian</mark>'* and *<mark style="color:yellow;">'The Lexicon'.</mark>*&#x20;

## eckoDAO (<mark style="color:yellow;">The Librarian</mark> :older\_woman:)

The primary smart contract that handles Proposals is called the Librarian. This contract is designed to take care of proposals creation and management as well as keep track of votes for each specific proposal and account. The main features of the DAO contract are the following:

* Create proposal and insert into `proposals-table`
* Vote proposal by a specific account and insert into `votes-table`
* Give information about proposals and actions taken by an account

### Governance

The contract is governed by a keyset, "kaddex-ns-admin"

### Operations

The contract operations are allowed to a keyset, "kaddex-ns-ops"

### Tables

The contract contains 2 tables with following schema:

* **proposals-table**: `id` `title` `description` `account` `tot-approved` `tot-refused` `start-date` `end-date` `creation-date`
* **votes-table**: `proposal-id` `account` `vp` `action`

### Functions

#### create-proposal

* Creates proposal with the parameters: `title` `description` `owner-account` `start-date` `end-date`
* Inserts the proposal into `proposals-table`

```
(create-proposal "New proposal" "this is a proposal" "k:govaddress" (time "2022-03-10T23:59:00Z") (time "2022-03-20T23:59:00Z"))
```

#### vote-proposal-helper

* Takes three parameters: `proposal-id` `account` `action`
* Inserts into `votes-table` the action (approved or refused) taken from an account on a specific proposal

```
(vote-proposal-helper "proposal-id" "k:bobaddress" "approved")
```

#### approved-vote

* Takes `proposal-id` and `account` as parameters
* calls **vote-proposal-helper** to vote for a proposal as approved

```
(approved-vote "proposal-id" "k:bobaddress")
```

#### refused-vote

* Takes `proposal-id` and `account` as parameters
* calls **vote-proposal-helper** to vote for a proposal as refused

```
(refused-vote "proposal-id" "k:bobaddress")
```

#### get-account-data

* This function needs an `account` as a required argument and retuns the voting-power, multiplier and staked-amount of that specific account
* These info are received from the **aggregator contract**

```
(get-account-data "k:bobaddress")
```

#### read-proposal

* Get proposal info giving a specific `proposal-id` as argument

```
(read-proposal "proposal-id")
```

#### read-all-proposals

* Get all proposals info

```
(read-all-proposals)
```

#### check-account-voted

* This function takes an `account` and a `proposal-id` as arguments.
* Checks if an account has already voted a specific proposal.

```
(check-account-voted "k:bobaddress" "proposal-id")
```

#### read-account-votes

* Takes `account` as paramenter
* Get vote info for each proposal that `account` has voted in the `votes-table`

```
(read-account-votes "k:bobaddress")
```

#### read-account-vote-proposal

* Takes `account` and `proposal-id` as paramenter
* Get vote info of `account` on specific `proposal`

```
(read-account-votes "prposal-id" "k:bobaddress")
```

## The eckoDEX Aggregator (<mark style="color:yellow;">The Lexicon</mark> :scroll:)

This contract is designed to manage each account's Voting Power. Voting Power (VP) is essential for a user that wants to vote a proposal in the DAO. Every time an account vote a proposal, the DAO contract make a call to the Aggregator contract in order to evaluate the VP of that specific account.

### Governance

The contract is governed by a keyset, "kaddex-ns-admin"

### Operations

The contract operations are allowed to a keyset, "kaddex-ns-ops"

### Tables

The contract contains 2 tables with following schema:

* **staking-aggregator-table**: `account` `start-time` `staked-amount` `shift`
* **privilege-table**: `guards` `action`

### Functions

#### grant-privilege

* Takes a guard and an action as arguments.
* This function grants a guard privilege to perform a specific action. If a guard does not have permission, the action won't be executed.

```
(grant-privilege (read-keyset 'guardaddress ) "aggregate-stake")
```

#### insert-lockup-batch

* Takes a list of objects as argument.
* Vaulting data are inserted into `staking-aggregator-table` through the use of this function. For a single user, the amount of kdx-locked coming from the vaulting program will be added up with the kdx-amount staked in order to create the `Position` of that specific user.

```
(insert-lockup-batch [{"account":"k:bobaddress", "amount": 100.0}])
```

#### aggregate-stake

* Takes two parameters: `requesting-account` `amount`
* It's called every time a new action of staking is made by an account. It is up to this function to verify whether an account is entering staking for the first time or not, if not, it checks if there is some amount already staked. Based on this information one of the three functions **create-new-stake-row** / **update-account-entering-staking-again** / **update-old-stake-row** is called to insert staking info into the `staking-aggregator-table` .

```
(aggregate-stake "k:bobaddress" 100.0)
```

#### aggregate-unstake

* Takes two parameters: `requesting-account` `unstaked-amount`
* It's called every time a new action of unstaking is made by an account. It is up to this function to call the **update-when-unstaking** function in order to update the `staking-aggregator-table` with the unstaking info.

```
(aggregate-unstake "k:bobaddress" 100.0)
```

#### get-voting-power

* Receiving an account as argument, it returns the VP of that specific account.

```
(get-voting-power "k:bobaddress")
```

#### get-account-data

* Takes an account as parameter.
* This function returns an object containing info about the inserted account. In particular the outcome will be the Position, VP and Multiplier of the account.

```
(get-account-data "k:bobaddress")
```

#### read-all-staking

* Get all staking info

```
(read-all-staking)
```

## Voting Power ( VP ) Calculation

**The formula to calculate the VP is:**

$$
V = \sqrt{P \cdot M}
$$

where:

* **P**: is the account Position, KDX amount ( `staked-amount` + kdx-locked in Vaulting program)
* **M**: is the multiplier

The Voting Power Multiplier is a time-dependent function of your KDX staking amount. After the initial action of staking, in 60 days the Multiplier value goes up to 1 and can reach 2.5 over the course of 4 years. Every time a new action of staking is made, the Multiplier is recalculated based on the prervious amount staked and the new inserted amount. In order to performe this kind of calculation the `shift` value is used and stored. The shift value shifts the curve along the x axis to accommodate adding stakes at different times.

**Multiplier formula:**

```
M = s • ([ X - shift ] ^ z) + c
```

where:

* **X**: is the time passed since the staking started
* **s, z, c**: are constants used to model the multiplier-curve efficiently

#### Example:

```
 user1:
  - entering staking at T(0) with 100 KDX
  - after 60 days --> Multiplier = 1 and VP = 10 = Math.sqrt( 100 • 1 ) 
```

```
 user2:
  - entering staking at T(0) with 10 KDX
  - adding 90 KDX after 30 days
  - after 60 days --> Multiplier = 0.8158 and VP = 9.03 = Math.sqrt( 100 • 0.8158 ) 
```

As it is possible to notice, after a period of 60 days, user1 will have acquired more VP compared to user2. This is due to the fact that user2 have made a new action of staking during the 60 days period, this action leads to an adjustment of the `shift` value, therefore to a lower Multiplier and VP.
