PancakeSwap Worker

https://github.com/alpaca-finance/bsc-alpaca-contract/blob/main/contracts/6/protocol/workers/pcs/PancakeswapV2Worker02.sol

Table of content

Background

Once user want to open position / manage position at PancakeSwap farming, a vault contract will call a contract that deployed with this worker contract

PancakeSwap is an AMM DEX that allows traders to convert one asset to another asset without order book. Users can provide liquidity to the market by providing a pair of asset with 1:1 value. For example, if current price of BNB = 500 USDT, liquidity provider need to provide 1 BNB and 500 USDT to the liquidity pool so that other can exchange directly with the pool instead of another trader.

To provide incentive to liquidity provider, AMM DEX traditionally grant a third token as a reward to compensate the opportunity cost of trading. This is where the yield farming come in to play. Alpaca finance provide a platform that allow liquidity provider to provide a liquidity with margin. Meaning they can provide a liquidity more than they currently have.

In this implementation of worker at PancakeSwap, the responsibility of PancakeSwap worker is to manage the LP token on behalf of users. This also included the borrowed capital as well.

Abstract

Attributes

PancakeSwap Worker Attribute

NameTypePublicDescription
masterChefIPcancakeMasterChef
PancakeSwap Masterchef address
factoryIPancakeFactory
PancakeSwap Factory address
routerIPancakeRouter02
PancakeSwap Router address
lpTokenIPancakePair
PancakeSwap LP address
wNativeaddress
Address of wrap native token
baseTokenaddress
Address of base token
farmingTokenaddress
Address of farm token
cakeaddress
Address of CAKE token
operatoraddress
Vault address
piduint256
PancakeSwap Masterchef Pool ID
sharesmappinguint256
mapping of position's share amount
okStratsaddressboolmapping
List of whitelisted strategy contracts
totalShareuint256
Total of share that issued to positions
addStratIStrategy
Address of strategy contract that will do adding liquidity to underlying LP
liqStratIStrategy
Address of strategy contract that will do the remove liquidity from underlying LP
reinvestBountyBpsuint256
Basis point that will allocate portion of reward back to caller
maxReinvestBountyBpsuint256
Maximum that reinvest bounty basis point canbe
okReinveestorsmapping
List of whitelisted reinvestor address
feeuint256
Trading fee at PancakeSwap
feeDenomuint256
Denominator of the fee used
reinvestThresholduint256
A threshold that will not trigger reinvest operation
reinvestPathaddressarray
A path that used in reinvesting back to LP
treasuryAccountaddress
Address that will the contract will keep the platform revenue
treashuryBountyBpsuint256
Basis point that allocated for platform revenue
benificialVaultaddress
A Vault address that will benefit from reinvesting
benificialValutBountyBpsuint256
Basis point that allocated the reward back to the vault
buybackAmountuint256
Temporary state variable used to handle transferring base token to beneficial vault address

Modifier

onlyEOAorWhitelisted

/// @dev Require that the caller must be an EOA account to avoid flash loans.
  modifier onlyEOA() {
    require(msg.sender == tx.origin, "PancakeswapV2Worker02::onlyEOA:: not eoa");
    _;
  }

Logic

  1. the caller must be an external own account.
  1. Otherwise, revert transaction.

onlyOperator

/// @dev Require that the caller must be the operator.
  modifier onlyOperator() {
    require(msg.sender == operator, "PancakeswapV2Worker02::onlyOperator:: not operator");
    _;
  }

Logic

  1. the caller address must be the same as configured
  1. Otherwise, revert transaction.

onlyReinvestor

//// @dev Require that the caller must be ok reinvestor.
  modifier onlyReinvestor() {
    require(okReinvestors[msg.sender], "PancakeswapV2Worker02::onlyReinvestor:: not reinvestor");
    _;

Logic

  1. the caller address must be the same as configured
  1. Otherwise, revert transaction.

Functions

Functions

NameTypeDescriptionDocumented
initializeExternalInitialize the contract once deployed
shareToBalancePublicViewGet share amount from balance
balanceToSharePublicViewGet balance from share amount
reinvestExternalCompound reward back to position
_reinvestInternal
workExternalOperate on positions
getMktSellAmountPublicViewCheck market if a token was to be sold
healthExternalViewCheck market value of position
liquidateExternalLiquidate position
_rewardToBeneficialVaultInternal
_buybackInternal
actualBaseTokenBalanceInternalViewGet balance of base token that this contract is holding
_addShareInternal
_removeShareInternal
getPathExternalView
getReversePathExternalView
getRewardPathExternalView
getReinvestPathExternalView
setReinvestConfigExternalOwner
setMaxReinvestBountyBpsExternalOwner
setStrategyOkExternalOwner
setReinvestorOkExternalOwner
setRewardPathExternalOwner
setCriticalStrategiesExternalView
setTreasuryConfigExternalOwner
setBeneficialVaultConfigExternalOwner

initialize

Use case

function Params

NameTypeDescription
_operatoraddressContract address that bound to this contract. Normally will be a vault contract
_baseTokenaddressERC20 address of the token that will be considered as base token
_masterChefIPancakeMasterChefPancakeSwap's Master Chef contract that will be used during working
_routerIPancakeRouterPancakeSwap's Router contract that will be used during working
_piduint256Pool ID that associated with PancakeSwap's Master Chef that will accept the LP token and yield Cake token
_addStratIStrategya contract address that will be used for adding liquidity to PancakeSwap liquidity pool
_liqStratIStrategya contract address that will be used to break the LP token at PancakeSwap
_reinvestBountyBpsuint256Basis Point that used to calculate an incentive for reinvesting the position
_treasureyAccountaddressAddress that will keep the revenue from working related
_reinvestPathaddressarrayAn array of address that associated with swapping a token to reinvest in the LP position
_reinvestThresholduint256Threshold to triggered reinvestment if pending cake reward reached
Untitled

Logic

  1. Set corresponding state variable
  1. Check validity of configuration

shareToBalance

Use case

function Params

NameTypeDescription
shareuint256Amount of share to convert to value

Logic

  1. When there's no share, 1 share = 1 balance
  1. Get total balance from PancakeSwap MasterChef contract
  1. Calculate balance by total balance * ( share / total share in this contract )

balanceToShare

Use case

function Params

NameTypeDescription
balanceuint256Total amount to calculate to share amount

Logic

  1. When there's no share, 1 share = 1 balance
  1. Get total balance as a denominator from PancakeSwap MasterChef contract
  1. calculate share by total share * (balance / total balance)

reinvest

Use case

function Params

NameTypeDescription
Untitled

Logic

  1. Call _reinvest() internal function passing the caller address as a treasury account
  1. call _buyback() internal function

_reinvest

Use case

function Params

NameTypeDescription
_treasuryAccountaddressAddress that will get some cut out of the reward from LP position
_treasuryBountyBpsuint256Basis point that will deduct from the reward
_callerBalanceuint256amount to be exclude from sending to treasury account
_reinvestThresholduint256Threshold to skip if CAKE reward of the LP position is low

Logic

  1. Claim all the CAKE reward first
  1. Check CAKE balance in this contract
  1. If CAKE is below reinvest threshold, exit this function
  1. calculate bounty for calling this reinvest function by _treasuryBountyBps * total CAKE reward
  1. Cut some amount our of bounty to beneficial vault ( Vault's contract )
  1. Transfer remaining bounty reward to treasury account
  1. Convert all non-bounty reward to base token
  1. Transfer base token to configure strategy contract that will do the converting BaseToken to LP token
  1. Execute the strategy, expected the strategy will transfer the LP back
  1. Deposit all LP token to PancakeSwap's MasterChef contract

work

Use case

function Params

NameTypeDescription
iduint256Position ID to work on
useraddressThe original user that is interacting with the operator.
debtuint256The amount of user debt to help the strategy make decisions
databytescalldataThe encoded data, consisting of strategy address and calldata

Logic

  1. trigger _reinvest internal function if configured
  1. Get the share amount of this position and convert it back to LP token
  1. Execute a strategy contract that passed via data variable
  1. add the LP token back to PancakeSwap's MasterChef contract. If the action is to close the position this will eventually be skipped
  1. Return any remaining BaseToken back to the caller. Typically the vault contract.

getMktSellAmount

Use case

function Params

NameTypeDescription
aInuint256The amount of asset to market sell
rInuint256The amount of asset in reserve for input
rOutuint256The amount of asset in reserve for output

Logic

  1. If aIn = 0, return 0
  1. calculate using x*y = k formula
  1. return the calculation with trading fee in consideration

health

Use case

function Params

NameTypeDescription
iduint256Position ID to check it's health

Logic

  1. Calculate the LP of this position
  1. Get the pool's total supply of BaseToken and FarmingToken
  1. Calculate the token amounts if to convert the position's LP tokens to the underlying assets
  1. call getMktSellAmount function supplying farm token as an input
  1. return the sum of base token from step 3 and step 4

liquidate

Use case

function Params

NameTypeDescription
iduint256The position ID to perform liquidation

Logic

  1. Convert the position back to LP tokens
  1. Transfer the LP token to configured liquidation strategy contract
  1. Return all available BaseToken back to the caller, typically a vault contract

_rewardToBeneficialVault

Use case

function Params

NameTypeDescription
_piduint256The target Pool ID that user will withdraw staked token neglecting the Alpaca reward

Logic

  1. read base token from the vault of interest contract
  1. swap reward token to beneficialVaultToken
  1. if beneficialvault token not equal to baseToken regardless of a caller balance, can directly transfer to beneficial vault
    1. otherwise, need to keep it as a buybackAmount,

** since beneficial vault is the same as the calling vault, it will think of this reward as a `back` amount to pay debt/ sending back to a position owner

_buyback

Use case

Logic

  1. Transfer the token to beneficial vault contract

actualBaseTokenBalance

Use case

Logic

  1. Return token amount excluding the amount to buyback

_addShare

Use case

function Params

NameTypeDescription
iduint256Position ID to add share

Logic

  1. Get the total amount of LP hold by this contract
  1. If there's none, exit
  1. deposit all LP token to PancakeSwap's MasterChef contract
  1. Calculate the share of this position
  1. Update the total share value

_removeShare

Use case

function Params

NameTypeDescription
iduint256Position ID of interest

Logic

  1. Calculate the LP balance from the share of the position
  1. Withdraw amount of LP from step 1 from PancakeSwap MasterChef contract
  1. Subtract the position share from total share of this contract

getPath

Use case

Logic

  1. Return array of address where first element is the base token address and farm token as the second element

getReversedPath

Use case

Logic

  1. Return array of address where first element is the farm token address and base token as the second element

getRewardPath

Use case

Logic

  1. Return the reward path vairable

getReinvestPath

Use case

Logic

  1. If the configured path has more than one element, return the configured one
  1. If the base token is a wrap Native token, return an array of reward as a first element and wNative token as the second element
  1. If the base token is an ERC20 token, return an array of reward as a first element and wNative token as the second element, and base token as a last element

setReinvestConfig

Use case

function Params

NameTypeDescription
_reinvestBountyBpsuint256Basis point to cut from reward from farming that will go to reinvester
_reinvestThresholduint256Threshold that will skip the reinvest if not met
_reinvestPathaddressarrayPath used in converting CAKE reward to base token

Logic

  1. Set state variables according to the function input

setMaxReinvestBountyBps

Use case

function Params

NameTypeDescription
_maxReinvestBountyBpsuint256Maximum basis point that will cut from farming reward token

Logic

  1. Set the state variable from the function input
  1. Basis point can't exceed 3000 (30%)

setStrategyOk

Use case

function Params

NameTypeDescription
stratsaddressarrayList of addresses that implement strategy interface
isOkboolTrue if whitelist, false if to blacklist

Logic

  1. Loop through all address
  1. Set the flag to whitelist/blacklist according to isOk flag

setReinvestorOk

Use case

function Params

NameTypeDescription
reinvestorsaddressarrayList of addresses
isOkboolTrue if whitelist, false if to blacklist

Logic

  1. Loop through all address
  1. Set the flag to whitelist/blacklist according to isOk flag

setRewardPath

Use case

function Params

NameTypeDescription
_rewardPathaddressarrayList of token address

Logic

  1. Last element of the array must be the base token
  1. Set the state variable from the function input

setCriticalStrategies

Use case

function Params

NameTypeDescription
_addStratIStrategyStrategy address use for adding liquidity to underly DEX LP pair
_liqStratIStrategyStrategy address use for removing liquidity to underly DEX LP pair

Logic

  1. Set state variables according to the function input

setTreasuryConfig

Use case

function Params

NameTypeDescription
_treasuryAccountaddressThe treasury address to update
_treasuryBountyBpsuint256The treasury bounty to update

Logic

  1. Set state variables according to the function input

setBeneficialVaultConfig

Use case

function Params

NameTypeDescription
_beneficialVaultBountyBpsuint256The bounty basis point value to update
_beneficialVaultIVaultAddress of contract that implement vault contract
_rewardPathaddressarrayList of token address

Logic

  1. Set state variables according to the function input