# Протокол токенсейла с вестингом
## Общий интерфейс контракта
Протокол токенсейла с вестингом подразумевает единую точку входа для пользователя через контракт `Market`. Пользователь может купить через него токен на всех заявленных раундах и склеймить исходя из календаря вестинга, закрепленного за каждым раундом. Этот контракт используется как для клиентов, непосредственно купивших токены, либо импортированных через служебный итерфейс как покупателей, так и тн коммандных токенов, закрепляемых за коммандой в соответствии с токеномикой.
```solidity
interface Market {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
struct VestingSchedule {
bool initialized;
address beneficiary;
uint256 cliff;
uint256 start;
uint256 duration;
uint256 slicePeriodSeconds;
bool revocable;
uint256 amountTotal;
uint256 released;
bool revoked;
}
function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
function OPERATOR() external view returns (bytes32);
function buy(uint256 _market, uint256 _amount, address _benefeciary) external;
function calculateOrderPrice(uint256 _market, uint256 _amount) external view returns (uint256 _price);
function calculateOrderSize(uint256 _market, uint256 _amount)
external
view
returns (uint256 _tgeAmount, uint256 _vestingAmount);
function claim() external;
function claimForIndex(uint256 _index) external;
function currency() external view returns (address);
function currencyTreasury() external view returns (address);
function deployMarket(
uint256 _price,
uint256 _minOrderSize,
uint256 _maxOrderSize,
uint256 _tgeRatio,
uint256 _start,
uint256 _cliff,
uint256 _duration,
uint256 _slicePeriod,
bool _revocable,
bool _permisionLess
) external;
function getIndexCount() external view returns (uint256);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function getVestingScheduleForIndex(uint256 _index) external view returns (VestingSchedule memory);
function getVestingSchedules() external view returns (VestingSchedule[] memory);
function grantRole(bytes32 role, address account) external;
function hasRole(bytes32 role, address account) external view returns (bool);
function marketsCount() external view returns (uint256);
function migrateUser(uint256 _market, uint256 _amount, address _benefeciary) external;
function productTreasury() external view returns (address);
function renounceRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
```
## Интерфейс получения данных
структура **VestingSchedule** обеспечивает данные по покупкам конкретного пользователя, а структура **MarketInfo** обеспечивает данные по конкретному раунду рынка. Для удобства в контракт введены функции с префиксом calculate, обеспечивающие расчет необходимых данных, на основе этих структур.
> **инфа не доступная в контракте**: сколько токенов купил пользователь
```solidity=
// Для указанного индекса покупки
VestingSchedule userInfoForIndex = market.getVestingScheduleForIndex(ROUND_NUM, BENEFECIARY)
// Для всех покупок, в которых пользователь учавствовал
VestingSchedule[] userInfo = market.getVestingSchedules(BENEFECIARY)
// сколько токенов уже склеймлено.
uint256 totalClaimed = userInfoForRound.amountTotal;
// сколько доступно на данный момент
uint256 avaibleToClaim = market.avaibleToClaim(PURCHASE_INDEX, BENEFECIARY);
// курс обмена, или цена 1 токена в валюте, за которую он продается
uint256 productPriceForOneToken = market.calculateOrderPrice(ROUND_NUM, 1e18);
```
## Покупка токенов
При покупке токенов пользователем часть токенов сразу уходит на кошелек пользователя, часть блокируется в соответствии с календарем вестинга
```solidity=
// ROUND_NUM - номер раунда 0..N
// PRODUCT_AMOUNT_TO_BUY - необходимое к покупке число токенов
// BENEFECIARY - адресс распорядителя токенов
//1. Получаем необходимую для аллокации пользователем сумму стейблкоиина
uint256 usdAmount = market.calculateOrderPrice(ROUND_NUM, PRODUCT_AMOUNT_TO_BUY);
//2. Апрувим поллученую сумму в адресс контракта токенсейла
usdt.approve(address(market), usdAmount);
//3. Покупаем токены
market.buy(ROUND_NUM, PRODUCT_AMOUNT_TO_BUY, BENEFECIARY);
```
## Клейм токенов
В соответствии с календарем вестинга пользователю открывается доступ к сбору(клейму) токенов. Важно понимать, что пользователь может владеть обязательствами с разными каллендарями(например если он приобрел токены в разных раундах или является кошельком команды, чьи токены разблокируются на нескольких календарях). В связи с этим фактом сущевствует два варианта клейма токенов - непосредственно для конкретного раунда и для всех доступных пользователю раундов.
```solidity=
// Сбор для всех раундов - в случае большого количества раундов
// может уперется в out of gas
market.claim();
// Сбор для конкретного раунда
market.claimForIndex(ROUND_NUM);
```
## Адреса контрактов
### Ethereum goerli
Контракт продукта(SHARK) : [0x7b8d1d0ca2d679ca8ffd37491c90b066d4511c12](https://goerli.etherscan.io/address/0x7b8d1d0ca2d679ca8ffd37491c90b066d4511c12)
Контракт валюты(TUSD) : [0x37bee9daecb30cd44305ff76fcdd44e471244efa](https://goerli.etherscan.io/address/0x37bee9daecb30cd44305ff76fcdd44e471244efa)
**Контракт магазина(MARKET)** :
https://goerli.etherscan.io/address/0x71d3b4779Fe591147db2013359A7B1A568535812
Контракт казначейства(TREASURY) :
https://goerli.etherscan.io/address/0xb4774da332416c26078ed39d4e3d64fd4cb34e75
### Binance testnet
Контракт продукта(SHARK) : [0x4fbd6fbd58045113ba7adf02034e0fcaa3e85396](https://testnet.bscscan.com/address/0x4fbd6fbd58045113ba7adf02034e0fcaa3e85396)
Контракт валюты(TUSD) : [0xbbf54ed533d1df95c201d0afd859c1707f7857ab](https://testnet.bscscan.com/address/0xbbf54ed533d1df95c201d0afd859c1707f7857ab)
**Контракт магазина(MARKET)** :
https://testnet.bscscan.com/address/0xf6b3fc7b787e1a5bbd9dfe530a0f6b02fc709733
Контракт казначейства(TREASURY) : https://testnet.bscscan.com/address/0x0C52135199590FB481b95Ff3cF82B87c3a34D16A
## Настройки сети
https://chainlist.org/chain/5
## Настройки раундов(SHARK)
TGE = сколько токенов доступно на старте
Cliff = период начальной блокировки
Duration = общий период вестинга
Slice = длинна периода еденичного разлока
> `(Duration - Cliff ) / Slice = количество разлоков`
0-4 люди заходят через buy()
5-12 через migrateUser()
| Index | Description | Amount, pc | TGE, % | Cliff, weeks | Duration, weeks | Slice, weeks | Price, $ per token |
| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| 0 | Seed | 23.000.000 | 3 | 12 | 60 | 4 | 0.01 |
| 1 | Private | 33.800.000 | 5 | 12 | 60 | 4 | 0.012 |
| 2 | Strategic | 58.750.000 | 7 | 12 | 60 | 4 | 0.014 |
| 3 | Public | 24.450.000 | 40 | 0 | 24 | 4 | 0.020 |
| 4 | Whitelist | 10.000.000 | 25 | 0 | 32 | 4 | 0.017 |
| 5 | Liquidity | 55.000.000 | 27 | 0 | 32 | 4 | 0 |
| 6 | Giveaways | 1.400.000 | 33 | 0 | 8 | 4 | 0 |
| 7 | Rewards | 500.000 | 8.3 | 0 | 44 | 4 | 0 |
| 8 | Marketing | 100.000.000 | 5 | 0 | 44 | 4 | 0 |
| 9 | Advisors | 75.600.000 | 0 | 44 | 132 | 12 | 0 |
| 10 | Ecosystem & Partnership | 100.000.000 | 5 | 0 | 64 | 4 | 0 |
| 11 | Core Team | 100.000.000 | 0 | 48 | 144 | 4 | 0 |
| 12 | P2E In game liquidity | 417.500.000 | 0 | 16 | 144 | 4 | 0 |
## Настройка белого списка
В контракте market предусмотрен единый белый список, он задействуется в раундах с настройкой `permisionLess = false`.
TBA
## Фабрика
TBA
## DAO
TBA