Techical Specification

Demeter Architecture

Farm Deployment steps (using arbiscan | console):

  1. Calculate fees by calling the calculateFees function on the farm deployer contract. farm_deployer.calculateFees(tokenA, tokenB)

    • This function takes two parameters tokenA and tokenB and both are of type address.

    • It returns four parameters (feeReceiver, feeToken, feeAmount, claimable) Here, feeReceiver and feeToken are of type address, feeAmount is of type uint256 and claimable is of type boolean which is true when a user creates a farm with either of the token being SPA or USDs. This function will revert if tokenA and tokenB are the same.

    • Privileged deployers are accounts that are marked as privileged by the owner of the deployer contract, the privileged deployers can create any farm without any fees and for other deployers, the fees can be discounted if either of the token is SPA or USDs.

  2. Approve the farm_deployer contract to spend the feeAmount on behalf of the farm_creator. feeToken.approve(farm_deployer, feeAmount, {‘from’: farm_creator})

    • User has to input the calculated fee from 1.and farm_deployer contract address. Approve USDs spend on the farm_deployer contract. This is required only for farms which do not have USDs or SPA as one of the pool tokens.

  3. Create farm using the the deployer contract (Deployer Contract)

 // tokenA - Address of tokenA
   // tokenB - Address of tokenB
   // feeTier - Fee tier for the Uniswap pool
   // tickLowerAllowed - Lower bound of the tick range for farm
   // tickUpperAllowed - Upper bound of the tick range for farm
   struct UniswapPoolData {
       address tokenA;
       address tokenB;
       uint24 feeTier;
       int24 tickLowerAllowed;
       int24 tickUpperAllowed;
   }
 
   // Defines the reward data for the constructor.
   // token - Address of the token
   // tknManager - Authority to update rewardToken related Params.
   struct RewardTokenData {
       address token;
       address tknManager;
   }
 
  
   struct FarmData {
       address farmAdmin;
       uint256 farmStartTime;
       uint256 cooldownPeriod;
       UniswapPoolData uniswapPoolData;
       RewardTokenData[] rewardData;
   }  
 
   /// @notice Creates a new farm
   /// @param _farmType Farm to deploy. (ex: UniswapFarmV1)
   /// @param _data Encoded farm deployment params.
   function createFarm(FarmData memory _data)
       external
       nonReentrant
       returns (address)

Contracts:

Demeter_Factory: (arb) 0xC4fb09E0CD212367642974F6bA81D8e23780A659 UniswapFarm_Deployer: (arb) 0xe9426fCF504D448CC2e39783f1D1111DC0d8E4E0

Payload Structure:

[
   "<farm_admin_addr>",
   farm_start_timestamp,  # Should be a unix timestamp (Tip: add a buffer of 1000s)
   cooldown_period_in_days,  # Tip: set cooldown as 0 for disabling lockup functionality in the farm.
   [
       "<uniswapPool_token_A_addr>",
       "<uniswapPool_token_B_addr>",
       fee_tier,   # Select appropriate fee_tier[10000, 3000, 500]
       lower_tick,
       upper_tick,
   ],
   [
       [
           "<rwd_token1_addr>",
           "<rwd_token1_manager_addr>"
       ],
       [
           "<rwd_token2_addr>",
           "<rwd_token2_manager_addr>"
       ]
   ]
]

Example Payload:

  1. NoLockup farm L2DAO-USDs

[
   "0x66aB6D9362d4F35596279692F0251Db635165871",      
   1664357905,
   0,
   [
       "0x2CaB3abfC1670D1a452dF502e216a66883cDf079",
       "0xD74f5255D557944cf7Dd0E45FF521520002D5748",
       3000,
       -48960,
       -6900
   ],
   [
       [
           "0x2CaB3abfC1670D1a452dF502e216a66883cDf079",
           "0x5b12d9846F8612E439730d18E1C12634753B1bF1"
       ]
   ]
]

2. Lockup farm L2DAO-USDs

[
   "0x66aB6D9362d4F35596279692F0251Db635165871",      
   1664357905,
   2,
   [
       "0x2CaB3abfC1670D1a452dF502e216a66883cDf079",
       "0xD74f5255D557944cf7Dd0E45FF521520002D5748",
       3000,
       -48960,
       -6900
   ],
   [
       [
           "0x2CaB3abfC1670D1a452dF502e216a66883cDf079",
           "0x5b12d9846F8612E439730d18E1C12634753B1bF1"
       ]
   ]
]

Interacting with UniswapFarmV1

Events

event Deposited(
       address indexed account,
       bool locked,
       uint256 tokenId,
       uint256 liquidity
   );
   event CooldownInitiated(
       address indexed account,
       uint256 tokenId,
       uint256 expiryDate
   );
   event DepositWithdrawn(
       address indexed account,
       uint256 tokenId,
       uint256 startTime,
       uint256 endTime,
       uint256 liquidity,
       uint256[] totalRewardsClaimed
   );
   event RewardsClaimed(
       address indexed account,
       uint8 fundId,
       uint256 tokenId,
       uint256 liquidity,
       uint256 fundLiquidity,
       uint256[] rewardAmount
   );
   event PoolUnsubscribed(
       address indexed account,
       uint8 fundId,
       uint256 depositId,
       uint256 startTime,
       uint256 endTime,
       uint256[] totalRewardsClaimed
   );
   event FarmStartTimeUpdated(uint256 newStartTime);
   event CooldownPeriodUpdated(
       uint256 oldCooldownPeriod,
       uint256 newCooldownPeriod
   );
   event RewardRateUpdated(
       address rwdToken,
       uint256[] oldRewardRate,
       uint256[] newRewardRate
   );
   event RewardAdded(address rwdToken, uint256 amount);
   event FarmClosed();
   event FundsRecovered(
       address indexed account,
       address rwdToken,
       uint256 amount
   );
   event TokenManagerUpdated(
       address rwdToken,
       address oldTokenManager,
       address newTokenManager
   );
   event RewardTokenAdded(address rwdToken, address rwdTokenManager);
   event FarmPaused(bool paused);

Farm Admin functions:

  1. UpdateCooldownPeriod

  2. updateFarmStartTime

  3. farmPauseSwitch

  4. closeFarm

// --------------------- Farm Admin Functions ---------------------
   /// --------------------- UpdateCooldownPeriod ---------------------
   /// @notice Update the cooldown period
   /// @param _newCooldownPeriod The new cooldown period (in seconds)
   function updateCooldownPeriod(uint256 _newCooldownPeriod)
       external
       onlyOwner
   /// --------------------- updateFarmStartTime ---------------------    
   /// @notice Update the farm start time.
   /// @dev Can be updated only before the farm start
   ///      New start time should be in future.
   /// @param _newStartTime The new farm start time.
   function updateFarmStartTime(uint256 _newStartTime) external onlyOwner
   
   /// --------------------- farmPauseSwitch ---------------------   
   /// @notice Pause / UnPause the deposit
   function farmPauseSwitch(bool _isPaused) external onlyOwner farmNotClosed
 
   /// --------------------- closeFarm ---------------------   
   /// @notice Recover rewardToken from the farm in case of EMERGENCY
   /// @dev Shuts down the farm completely
   function closeFarm() external onlyOwner nonReentrant

Token Manager functions:

  1. recoverRewardFunds

  2. setRewardRate

  3. updateTokenManager

// --------------------- Token Manager Functions ---------------------
   /// --------------------- recoverRewardFunds ---------------------
   /// @notice Get the remaining balance out of the  farm
   /// @param _rwdToken The reward token's address
   /// @param _amount The amount of the reward token to be withdrawn
   /// @dev Function recovers minOf(_amount, rewardsLeft)
   /// @dev In case of partial withdraw of funds, the reward rate has to be set manually again.
   function recoverRewardFunds(address _rwdToken, uint256 _amount)
       external
       isTokenManager(_rwdToken)
       nonReentrant
       
   /// --------------------- setRewardRate ---------------------    
   /// @notice Function to update reward params for a fund.
   /// @param _rwdToken The reward token's address
   /// @param _newRewardRates The new reward rate for the fund (includes the precision)
   function setRewardRate(address _rwdToken, uint256[] memory _newRewardRates)
       external
       isTokenManager(_rwdToken)

   
   /// --------------------- updateTokenManager ---------------------   
   /// @notice Transfer the tokenManagerRole to other user.
   /// @dev Only the existing tokenManager for a reward can call this function.
   /// @param _rwdToken The reward token's address.
   /// @param _newTknManager Address of the new token manager.
   function updateTokenManager(address _rwdToken, address _newTknManager)
       external
       isTokenManager(_rwdToken)

Public Functions:

  1. Deposit: This function is called when NFT is transferred to the Farm contract.

  2. initiateCooldown: Function called when a user wants to initiate cooldown for his/her locked deposit.

  3. withdraw:

  4. claimRewards

  5. addRewards: Function to add reward funds in the Farm.

  6. computeRewards: Function to compute accrued rewards for a deposit.

  7. getNumDeposits

  8. getDeposit

  9. getNumSubscriptions

  10. getSubscriptionInfo

  11. getRewardTokens

  12. getRewardRates

  13. getRewardFundInfo

  14. getRewardBalance

// --------------------- Public Functions ---------------------
   /// --------------------- Deposit ---------------------
   /// @notice Function is called when user transfers the NFT to the contract.
   /// @param _from The address of the owner.
   /// @param _tokenId nft Id generated by uniswap v3.
   /// @param _data The data should be the lockup flag (bool).
   function onERC721Received(
       address, // unused variable. not named
       address _from,
       uint256 _tokenId,
       bytes calldata _data
   ) external override notPaused returns (bytes4);

   
   /// --------------------- initiateCooldown ---------------------
    /// @notice Function to lock a staked deposit
   /// @param _depositId The id of the deposit to be locked
   /// @dev _depositId is corresponding to the user's deposit
   function initiateCooldown(uint256 _depositId)
       external
       notPaused
       nonReentrant

   /// --------------------- withdraw ---------------------
   /// @notice Function to withdraw a deposit from the farm.
   /// @param _depositId The id of the deposit to be withdrawn
   function withdraw(uint256 _depositId) external nonReentrant

   
   /// --------------------- claimRewards ---------------------
   /// @notice Claim rewards for the user.
   /// @param _account The user's address
   /// @param _depositId The id of the deposit
   /// @dev Anyone can call this function to claim rewards for the user
   function claimRewards(address _account, uint256 _depositId)
       external
       farmNotClosed
       nonReentrant;
 
   /// @notice Claim rewards for the user.
   /// @param _depositId The id of the deposit
   function claimRewards(uint256 _depositId)
       external
       farmNotClosed
       nonReentrant;

   
   /// --------------------- addRewards ---------------------
   /// @notice Add rewards to the farm.
   /// @param _rwdToken the reward token's address.
   /// @param _amount the amount of reward tokens to add.
   function addRewards(address _rwdToken, uint256 _amount)
       external
       nonReentrant;

   
   /// --------------------- computeRewards ---------------------
   /// @notice Function to compute the total accrued rewards for a deposit
   /// @param _account The user's address
   /// @param _depositId The id of the deposit
   /// @return rewards The total accrued rewards for the deposit (uint256[])
   function computeRewards(address _account, uint256 _depositId)
       external
       view
       returns (uint256[] memory rewards);

   
   /// --------------------- getNumDeposits ---------------------
   /// @notice get number of deposits for an account
   /// @param _account The user's address
   function getNumDeposits(address _account) external view returns (uint256)

   
   /// --------------------- getDeposit ---------------------
   /// @notice get deposit info for an account
   /// @notice _account The user's address
   /// @notice _depositId The id of the deposit
   function getDeposit(address _account, uint256 _depositId)
       external
       view
       returns (Deposit memory)

   
   /// --------------------- getNumSubscriptions ---------------------
   /// @notice get number of deposits for an account
   /// @param _tokenId The token's id
   function getNumSubscriptions(uint256 _tokenId)
       external
       view
       returns (uint256)

   
   /// --------------------- getSubscriptionInfo ---------------------
   /// @notice get subscription stats for a deposit.
   /// @param _tokenId The token's id
   /// @param _subscriptionId The subscription's id
   function getSubscriptionInfo(uint256 _tokenId, uint256 _subscriptionId)
       external
       view
       returns (Subscription memory)
 
    /// --------------------- getRewardTokens ---------------------

   /// @notice Get list of reward tokens.
  /// @return The list of reward tokens.
  function getRewardTokens() external view returns (address[] memory)


   /// --------------------- getRewardRates ---------------------
   /// @notice get reward rates for a rewardToken.
   /// @param _rwdToken The reward token's address
   /// @return The reward rates for the reward token (uint256[])
   function getRewardRates(address _rwdToken)
       external
       view
       returns (uint256[] memory)

   
   /// --------------------- getRewardFundInfo ---------------------
   /// @notice get farm reward fund info.
   /// @param _fundId The fund's id
   function getRewardFundInfo(uint8 _fundId)
       external
       view
       returns (RewardFund memory)

   
   /// --------------------- getRewardBalance ---------------------
   /// @notice Get the remaining reward balance for the farm.
   /// @param _rwdToken The reward token's address
   function getRewardBalance(address _rwdToken) public view returns (uint256)
   

Last updated