Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SC-929] Renamed FarmAccounting and UserAccounting libraries #73

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,22 +113,22 @@ 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/libraries/Allocation.sol#L13-L15) for farming params, updated only 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/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/libraries/Accounting.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/libraries/Accounting.sol#L11) per each farmer, updated on deposits/withdrawals (kudos to [@snjax](https://github.com/snjax)):

```solidity
mapping(address => int256) public corrections;
Expand Down
10 changes: 5 additions & 5 deletions contracts/FarmingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import { IERC20Plugins } from "@1inch/token-plugins/contracts/interfaces/IERC20P

import { IFarmingPlugin } from "./interfaces/IFarmingPlugin.sol";
import { Distributor } from "./Distributor.sol";
import { FarmingLib, FarmAccounting } from "./FarmingLib.sol";
import { FarmingLib, Allocation } from "./libraries/FarmingLib.sol";

contract FarmingPlugin is Plugin, IFarmingPlugin, Distributor {
using SafeERC20 for IERC20;
using FarmingLib for FarmingLib.Info;
using FarmAccounting for FarmAccounting.Info;
using Allocation for Allocation.Info;
using Address for address payable;

error ZeroFarmableTokenAddress();
Expand All @@ -37,8 +37,8 @@ contract FarmingPlugin is Plugin, IFarmingPlugin, Distributor {
emit FarmCreated(address(farmableToken_), address(rewardsToken_));
}

function farmInfo() public view returns(FarmAccounting.Info memory) {
return _farm.farmInfo;
function farmInfo() public view returns(Allocation.Info memory) {
return _farm.allocationInfo;
}

function totalSupply() public view returns(uint256) {
Expand Down Expand Up @@ -91,7 +91,7 @@ contract FarmingPlugin is Plugin, IFarmingPlugin, Distributor {
payable(_distributor).sendValue(amount);
} else {
if (token_ == rewardsToken) {
if (rewardsToken.balanceOf(address(this)) < _farm.farmInfo.balance + amount) revert InsufficientFunds();
if (rewardsToken.balanceOf(address(this)) < _farm.allocationInfo.balance + amount) revert InsufficientFunds();
}
token_.safeTransfer(_distributor, amount);
}
Expand Down
8 changes: 4 additions & 4 deletions contracts/FarmingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.s

import { IFarmingPool } from "./interfaces/IFarmingPool.sol";
import { Distributor } from "./Distributor.sol";
import { FarmAccounting, FarmingLib } from "./FarmingLib.sol";
import { Allocation, FarmingLib } from "./libraries/FarmingLib.sol";

contract FarmingPool is IFarmingPool, Distributor, ERC20 {
using SafeERC20 for IERC20;
Expand Down Expand Up @@ -48,8 +48,8 @@ contract FarmingPool is IFarmingPool, Distributor, ERC20 {
return IERC20Metadata(address(stakingToken)).decimals();
}

function farmInfo() public view returns(FarmAccounting.Info memory) {
return _farm.farmInfo;
function farmInfo() public view returns(Allocation.Info memory) {
return _farm.allocationInfo;
}

function startFarming(uint256 amount, uint256 period) public virtual onlyDistributor {
Expand Down Expand Up @@ -104,7 +104,7 @@ contract FarmingPool is IFarmingPool, Distributor, ERC20 {
if (token == stakingToken) {
if (stakingToken.balanceOf(address(this)) < totalSupply() + amount) revert InsufficientFunds();
} else if (token == rewardsToken) {
if (rewardsToken.balanceOf(address(this)) < _farm.farmInfo.balance + amount) revert InsufficientFunds();
if (rewardsToken.balanceOf(address(this)) < _farm.allocationInfo.balance + amount) revert InsufficientFunds();
}

token.safeTransfer(_distributor, amount);
Expand Down
8 changes: 4 additions & 4 deletions contracts/MultiFarmingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { IERC20Plugins } from "@1inch/token-plugins/contracts/interfaces/IERC20P

import { IMultiFarmingPlugin } from "./interfaces/IMultiFarmingPlugin.sol";
import { Distributor } from "./Distributor.sol";
import { FarmAccounting, FarmingLib } from "./FarmingLib.sol";
import { Allocation, FarmingLib } from "./libraries/FarmingLib.sol";

contract MultiFarmingPlugin is Plugin, IMultiFarmingPlugin, Distributor {
using SafeERC20 for IERC20;
Expand Down Expand Up @@ -46,8 +46,8 @@ contract MultiFarmingPlugin is Plugin, IMultiFarmingPlugin, Distributor {
return _rewardsTokens.items.get();
}

function farmInfo(IERC20 rewardsToken) public view returns(FarmAccounting.Info memory) {
return _farms[rewardsToken].farmInfo;
function farmInfo(IERC20 rewardsToken) public view returns(Allocation.Info memory) {
return _farms[rewardsToken].allocationInfo;
}

function totalSupply() public view returns(uint256) {
Expand Down Expand Up @@ -132,7 +132,7 @@ contract MultiFarmingPlugin is Plugin, IMultiFarmingPlugin, Distributor {
payable(_distributor).sendValue(amount);
} else {
if (_rewardsTokens.contains(address(token_))) {
if (token_.balanceOf(address(this)) < _farms[token_].farmInfo.balance + amount) revert InsufficientFunds();
if (token_.balanceOf(address(this)) < _farms[token_].allocationInfo.balance + amount) revert InsufficientFunds();
}
token_.safeTransfer(_distributor, amount);
}
Expand Down
4 changes: 2 additions & 2 deletions contracts/interfaces/IFarmingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ pragma solidity ^0.8.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IPlugin } from "@1inch/token-plugins/contracts/interfaces/IPlugin.sol";
import { FarmAccounting } from "../accounting/FarmAccounting.sol";
import { Allocation } from "../libraries/Allocation.sol";

interface IFarmingPlugin is IPlugin {
event FarmCreated(address token, address reward);
event RewardUpdated(uint256 reward, uint256 duration);

// View functions
function totalSupply() external view returns(uint256);
function farmInfo() external view returns(FarmAccounting.Info memory);
function farmInfo() external view returns(Allocation.Info memory);
function farmed(address account) external view returns(uint256);

// User functions
Expand Down
4 changes: 2 additions & 2 deletions contracts/interfaces/IFarmingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
pragma solidity ^0.8.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { FarmAccounting } from "../accounting/FarmAccounting.sol";
import { Allocation } from "../libraries/Allocation.sol";

interface IFarmingPool is IERC20 {
event RewardUpdated(uint256 reward, uint256 duration);

// View functions
function farmInfo() external view returns(FarmAccounting.Info memory);
function farmInfo() external view returns(Allocation.Info memory);
function farmed(address account) external view returns(uint256);

// User functions
Expand Down
4 changes: 2 additions & 2 deletions contracts/interfaces/IMultiFarmingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ pragma solidity ^0.8.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IPlugin } from "@1inch/token-plugins/contracts/interfaces/IPlugin.sol";
import { FarmAccounting } from "../accounting/FarmAccounting.sol";
import { Allocation } from "../libraries/Allocation.sol";

interface IMultiFarmingPlugin is IPlugin {
event FarmCreated(address token, address reward);
event RewardUpdated(address token, uint256 reward, uint256 duration);

// View functions
function totalSupply() external view returns(uint256);
function farmInfo(IERC20 rewardsToken) external view returns(FarmAccounting.Info memory);
function farmInfo(IERC20 rewardsToken) external view returns(Allocation.Info memory);
function farmed(IERC20 rewardsToken, address account) external view returns(uint256);

// User functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

pragma solidity ^0.8.0;

import { FarmAccounting } from "./FarmAccounting.sol";
import { Allocation } from "./Allocation.sol";

library UserAccounting {
library Accounting {
struct Info {
uint40 checkpoint;
uint216 farmedPerTokenStored;
Expand All @@ -30,7 +30,7 @@ library UserAccounting {

function farmed(Info storage info, address account, uint256 balance, uint256 fpt) internal view returns(uint256) {
// balance * fpt is less than 168 bit
return uint256(int256(balance * fpt) - info.corrections[account]) / FarmAccounting._SCALE;
return uint256(int256(balance * fpt) - info.corrections[account]) / Allocation._SCALE;
}

function eraseFarmed(Info storage info, address account, uint256 balance, uint256 fpt) internal {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;

import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";

library FarmAccounting {
library Allocation {
error ZeroDuration();
error DurationTooLarge();
error AmountTooLarge();
Expand All @@ -31,7 +31,7 @@ library FarmAccounting {
}
}

function startFarming(Info storage info, uint256 amount, uint256 period) internal returns(uint256) {
function allocate(Info storage info, uint256 amount, uint256 period) internal returns(uint256) {
if (period == 0) revert ZeroDuration();
if (period > type(uint32).max) revert DurationTooLarge();

Expand All @@ -52,7 +52,7 @@ library FarmAccounting {
return amount;
}

function stopFarming(Info storage info) internal returns(uint256 leftover) {
function terminateAllocation(Info storage info) internal returns(uint256 leftover) {
leftover = info.reward - farmedSinceCheckpointScaled(info, info.finished - info.duration) / _SCALE;
(info.finished, info.duration, info.reward, info.balance) = (
uint40(block.timestamp),
Expand Down
40 changes: 20 additions & 20 deletions contracts/FarmingLib.sol → contracts/libraries/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 { Allocation } from "./Allocation.sol";
import { Accounting } from "./Accounting.sol";

/// @title FarmingLib
/// @dev A library for farming logic, using FarmAccounting and UserAccounting.
/// @dev A library for farming logic, using Allocation and Accounting.
library FarmingLib {
using FarmAccounting for FarmAccounting.Info;
using UserAccounting for UserAccounting.Info;
using Allocation for Allocation.Info;
using Accounting for Accounting.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 allocation and accounting detailed info for farming operations. See {Allocation.Info} and {Accounting.Info} for.
struct Data {
FarmAccounting.Info farmInfo;
UserAccounting.Info userInfo;
Allocation.Info allocationInfo;
Accounting.Info accountingInfo;
}

/// @dev Struct containing the total supply function and a data slot for EVM storage.
Expand Down Expand Up @@ -60,8 +60,8 @@ library FarmingLib {
*/
function startFarming(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.accountingInfo.updateFarmedPerToken(_farmedPerToken(self));
reward = data.allocationInfo.allocate(amount, period);
}

/**
Expand All @@ -71,8 +71,8 @@ library FarmingLib {
*/
function stopFarming(Info memory self) internal returns(uint256 leftover) {
Data storage data = self.getData();
data.userInfo.updateFarmedPerToken(_farmedPerToken(self));
leftover = data.farmInfo.stopFarming();
data.accountingInfo.updateFarmedPerToken(_farmedPerToken(self));
leftover = data.allocationInfo.terminateAllocation();
}

/**
Expand All @@ -83,7 +83,7 @@ library FarmingLib {
* @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));
return self.getData().accountingInfo.farmed(account, balance, _farmedPerToken(self));
}

/**
Expand All @@ -96,10 +96,10 @@ library FarmingLib {
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.accountingInfo.farmed(account, balance, fpt);
if (amount > 0) {
data.userInfo.eraseFarmed(account, balance, fpt);
data.farmInfo.claim(amount);
data.accountingInfo.eraseFarmed(account, balance, fpt);
data.allocationInfo.claim(amount);
}
}

Expand All @@ -111,14 +111,14 @@ library FarmingLib {
* @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().accountingInfo.updateBalances(from, to, amount, _farmedPerToken(self));
}

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

// UserAccounting bindings
// Accounting bindings

function _lazyGetSupply(bytes32 context) private view returns(uint256) {
Info memory self = _contextToInfo(context);
Expand All @@ -127,7 +127,7 @@ library FarmingLib {

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

function _contextToInfo(bytes32 context) private pure returns(Info memory self) {
Expand Down
6 changes: 3 additions & 3 deletions test/FarmingPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,14 @@ describe('FarmingPlugin', function () {
const duration = BigInt(60 * 60 * 24);
await farm.startFarming(1000, duration);
await time.increaseTo((await farm.farmInfo()).finished + 1n);

const balanceWalletBefore = await gift.balanceOf(wallet1);
const balanceFarmBefore = await gift.balanceOf(farm);

const distributor = await farm.distributor();
expect(wallet1.address).to.equal(distributor);
await farm.stopFarming();

expect(await gift.balanceOf(wallet1)).to.be.equal(balanceWalletBefore);
expect(await gift.balanceOf(farm)).to.be.equal(balanceFarmBefore);
expect((await farm.farmInfo()).reward).to.be.equal(0);
Expand Down
Loading