Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,22 +113,28 @@ contract AMMPoolToken is ERC20Plugins {

Storage access:

- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/FarmAccounting.sol#L14-L16) for farming params, updated only on farming restarting:
- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/Farming.sol#L9-L11) for farming params, updated when farming is restarted or stopped:

```solidity
uint40 public finished;
uint32 public duration;
uint184 public reward;
```

- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/Farming.sol#L9-L12) for total amount of rewards that haven't been claimed yet, updated when farming is restarted, stopped or when the user claims rewards:

```solidity
uint256 balance;
```

- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/UserAccounting.sol#L7-L8) for farming state, updated only on changing number of farming tokens:
- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/Rewards.sol#L9-L10) for farming state, updated only on changing number of farming tokens:

```solidity
uint40 public checkpoint;
uint216 public farmedPerTokenStored;
```

- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/UserAccounting.sol#L9) per each farmer, updated on deposits/withdrawals (kudos to [@snjax](https://github.com/snjax)):
- [1 storage slot](https://github.com/1inch/farming/blob/master/contracts/accounting/Rewards.sol#L11) per each farmer, updated on deposits/withdrawals (kudos to [@snjax](https://github.com/snjax)):

```solidity
mapping(address => int256) public corrections;
Expand Down
34 changes: 34 additions & 0 deletions contracts/Distributor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

import { IDistributor } from "./interfaces/IDistributor.sol";

abstract contract Distributor is IDistributor, Ownable {
address internal _distributor;

event DistributorChanged(address oldDistributor, address newDistributor);

error NotDistributor();
error SameDistributor();
error ZeroDistributorAddress();

modifier onlyDistributor {
if (msg.sender != _distributor) revert NotDistributor();
_;
}

function setDistributor(address distributor_) public virtual onlyOwner {
if (distributor_ == address(0)) revert ZeroDistributorAddress();
address oldDistributor = _distributor;
if (distributor_ == oldDistributor) revert SameDistributor();
emit DistributorChanged(oldDistributor, distributor_);
_distributor = distributor_;
}

function distributor() public view virtual returns (address) {
return _distributor;
}
}
116 changes: 58 additions & 58 deletions contracts/FarmingLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

pragma solidity ^0.8.0;

import { FarmAccounting } from "./accounting/FarmAccounting.sol";
import { UserAccounting } from "./accounting/UserAccounting.sol";
import { Farming } from "./accounting/Farming.sol";
import { Rewards } from "./accounting/Rewards.sol";

/// @title FarmingLib
/// @dev A library for farming logic, using FarmAccounting and UserAccounting.
/// @dev A library for farming logic, using Farming and Rewards.
library FarmingLib {
using FarmAccounting for FarmAccounting.Info;
using UserAccounting for UserAccounting.Info;
using Farming for Farming.Info;
using Rewards for Rewards.Info;
using FarmingLib for FarmingLib.Info;

/// @dev Struct containing farm and user detailed info for farming operations. See {FarmAccounting.Info} and {UserAccounting.Info} for.
/// @dev Struct containing farming and rewards detailed info for farming operations. See {Farming.Info} and {Rewards.Info}.
struct Data {
FarmAccounting.Info farmInfo;
UserAccounting.Info userInfo;
Farming.Info farmingInfo;
Rewards.Info rewardsInfo;
}

/// @dev Struct containing the total supply function and a data slot for EVM storage.
Expand All @@ -25,7 +25,7 @@ library FarmingLib {
}

/**
* @notice Creates a new Info struct.
* @notice Creates a new FarmingLib.Info struct.
* @param getTotalSupply The function to get the total supply.
* @param data The data struct for storage.
* @return info The created Info struct.
Expand All @@ -40,8 +40,8 @@ library FarmingLib {
}

/**
* @notice Retrieves the Data struct from an Info struct.
* @param self The Info struct.
* @notice Retrieves the FarmingLib.Data struct from an FarmingLib.Info struct.
* @param self The Info struct to retrieve data from storage.
* @return data The retrieved Data struct.
*/
function getData(Info memory self) internal pure returns(Data storage data) {
Expand All @@ -52,84 +52,73 @@ library FarmingLib {
}

/**
* @notice Begins farming for a specified period.
* @param self The Info struct.
* @param amount The amount to farm.
* @param period The farming period.
* @return reward The farming reward.
* @notice Updates farming info with new amount and specified period.
* @param self The FarmingLib.Info struct to retrieve data from storage.
* @param amount A new amount to farm.
* @param period A new farming period.
* @return reward Updated farming reward.
*/
function startFarming(Info memory self, uint256 amount, uint256 period) internal returns(uint256 reward) {
function updateFarmData(Info memory self, uint256 amount, uint256 period) internal returns(uint256 reward) {
Data storage data = self.getData();
data.userInfo.updateFarmedPerToken(_farmedPerToken(self));
reward = data.farmInfo.startFarming(amount, period);
data.rewardsInfo.updateFarmedPerToken(_farmedPerToken(self));
reward = data.farmingInfo.update(amount, period);
}

/**
* @notice Stops farming immediately.
* @param self The FarmingLib.Info struct to retrieve data from storage.
* @return leftover Amount of reward tokens remaining after farming.
*/
function stopFarming(Info memory self) internal returns(uint256 leftover) {
function cancelFarming(Info memory self) internal returns(uint256 leftover) {
Data storage data = self.getData();
data.userInfo.updateFarmedPerToken(_farmedPerToken(self));
leftover = data.farmInfo.stopFarming();
}

/**
* @notice Gets the farmed amount for an account.
* @param self The Info struct.
* @param account The account to check.
* @param balance The account balance.
* @return result The farmed amount.
*/
function farmed(Info memory self, address account, uint256 balance) internal view returns(uint256) {
return self.getData().userInfo.farmed(account, balance, _farmedPerToken(self));
data.rewardsInfo.updateFarmedPerToken(_farmedPerToken(self));
leftover = data.farmingInfo.cancel();
}

/**
* @notice Claims the farmed amount for an account.
* @param self The Info struct.
* @param account The account to claim for.
* @param balance The account balance.
* @return amount The claimed amount.
* @notice Claims the farmed reward tokens for an account.
* @param self The FarmingLib.Info struct to retrieve data from storage.
* @param account The address of the account to claim for.
* @param balance The account balance of farmable tokens.
* @return amount The claimed amount of reward tokens.
*/
function claim(Info memory self, address account, uint256 balance) internal returns(uint256 amount) {
Data storage data = self.getData();
uint256 fpt = _farmedPerToken(self);
amount = data.userInfo.farmed(account, balance, fpt);
amount = data.rewardsInfo.farmed(account, balance, fpt);
if (amount > 0) {
data.userInfo.eraseFarmed(account, balance, fpt);
data.farmInfo.claim(amount);
data.rewardsInfo.eraseFarmed(account, balance, fpt);
data.farmingInfo.claim(amount);
}
}

/**
* @notice Updates the balances of two accounts.
* @param self The Info struct.
* @param from The account to transfer from.
* @param to The account to transfer to.
* @notice Updates the farmable token balances of two accounts.
* @param self The FarmingLib.Info struct to retrieve data from storage.
* @param from The address of the account to transfer from.
* @param to The address of the account to transfer to.
* @param amount The amount to transfer.
*/
function updateBalances(Info memory self, address from, address to, uint256 amount) internal {
self.getData().userInfo.updateBalances(from, to, amount, _farmedPerToken(self));
self.getData().rewardsInfo.updateBalances(from, to, amount, _farmedPerToken(self));
}

function _farmedPerToken(Info memory self) private view returns (uint256) {
return self.getData().userInfo.farmedPerToken(_infoToContext(self), _lazyGetSupply, _lazyGetFarmed);
}

// UserAccounting bindings

function _lazyGetSupply(bytes32 context) private view returns(uint256) {
Info memory self = _contextToInfo(context);
return self.getTotalSupply();
/**
* @notice Gets the amount of farmed reward tokens for an account.
* @param self The FarmingLib.Info struct to retrieve data from storage.
* @param account The address of the account to check.
* @param balance The farmable token balance of the account.
* @return result The number of tokens farmed.
*/
function farmed(Info memory self, address account, uint256 balance) internal view returns(uint256) {
return self.getData().rewardsInfo.farmed(account, balance, _farmedPerToken(self));
}

function _lazyGetFarmed(bytes32 context, uint256 checkpoint) private view returns(uint256) {
Info memory self = _contextToInfo(context);
return self.getData().farmInfo.farmedSinceCheckpointScaled(checkpoint);
function _farmedPerToken(Info memory self) private view returns (uint256) {
return self.getData().rewardsInfo.farmedPerToken(_infoToContext(self), _lazyGetSupply, _lazyGetFarmed);
}

// --- Rewards bindings section start ---
function _contextToInfo(bytes32 context) private pure returns(Info memory self) {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
self := context
Expand All @@ -141,4 +130,15 @@ library FarmingLib {
context := self
}
}

function _lazyGetSupply(bytes32 context) private view returns(uint256) {
Info memory self = _contextToInfo(context);
return self.getTotalSupply();
}

function _lazyGetFarmed(bytes32 context, uint256 checkpoint) private view returns(uint256) {
Info memory self = _contextToInfo(context);
return self.getData().farmingInfo.farmedSinceCheckpointScaled(checkpoint);
}
// --- Rewards bindings section end ---
}
Loading