Skip to content

Commit

Permalink
fix: [L-03] Add missing documentation (#53)
Browse files Browse the repository at this point in the history
Add documentation for:
 - UserDeposit and StakingToken structs.
 - getAverageDepositTimePostDeposit()
 - getCurrentTime()
 - _stake()

Update documentation for:
 - Overall contract.
 - recoverToken()
 - stake()
 - stakeFor()
 - unstake()
 - withdrawReward()
 - exit()
 - _updateReward()
  • Loading branch information
pxrl committed Jan 4, 2023
1 parent d38d4cd commit 95ae7ff
Showing 1 changed file with 61 additions and 14 deletions.
75 changes: 61 additions & 14 deletions contracts/AcceleratingDistributor.sol
Expand Up @@ -8,27 +8,47 @@ import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Multicall.sol";

/**
* @notice Across token distribution contract. Contract is inspired by Synthetix staking contract and Ampleforth geyser.
* Stakers start by earning their pro-rata share of a baseEmissionRate per second which increases based on how long
* they have staked in the contract, up to a max emission rate of baseEmissionRate * maxMultiplier. Multiple LP tokens
* can be staked in this contract enabling depositors to batch stake and claim via multicall. Note that this contract is
* only compatible with standard ERC20 tokens, and not tokens that charge fees on transfers, dynamically change
* balance, or have double entry-points. It's up to the contract owner to ensure they only add supported tokens.
* @title Across Accelerating Distributor (Staking) Contract
* @notice Stakers start by earning their pro-rata share of a baseEmissionRate per second. The baseEmissionRate is
* amplified by a reward multiplier, which increases up to a configurable maxMultiplier, based on the time and amounts
* of previous deposits into the contract. Multiple LP tokens can be staked in this contract enabling depositors to
* batch stake and claim via multicall.
* @notice This contract is only compatible with standard ERC20 tokens, and not tokens that charge fees on transfers,
* dynamically change balance, or have double entry-points. It's the responsibility of the contract owner to ensure
* they only add supported tokens, and that staking token configurations are applied correctly.
* @dev This contract is inspired by the Synthetix staking contract, and the Ampleforth geyser.
*/

contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
using SafeERC20 for IERC20;

IERC20 public immutable rewardToken;

// Each User deposit is tracked with the information below.
/**
* @notice Tracks the staking balance and associated rewards of an address for a single staking token.
* @dev Stored user rewards are updated each time a Staker Function is called with the user's address.
* @param cumulativeBalance User's current total staking balance in the contract for this address.
* @param averageDepositTime Averaged timestamp of user's entry into the pool, weighted by the size of each deposit.
* @param rewardsAccumulatedPerToken User's cumulative per-unit share of staking rewards as at the last update.
* @param rewardsOutstanding Staking reward tokens available to be claimed since last update.
*/
struct UserDeposit {
uint256 cumulativeBalance;
uint256 averageDepositTime;
uint256 rewardsAccumulatedPerToken;
uint256 rewardsOutstanding;
}

/**
* @notice Tracks the global configuration and state of each staking token.
* @dev Global stakingToken state is updated each time a Staker Function is called.
* @param baseEmissionRate Base staking token emission rate, before applying any user multiplier.
* @param maxMultiplier Maximum achievable multiplier to be applied to baseEmissionRate.
* @param secondsToMaxMulitplier Number of seconds after user's averageDepositTime before reaching maxMultiplier.
* @param cumulativeStaked Total amount of deposit token staked in contract.
* @param rewardPerTokenStored Global cumulative per-unit share of staking rewards as at the last update.
* @param lastUpdateTime Timestamp of last configuration change or rewards calculation.
*/
struct StakingToken {
bool enabled;
uint256 baseEmissionRate;
Expand All @@ -52,10 +72,19 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
_;
}

/**
* @notice AcceleratingDistributor constructor.
* @dev The reward token is immutable once the contact has been deployed.
* @param _rewardToken Contract address of token to be used for staking rewards.
*/
constructor(address _rewardToken) {
rewardToken = IERC20(_rewardToken);
}

/**
* @notice Returns the current block timestamp.
* @return uint256 Current block timestamp.
*/
function getCurrentTime() public view virtual returns (uint256) {
return block.timestamp; // solhint-disable-line not-rely-on-time
}
Expand Down Expand Up @@ -104,7 +133,7 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
**************************************/

/**
* @notice Enable a token for staking.
* @notice Enable a token for staking. Emits a TokenConfiguredForStaking event on success.
* @dev The owner should ensure that the token enabled is a standard ERC20 token to ensure correct functionality.
* @param stakedToken The address of the token that can be staked.
* @param enabled Whether the token is enabled for staking.
Expand Down Expand Up @@ -157,6 +186,7 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
* staking rewards or recover excess LP tokens that were inadvertently dropped onto the contract. Importantly, the
* contract will only let the owner recover staked excess tokens above what the contract thinks it should have. i.e
* the owner cant use this method to steal staked tokens, only recover excess ones mistakenly sent to the contract.
* Emits a RecoverToken event on success.
* @param token The address of the token to skim.
*/
function recoverToken(address token) external onlyOwner {
Expand All @@ -176,7 +206,8 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
**************************************/
/**
* @notice Stake tokens for rewards.
* @notice Stake tokens for rewards. Callable by any user. Fails when the specified amount is 0, or when the caller
* can not successfully transfer the specified amount. Emits a Stake event on success.
* @dev The caller of this function must approve this contract to spend amount of stakedToken.
* @param stakedToken The address of the token to stake.
* @param amount The amount of the token to stake.
Expand All @@ -186,7 +217,8 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
}
/**
* @notice Stake tokens for rewards on behalf of `beneficiary`.
* @notice Stake tokens on behalf of `beneficiary`. Callable by any user. Fails when the specified amount is 0, or
* when the caller can not successfully transfer the specified amount. Emits a Stake event on success.
* @dev The caller of this function must approve this contract to spend amount of stakedToken.
* @dev The caller of this function is effectively donating their tokens to the beneficiary. The beneficiary
* can then unstake or claim rewards as they wish.
Expand All @@ -204,7 +236,8 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
}
/**
* @notice Withdraw staked tokens.
* @notice Withdraw staked tokens. Callable only by users with a staked balance. Fails when the specified amount is
* 0, or is greater than the currently staked balance. Emits an Unstake event on success.
* @param stakedToken The address of the token to withdraw.
* @param amount The amount of the token to withdraw.
*/
Expand All @@ -230,7 +263,8 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
}
/**
* @notice Get entitled rewards for the staker.
* @notice Claim all rewards available to the caller. Callable by any user. Emits a RewardsWithdrawn event on
* success.
* @dev Calling this method will reset the caller's reward multiplier.
* @param stakedToken The address of the token to get rewards for.
*/
Expand All @@ -257,7 +291,8 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
}

/**
* @notice Exits a staking position by unstaking and getting rewards. This totally exits the staking position.
* @notice Claim all rewards available to the caller and exits their staking position. Callable by any user.
* Emits Unstake, RewardsWithdrawn and Exit events on success.
* @dev Calling this method will reset the caller's reward multiplier.
* @param stakedToken The address of the token to get rewards for.
*/
Expand Down Expand Up @@ -368,6 +403,7 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
* cumulative previous deposits, new deposit and time from the last deposit.
* @param stakedToken The address of the staked token to query.
* @param account The address of the user to query.
* @param amount Marginal amount of stakingToken to be deposited into the staking contract.
* @return uint256 Average post deposit time, considering all deposits to date.
*/
function getAverageDepositTimePostDeposit(
Expand All @@ -386,7 +422,11 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
* INTERNAL FUNCTIONS *
**************************************/

// Update the internal counters for a given stakedToken and user.
/**
* @notice Update global state for a given stakedToken. If a user address is supplied, update that user's rewards.
* @param stakedToken The address of the staked token to update.
* @param account The address of the user to update. Supplying address(0) will skip any user update.
*/
function _updateReward(address stakedToken, address account) internal {
StakingToken storage stakingToken = stakingTokens[stakedToken];
stakingToken.rewardPerTokenStored = baseRewardPerToken(stakedToken);
Expand All @@ -398,6 +438,13 @@ contract AcceleratingDistributor is ReentrancyGuard, Ownable, Multicall {
}
}

/**
* @notice Deposit user funds of stakedToken into the staking contract.
* @dev Rewards for any pre-existing staking balances are finalised prior to modifying user state.
* @param stakedToken The address of the staked token to update.
* @param amount Marginal amount of stakingToken to be deposited into the staking contract.
* @param staker The address of the user depositing funds.
*/
function _stake(
address stakedToken,
uint256 amount,
Expand Down

0 comments on commit 95ae7ff

Please sign in to comment.