From 85de256bff50cd258ba0bff36494873673f942d0 Mon Sep 17 00:00:00 2001 From: thomga Date: Thu, 12 Jan 2023 16:18:39 -0300 Subject: [PATCH 1/3] feat: implement staking with permit on PegasysStaking --- .npmignore | 5 ++- README.md | 2 +- contracts/earn/PegasysStaking.sol | 69 ++++++++++++++++++++++++++++++- package.json | 2 +- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/.npmignore b/.npmignore index de9d0b9..49b67d6 100644 --- a/.npmignore +++ b/.npmignore @@ -6,4 +6,7 @@ node_modules/ .env.example .github/ hardhat.config.ts -tsconfig.json \ No newline at end of file +tsconfig.json +contracts/TestERC20.sol +contracts/WSYS.sol +contracts/Distributor.sol \ No newline at end of file diff --git a/README.md b/README.md index af910b1..07b98af 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ TimeLock: `0x2C4ce5DcE61b22d9eed75136CD5C8bbd788A243B` GovernorAlpha: `0x633Bdeb5D4b5f93933833A692e230a7d48fC2d77` -PegasysStaking: `0x83dd2F2bFd808b4618BF1d6c7d09714e66EE3014` +PegasysStaking: `0xC46be9cC139f927483b895E60BFA2ECffDa4D8b2` ### Syscoin Tanenbaum Testnet: diff --git a/contracts/earn/PegasysStaking.sol b/contracts/earn/PegasysStaking.sol index b5129d7..c28df0d 100644 --- a/contracts/earn/PegasysStaking.sol +++ b/contracts/earn/PegasysStaking.sol @@ -6,6 +6,7 @@ import "openzeppelin-contracts-legacy/math/SafeMath.sol"; import "openzeppelin-contracts-legacy/token/ERC20/SafeERC20.sol"; import "openzeppelin-contracts-legacy/access/Ownable.sol"; import "openzeppelin-contracts-legacy/token/ERC20/IERC20.sol"; +import "../pegasys-core/interfaces/IPegasysERC20.sol"; /** * @title Pegasys Staking @@ -179,6 +180,70 @@ contract PegasysStaking is Ownable { emit Deposit(_msgSender(), _amountMinusFee, _fee); } + /** + * @notice Deposit PSYS for reward token allocation with permit + * @param _amount The amount of PSYS to deposit + */ + function depositWithPermit( + uint256 _amount, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external { + UserInfo storage user = userInfo[_msgSender()]; + + uint256 _fee = _amount.mul(depositFeePercent).div( + DEPOSIT_FEE_PERCENT_PRECISION + ); + uint256 _amountMinusFee = _amount.sub(_fee); + + uint256 _previousAmount = user.amount; + uint256 _newAmount = user.amount.add(_amountMinusFee); + user.amount = _newAmount; + + uint256 _len = rewardTokens.length; + for (uint256 i; i < _len; i++) { + IERC20 _token = rewardTokens[i]; + updateReward(_token); + + uint256 _previousRewardDebt = user.rewardDebt[_token]; + user.rewardDebt[_token] = _newAmount + .mul(accRewardPerShare[_token]) + .div(ACC_REWARD_PER_SHARE_PRECISION); + + if (_previousAmount != 0) { + uint256 _pending = _previousAmount + .mul(accRewardPerShare[_token]) + .div(ACC_REWARD_PER_SHARE_PRECISION) + .sub(_previousRewardDebt); + if (_pending != 0) { + safeTokenTransfer(_token, _msgSender(), _pending); + emit ClaimReward(_msgSender(), address(_token), _pending); + } + } + } + + // permit + IPegasysERC20(address(psys)).permit( + msg.sender, + address(this), + _amount, + deadline, + v, + r, + s + ); + + psys.safeTransferFrom(_msgSender(), address(this), _amount); + + internalPsysBalance = internalPsysBalance.add(_amountMinusFee); + + safeTokenTransfer(psys, _msgSender(), _fee); + + emit Deposit(_msgSender(), _amountMinusFee, _fee); + } + /** * @notice Get user info * @param _user The address of the user @@ -265,8 +330,8 @@ contract PegasysStaking is Ownable { uint256 _depositFeePercent ) external onlyOwner { require( - _depositFeePercent <= 5e17, - "PegasysStaking: deposit fee can't be greater than 50%" + _depositFeePercent <= 3e16, + "PegasysStaking: deposit fee can't be greater than 3%" ); uint256 oldFee = depositFeePercent; depositFeePercent = _depositFeePercent; diff --git a/package.json b/package.json index 2bd6e6e..ce4e76c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pollum-io/pegasys-protocol", - "version": "0.0.16", + "version": "0.0.17", "description": "Contracts for the Pegasys Dex.", "main": "index.js", "keywords": [ From 54560de64b429b84a2c6715232ce398a0ff59ceb Mon Sep 17 00:00:00 2001 From: thomga Date: Mon, 16 Jan 2023 13:20:28 -0300 Subject: [PATCH 2/3] fix: permit logic on PegasysStaking deposit --- README.md | 2 +- contracts/earn/PegasysStaking.sol | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 07b98af..2578b34 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ TimeLock: `0x2C4ce5DcE61b22d9eed75136CD5C8bbd788A243B` GovernorAlpha: `0x633Bdeb5D4b5f93933833A692e230a7d48fC2d77` -PegasysStaking: `0xC46be9cC139f927483b895E60BFA2ECffDa4D8b2` +PegasysStaking: `0xD50b0beE43a5058efaF56b3703Cb1F97e3D127c6` ### Syscoin Tanenbaum Testnet: diff --git a/contracts/earn/PegasysStaking.sol b/contracts/earn/PegasysStaking.sol index c28df0d..9aec1f4 100644 --- a/contracts/earn/PegasysStaking.sol +++ b/contracts/earn/PegasysStaking.sol @@ -235,11 +235,9 @@ contract PegasysStaking is Ownable { s ); - psys.safeTransferFrom(_msgSender(), address(this), _amount); - internalPsysBalance = internalPsysBalance.add(_amountMinusFee); - - safeTokenTransfer(psys, _msgSender(), _fee); + psys.safeTransferFrom(_msgSender(), address(this), _amount); + safeTokenTransfer(psys, feeReceiver, _fee); emit Deposit(_msgSender(), _amountMinusFee, _fee); } From c065257636b516298e0df21703b526db8edf232b Mon Sep 17 00:00:00 2001 From: thomga Date: Tue, 17 Jan 2023 14:57:56 -0300 Subject: [PATCH 3/3] fix: logic on depositWithPermit --- README.md | 2 +- contracts/earn/FeeCollector.sol | 25 ++++++++++++++----------- contracts/earn/PegasysStaking.sol | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2578b34..d12f873 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ TimeLock: `0x2C4ce5DcE61b22d9eed75136CD5C8bbd788A243B` GovernorAlpha: `0x633Bdeb5D4b5f93933833A692e230a7d48fC2d77` -PegasysStaking: `0xD50b0beE43a5058efaF56b3703Cb1F97e3D127c6` +PegasysStaking: `0x1e6dc4CB2F98817A0E3D850Bba7aEfa3CFcdE55F` ### Syscoin Tanenbaum Testnet: diff --git a/contracts/earn/FeeCollector.sol b/contracts/earn/FeeCollector.sol index 7ed25e2..c50abed 100644 --- a/contracts/earn/FeeCollector.sol +++ b/contracts/earn/FeeCollector.sol @@ -35,7 +35,7 @@ contract FeeCollector is Ownable { EnumerableSet.AddressSet private _isAuth; modifier onlyAuth() { - require(_isAuth.contains(_msgSender()), "MoneyMaker: FORBIDDEN"); + require(_isAuth.contains(_msgSender()), "FeeCollector: FORBIDDEN"); _; } @@ -98,7 +98,7 @@ contract FeeCollector is Ownable { function addAuth(address _auth) external onlyOwner { require( _isAuth.add(_auth), - "MoneyMaker: Address is already authorized" + "FeeCollector: Address is already authorized" ); emit AddAuthorizedAddress(_auth); } @@ -106,7 +106,10 @@ contract FeeCollector is Ownable { /// @notice Remove a user of authorized addresses /// @param _auth The address to remove function removeAuth(address _auth) external onlyOwner { - require(_isAuth.remove(_auth), "MoneyMaker: Address is not authorized"); + require( + _isAuth.remove(_auth), + "FeeCollector: Address is not authorized" + ); emit RemoveAuthorizedAddress(_auth); } @@ -130,7 +133,7 @@ contract FeeCollector is Ownable { // Checks require( token != tokenTo && token != wsys && token != bridge, - "MoneyMaker: Invalid bridge" + "FeeCollector: Invalid bridge" ); // Effects @@ -185,7 +188,7 @@ contract FeeCollector is Ownable { // C6: It's not a fool proof solution, but it prevents flash loans, so here it's ok to use tx.origin modifier onlyEOA() { // Try to make flash-loan exploit harder to do by only allowing externally owned addresses. - require(_msgSender() == tx.origin, "MoneyMaker: must use EOA"); + require(_msgSender() == tx.origin, "FeeCollector: must use EOA"); _; } @@ -201,7 +204,7 @@ contract FeeCollector is Ownable { ) external onlyEOA onlyAuth { require( slippage < 5_000, - "MoneyMaker: slippage needs to be lower than 50%" + "FeeCollector: slippage needs to be lower than 50%" ); _convert(token0, token1, slippage); } @@ -219,11 +222,11 @@ contract FeeCollector is Ownable { // TODO: This can be optimized a fair bit, but this is safer and simpler for now require( slippage < 5_000, - "MoneyMaker: slippage needs to be lower than 50%" + "FeeCollector: slippage needs to be lower than 50%" ); require( token0.length == token1.length, - "MoneyMaker: arrays length don't match" + "FeeCollector: arrays length don't match" ); uint256 len = token0.length; @@ -251,7 +254,7 @@ contract FeeCollector is Ownable { amount1 = 0; } else { IPegasysPair pair = IPegasysPair(factory.getPair(token0, token1)); - require(address(pair) != address(0), "MoneyMaker: Invalid pair"); + require(address(pair) != address(0), "FeeCollector: Invalid pair"); IERC20(address(pair)).safeTransfer( address(pair), @@ -384,7 +387,7 @@ contract FeeCollector is Ownable { // Checks // X1 - X5: OK IPegasysPair pair = IPegasysPair(factory.getPair(fromToken, toToken)); - require(address(pair) != address(0), "MoneyMaker: Cannot convert"); + require(address(pair) != address(0), "FeeCollector: Cannot convert"); (uint256 reserve0, uint256 reserve1, ) = pair.getReserves(); (uint256 reserveInput, uint256 reserveOutput) = fromToken == @@ -413,7 +416,7 @@ contract FeeCollector is Ownable { reserveOutput, reserveInput ) >= amountInput.mul(rest).mul(rest).div(100_000_000), - "MoneyMaker: Slippage caught" + "FeeCollector: Slippage caught" ); } diff --git a/contracts/earn/PegasysStaking.sol b/contracts/earn/PegasysStaking.sol index 9aec1f4..0ca04cf 100644 --- a/contracts/earn/PegasysStaking.sol +++ b/contracts/earn/PegasysStaking.sol @@ -237,7 +237,7 @@ contract PegasysStaking is Ownable { internalPsysBalance = internalPsysBalance.add(_amountMinusFee); psys.safeTransferFrom(_msgSender(), address(this), _amount); - safeTokenTransfer(psys, feeReceiver, _fee); + psys.safeTransfer(feeReceiver, _fee); emit Deposit(_msgSender(), _amountMinusFee, _fee); }