Intercoin / CommunityCoinContract

Contracts to let people stake various tokens and use the trust that was built up in Intercoin's factory code.
GNU Affero General Public License v3.0
12 stars 2 forks source link

StakingContract

StakingContract is not a single contract but it is a complex mechanism of several contracts that linked between itselfs. \ StakingContract allows to distributed tokens(tradedToken) by staking it for a period. Here and below we will call it ITR, like InTeRcoin token.\ So user should:

StakingContract represented with two pools CommunityStakingPool and CommunityStakingPoolERC20, that can not be used simultaneously in one ComminityCoin scope The list of basic features:

Contracts

As said before StakingContract is a several contracts:

Interactions

Here we will describe main user cases like: stake, unstake, redeem, remove liquidity, etc.

Preparing to correct work

if using usual CommunityStakingPool then:

Steps to deploy

StakingContract is a complex of several contracts that linked between itselfs. We developed pattern that any produced instances use the same code deployed before and interact with it through DELEGATE_CALL. So any instance should be produced only by factory.\ So deployed process contains from two steps:

  1. Deploy implementations\ communityCoin.sol\ communityStakingPoolFactory.sol\ communityStakingPool.sol\ communityStakingPoolErc20.sol\ poolStakesLib.sol\ All contracts have proxy-based upgradeability system. so no constructors can be used in upgradeable contracts.\ example in ./scripts/deploy-implementations.js
  2. Deploy factory deployed CommunityCoinFactory.sol with addresses of implementations deployed in the step before and Costmanager address that can be empty \ example in ./scripts/deploy.js

Steps to use

  1. Need to create CommunityCoin To produce CommunityCoin instance user should call produce with params:
name type description
reserveToken address address of reserve token. like a WETH, USDT,USDC, etc.
tradedToken address address of traded token. For example the intercoin ITR token
hook address address of contract implemented IHook interface and used to calculation bonus tokens amount
discountSensitivity uint256 value that manage amount tokens in redeem process. multiplied by FRACTION(10**5 by default)
communitySettings tuple tuple of community settings. see below

struct CommunitySettings

name type description
invitedByFraction uint256 fraction(multiplied by FRACTION) that will get inviter when invited person do unstake operation
addr address address of community contract
redeemRoleId uint8 users with this role can be able to redeem or redeem and remove liquidity
circulationRoleId uint8 users with this role can call addToCirculation
tariffRoleId uint8 users with this role can set tariffcall setComission

How to stake

There are several ways:

  1. buyAndStakeLiquidity (via ETH)
    User send network coins(ETH,BNB,MATIC,etc) directly(or with payable method) into the CommunityStakingPool. Contract do following:

    • swap coins will converts into WrappedCoins(WETH).
    • swap WETH into reserveToken.
    • then using Formula#1 converts part of reserve tokens to traded to make sure that adding to liquidity happens without remainder.

      if uniswap pair reserveToken:[WETH] does not exists then transactions will revert.

  2. buyAndStakeLiquidity (via paying token)
    User make ERC20::approve paying tokens into CommunityStakingPool contract and call buyAndStakeLiquidity.
    Contract do following:

    • swap paying tokens into reserveToken.
    • then using Formula#1 converts part of reserve tokens to traded to make sure that adding to liquidity happens without remainder.

      if uniswap pair reserveToken:[payingToken] does not exists then transactions will revert.

  3. buyAndStakeLiquidity (via reserve token)
    User make ERC20::approve reserve tokens into CommunityStakingPool contract and call buyAndStakeLiquidity.
    Contract do following:

    • using Formula#1 converts part of reserve tokens to traded to make sure that adding to liquidity happens without remainder.
  4. sellAndStakeLiquidity
    used in cases when user already have tradedToken but didn't get enough reserved tokens. So user make ERC20::approve traded tokens into CommunityStakingPool contract and call sellAndStakeLiquidity.

  5. stakeLiquidity
    used in cases when user have already LP tokens. Could be obtained after unstake/redeem or transfered by another user. So user make the same as before: make ERC20::approve LP tokens into CommunityStakingPool contract and call sellAndStakeLiquidity.

  6. addAndStakeLiquidity
    used in cases when user have traded and reserve tokens. So user make the same as before: make ERC20::approve both tokens into CommunityStakingPool contract and call addAndStakeLiquidity. Keep in mind that there are no calculation to add liquidity without remainder. If one of tokens fully consuming but other not, then all that left will refund to user back.

flowchart TB
WETH(convert coins to WETH)
reserveToken(convert to reserveToken)
doUniswap1(swap reserveToken to tradedToken partly)
doUniswap2(swap tradedToken to reserveToken partly)
PayingToken(PayingToken)
AddLiquidity(adding liquidity to Uniswap)
PoolObtainLP(Pool Obtained LP)
mintITRcAndReturnBackToUser(mint ITRc to user)
StakeLPDirectly( stake LP directly in a pool)
End[[end]]
subgraph Buy And Stake Logic
doUniswap1 --> AddLiquidity --> PoolObtainLP --> mintITRcAndReturnBackToUser
doUniswap2 --> AddLiquidity
StakeLPDirectly --> mintITRcAndReturnBackToUser
end

1[[1]] -.-> WETH --swap--> reserveToken --> doUniswap1 
2[[2]] -.-> PayingToken --swap--> reserveToken 
3[[3]] -.-> reserveToken 
4[[4]] -.-> doUniswap2
5[[5]] -.-> AddLiquidity 
6[[6]] -.-> StakeLPDirectly
mintITRcAndReturnBackToUser --> End

How to unstake

Requirements:

So sender should approve tokens to CommunityCoin and call one of such methods:

[not completed]

How to redeem

Requirements:

So sender should approve tokens to CommunityCoin and call one of such methods:

[not completed]

CommunityContract

using external Community Contract as a contraсt that checking users rights. Settings of Community Contract have pointed in CommunitySettings when producing CommunityCoin. (see "Step to use" section)

Bonuses

General information about bonuses. how, where, when.
There are several bonuses can be happens in system:

Taxes

There are couple of taxes applied in system: tax description when applied
discountSensitivity see Formula#2. setup through produced CommunityCoin every transfer
inflation tax see Formula#3. autocalculated and depend of inflation tokens every transfer
Tariffs var unstakeTariff and redeemTariff can be set by owner unstake / redeem
taxHook if external taxHook contract are present then in any transfer it can adjust transferred amount up or down. But not more then MAX_BOOST or not less then MAX_TAX fractions respectively. in every transfer
lpFraction reducing LP tokens by lpFraction tax in pool(not erc20pool) unstake/redeem
Limit for taxes (multiple by fraction = 100000) name value description
MAX_UNSTAKE_TARIFF 10000 10%
MAX_REDEEM_TARIFF 10000 10%
MAX_TAX 10000 10%
MAX_BOOST 10000 10%

[in progress]

Formulas

Formula#1.

How much tokens need to swap from one reserve to get another and fully added to liquidity without remainder

Where:
r1 - reserve at uniswap(reserve side 1)
r2 - incoming amount of reserve(side 1) token
r3 - tokens amount from reserve side1 that need to use swapExactTokensForTokens

Formula#2.

How tokens calculated with circulation tokens present


Where:
totalReserves - tokens over all pools but without bonuses and inflation tokens
totalSupply - tokens over all pools

Formula#3.

ratio with discount sensitivity