# Протокол токенсейла с вестингом ## Общий интерфейс контракта Протокол токенсейла с вестингом подразумевает единую точку входа для пользователя через контракт `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