---
# System prepended metadata

title: Farm update

---

# Farm update

## Locked LP tokens

Goal: The farm locks deposits for a certain amount of time. Delegators cannot withdraw in that period. When the user attempts to withdraw, the smart contract compares current timestamp with saved timestamp for one specific deposit.

### Displaying locked stake

The farm has a new parameter called `withdrawLockTime` that can be found in `storage.farm.withdrawLockTime`. Whenever a `delegator` deposits amount `A`, the `withdrawLockedUntilDate` property gets computed based on `time.now() + withdrawLockTime` for amount `A`. Each deposit gets its own entry in a `map` in the `delegators`.

```typescript
type delegator = address;
type depositId = nat;
type delegatorId = (delegator, depositId);
type delegatorRecord = {
    accumulatedRewardPerShareStart: nat,
    claimLockedUntilDate: timestamp,
    lpTokenBalance: nat,
    withdrawLockedUntilDate: timestamp
};
type delegators = big_map(delegatorId, delegatorRecord);

// example for delegatorId tuple
let delegatorId = (tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb, 19);
19 is the depositId, which is 
the blockLevel (=blockHeight) when the deposit was performed.
```

> A delegator can only deposit once every block. The smart contract handles the error if two deposits are attempted in the same block. Obviously, multiple delegators can deposit in the same block.

**Staked balances have therefore 2 implicit states: locked and unlocked. When a delegator attempts to withdraw, the smart contract compares the timestamp and either releases the balance or not.**

**Suggestion 1:** The UI shows whether the deposit is redeemable.

**Suggestion 2:** The UI shows the global withdrawLockTime setting of the farm.

### Withdrawing staked tokens

The `%withdraw` entrypoint previously accepted only the amount to be withdrawn: `withdrawParameter = nat`.

In the ~~prototype~~ final farm the parameter for withdraw is:

```
type withdrawDepositParameter = {
    depositId: nat,
    value: nat
};
type withdrawParameter = list(withdrawDepositParameter);
```

~~In the next update, the withdrawParameter will accept a list of depositIds. The delegator will be able to withdaw multiple deposits at once.~~
The delegator is able to withdraw multiple deposits at once, by providing a list of depositIds.
Eg. using the popular JS/TS SDK **Taquito**, calling the `%withdraw` entrypoint would look like the following:

```
const withdrawParameter = [
    { depositId: 257, value: 10 },
    { depositId: 300, value: 5 }
];
            
const withdrawOperation = await contractInstance.methods.withdraw(withdrawParameter).send();
```

**Suggestion 3:** The UI only shows redeemable deposits.

Mandatory: Delegator needs to specify `depositId` when withdrawing funds. The specified value to be withdrawn is related to the individual deposit. The value to be withdrawn cannot exceed the staked amount of the deposit.


## Withdraw fees

The farm has a `beneficiary` address that receives withdraw fees. Withdraw fees are set by an admin not as percentages, but as *basis points*. 

Added to storage: 
`storage.addresses.beneficiary`
`storage.farm.withdrawFeeBasisPoints`

> 500 basis points equal 5%

**Suggestion 4:** UI displays withraw fee as % to the delegator.

## Claim

Claiming of reward tokens is time restricted and saved for each deposit in `delegatorRecord.claimLockedUntilDate`. Similiarly to the above described `%withdraw` logic, the smart contract compares the timestamp when a delegator attempts to claim.
At time of deposit, the smart contract assigns the full lock duration of **withdrawLockTime** to `claimLockedUntilDate`. Therefore, claiming while LP tokens are locked, is not possible.
After the withdrawLockedUntilDate period is passed, claiming by the delegator is possible, as long it does not happen more frequently than it is defined in `storage.farm.claimLockTime`. 

An example of common variables:
LP tokens are locked for one month. Claiming is restricted to once a week.

After deposit, the delegator cannot withdraw or claim for one month. After one month, the user can withdraw or claim. If the user claims, claiming and withdraw are locked for one week.

**Suggestion 5:** UI displays when the deleagtor can claim or withdraw the next time.

```javascript=
const depositIdA = 344;
const depositIdB = 365;
const claimParameter = [depositIdA, depositIdB]
const operation = await contract.methods
                    .claim(claimParameter)
                    .send();
```





## Reading storage with a tuple as big map key in Taquito

```javascript=
getDelegatorRecord: async function(delegatorId): Promise<delegatorRecord> {
    const storage = await contract.storage();
  
    const delegatorId = {
      0: 'tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb',
      1: 344
    };
    const delegatorRecord = await storage.delegators.get(delgatorId);
  
    return delegatorRecord;
},
```