Skip to content

Commit

Permalink
Merge pull request #4 from 1inch/feature/oz_5
Browse files Browse the repository at this point in the history
[SC-989][SC-990] Feature/oz 5
  • Loading branch information
ZumZoom authored Dec 21, 2023
2 parents 8a812b0 + f81cab8 commit 3ea4994
Show file tree
Hide file tree
Showing 14 changed files with 1,605 additions and 746 deletions.
25 changes: 0 additions & 25 deletions .github/actions/setup/action.yml

This file was deleted.

18 changes: 15 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,32 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- uses: actions/setup-node@v3
with:
node-version: 20
cache: 'yarn'
- run: yarn
- run: yarn lint

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- uses: actions/setup-node@v3
with:
node-version: 20
cache: 'yarn'
- run: yarn
- run: yarn test:ci

coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/setup
- uses: actions/setup-node@v3
with:
node-version: 20
cache: 'yarn'
- run: yarn
- run: yarn coverage
- uses: codecov/codecov-action@v3
28 changes: 28 additions & 0 deletions .solcover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = {
configureYulOptimizer: true,
solcOptimizerDetails: {
yul: true,
yulDetails: {
optimizerSteps:
'dhfoDgvlfnTUtnIf' + // None of these can make stack problems worse
'[' +
'xa[r]EscLM' + // Turn into SSA and simplify
'cCTUtTOntnfDIl' + // Perform structural simplification
'Lcl' + // Simplify again
'Vcl [j]' + // Reverse SSA

// should have good 'compilability' property here.

'Tpel' + // Run functional expression inliner
'xa[rl]' + // Prune a bit more in SSA
'xa[r]cL' + // Turn into SSA again and simplify
'gvf' + // Run full inliner
'CTUca[r]LSsTFOtfDnca[r]Ilc' + // SSA plus simplify
']' +
'jml[jl] VcTOcl jml : fDnTOcm', // Make source short and pretty
},
},
skipFiles: [
'mocks', 'tests', 'interfaces',
],
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"solidity.compileUsingRemoteVersion": "0.8.19"
"solidity.compileUsingRemoteVersion": "0.8.23"
}
45 changes: 15 additions & 30 deletions contracts/St1inch.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;
pragma solidity 0.8.23;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
Expand Down Expand Up @@ -64,7 +64,7 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
uint256 private constant _PLUGIN_CALL_GAS_LIMIT = 500_000;
uint256 private constant _ONE_E9 = 1e9;

IERC20 public immutable oneInch;
IERC20 public immutable ONE_INCH;

/// @notice The stucture to store stake information for a staker
struct Depositor {
Expand All @@ -91,12 +91,13 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
ERC20Plugins(_PLUGINS_LIMIT, _PLUGIN_CALL_GAS_LIMIT)
ERC20("Staking 1INCH v2", "st1INCH")
VotingPowerCalculator(expBase_, block.timestamp)
Ownable(msg.sender)
{
// voting power after MAX_LOCK_PERIOD should be equal to staked amount divided by _VOTING_POWER_DIVIDER
if (_votingPowerAt(1e18, block.timestamp + MAX_LOCK_PERIOD) * _VOTING_POWER_DIVIDER < 1e18) revert ExpBaseTooBig();
if (_votingPowerAt(1e18, block.timestamp + MAX_LOCK_PERIOD + 1) * _VOTING_POWER_DIVIDER > 1e18) revert ExpBaseTooSmall();
setFeeReceiver(feeReceiver_);
oneInch = oneInch_;
ONE_INCH = oneInch_;
}

/**
Expand All @@ -114,7 +115,7 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
* @param defaultFarm_ The farm contract address
*/
function setDefaultFarm(address defaultFarm_) external onlyOwner {
if (defaultFarm_ != address(0) && Plugin(defaultFarm_).token() != this) revert DefaultFarmTokenMismatch();
if (defaultFarm_ != address(0) && Plugin(defaultFarm_).TOKEN() != this) revert DefaultFarmTokenMismatch();
defaultFarm = defaultFarm_;
emit DefaultFarmSet(defaultFarm_);
}
Expand Down Expand Up @@ -217,7 +218,7 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
* @param permit Permit given by the staker
*/
function depositWithPermit(uint256 amount, uint256 duration, bytes calldata permit) external {
oneInch.safePermit(permit);
ONE_INCH.safePermit(permit);
_deposit(msg.sender, amount, duration);
}

Expand All @@ -238,10 +239,10 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
* @param permit Permit given by the caller
*/
function depositForWithPermit(address account, uint256 amount, bytes calldata permit) external {
oneInch.safePermit(permit);
ONE_INCH.safePermit(permit);
_deposit(account, amount, 0);
}

/**
* @notice Implements logic to stake tokens and add the staker for the default farm if needed
* @param account The account staking tokens
Expand All @@ -266,7 +267,7 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
_mint(account, balanceDiff);

if (amount > 0) {
oneInch.safeTransferFrom(msg.sender, address(this), amount);
ONE_INCH.safeTransferFrom(msg.sender, address(this), amount);
}

if (defaultFarm != address(0) && !hasPlugin(account, defaultFarm)) {
Expand Down Expand Up @@ -311,8 +312,8 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
if (loss > amount * maxLossRatio / _ONE_E9) revert LossIsTooBig();

_withdraw(depositor, balance);
oneInch.safeTransfer(to, ret);
oneInch.safeTransfer(feeReceiver, loss);
ONE_INCH.safeTransfer(to, ret);
ONE_INCH.safeTransfer(feeReceiver, loss);
}
}

Expand All @@ -328,7 +329,7 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
(loss, ret) = _earlyWithdrawLoss(amount, balanceOf(account));
canWithdraw = loss <= amount * maxLossRatio / _ONE_E9;
}

/**
* @notice Calculates the loss amount if the staker does early withdrawal at the current block
* @dev Internal, Maths:
Expand Down Expand Up @@ -365,7 +366,7 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
uint256 amount = depositor.amount;
if (amount > 0) {
_withdraw(depositor, balanceOf(msg.sender));
oneInch.safeTransfer(to, amount);
ONE_INCH.safeTransfer(to, amount);
}
}

Expand All @@ -387,8 +388,8 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
if (address(token) == address(0)) {
Address.sendValue(payable(msg.sender), amount);
} else {
if (token == oneInch) {
if (amount > oneInch.balanceOf(address(this)) - totalDeposits) revert RescueAmountIsTooLarge();
if (token == ONE_INCH) {
if (amount > ONE_INCH.balanceOf(address(this)) - totalDeposits) revert RescueAmountIsTooLarge();
}
token.safeTransfer(msg.sender, amount);
}
Expand Down Expand Up @@ -419,20 +420,4 @@ contract St1inch is ERC20Plugins, Ownable, VotingPowerCalculator, IVotable {
function transferFrom(address, address, uint256) public pure override(IERC20, ERC20) returns (bool) {
revert TransferDisabled();
}

/**
* @notice Always reverts to disable ERC20 token transfer feature
* @dev This function always reverts
*/
function increaseAllowance(address, uint256) public pure override returns (bool) {
revert ApproveDisabled();
}

/**
* @notice Always reverts to disable ERC20 token transfer feature
* @dev This function always reverts
*/
function decreaseAllowance(address, uint256) public pure override returns (bool) {
revert ApproveDisabled();
}
}
12 changes: 6 additions & 6 deletions contracts/StakingFarmingPlugin.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;
pragma solidity 0.8.23;

import "@1inch/farming/contracts/FarmingPlugin.sol";
import "./interfaces/ISt1inch.sol";

contract StakingFarmingPlugin is FarmingPlugin {
using SafeERC20 for IERC20;

ISt1inch public immutable st1inch;
ISt1inch public immutable ST1INCH;

constructor(ISt1inch st1inch_) FarmingPlugin(st1inch_, st1inch_.oneInch()) {
st1inch = st1inch_;
constructor(ISt1inch st1inch_, address owner_) FarmingPlugin(st1inch_, st1inch_.ONE_INCH(), owner_) {
ST1INCH = st1inch_;
}

function _transferReward(IERC20 reward, address to, uint256 amount) internal override {
if (st1inch.emergencyExit()) {
if (ST1INCH.emergencyExit()) {
reward.safeTransfer(to, amount);
} else {
st1inch.depositFor(to, amount);
ST1INCH.depositFor(to, amount);
}
}
}
21 changes: 12 additions & 9 deletions contracts/helpers/St1inchPreview.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;
pragma solidity 0.8.23;

import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./VotingPowerCalculator.sol";
import "../St1inch.sol";

contract St1inchPreview is VotingPowerCalculator, Ownable {
St1inch public immutable st1INCH;
St1inch public immutable ST1INCH;
uint256 private constant _VOTING_POWER_DIVIDER = 20;
uint256 private constant _ONE_E9 = 1e9;
uint256 public durationUntilMaxAllowedLoss; // log(0.95 * maxAllowedLoss + 0.05) / log(baseExp)

constructor(St1inch st1INCH_) VotingPowerCalculator(st1INCH_.expBase(), st1INCH_.origin()) {
st1INCH = st1INCH_;
constructor(St1inch st1INCH_)
VotingPowerCalculator(st1INCH_.EXP_BASE(), st1INCH_.ORIGIN())
Ownable(msg.sender)
{
ST1INCH = st1INCH_;
}

function previewBalance(address account, uint256 amount, uint256 duration) external view returns (uint256) {
(, uint40 unlockTime, uint176 balance) = st1INCH.depositors(account);
(, uint40 unlockTime, uint176 balance) = ST1INCH.depositors(account);
uint256 lockedTill = Math.max(unlockTime, block.timestamp) + duration;
return _balanceAt(balance + amount, lockedTill) / _VOTING_POWER_DIVIDER;
}
Expand All @@ -28,15 +31,15 @@ contract St1inchPreview is VotingPowerCalculator, Ownable {
}

function previewPowerOfAtTime(address account, uint256 amount, uint256 duration, uint256 timestamp) public view returns (uint256) {
(, uint40 unlockTime, uint176 balance) = st1INCH.depositors(account);
(, uint40 unlockTime, uint176 balance) = ST1INCH.depositors(account);
uint256 lockedTill = Math.max(unlockTime, block.timestamp) + duration;
return _votingPowerAt(_balanceAt(balance + amount, lockedTill) / _VOTING_POWER_DIVIDER, timestamp);
}

function previewUnlockTime(address account) public view returns (uint256 allowedExitTime) {
(uint40 lockTime, uint40 unlockTime,) = st1INCH.depositors(account);
allowedExitTime = lockTime + (unlockTime - lockTime) * st1INCH.minLockPeriodRatio() / _ONE_E9;
allowedExitTime = Math.max(allowedExitTime, unlockTime - st1INCH.MAX_LOCK_PERIOD() + durationUntilMaxAllowedLoss);
(uint40 lockTime, uint40 unlockTime,) = ST1INCH.depositors(account);
allowedExitTime = lockTime + (unlockTime - lockTime) * ST1INCH.minLockPeriodRatio() / _ONE_E9;
allowedExitTime = Math.max(allowedExitTime, unlockTime - ST1INCH.MAX_LOCK_PERIOD() + durationUntilMaxAllowedLoss);
}

function setDurationUntilMaxAllowedLoss(uint256 duration) external onlyOwner {
Expand Down
Loading

0 comments on commit 3ea4994

Please sign in to comment.