Skip to content

Commit

Permalink
SOV-2210 Merge latest development to master
Browse files Browse the repository at this point in the history
- LiquidityMining: set up to 100% liquid distribution  
- FeeSharingCollector: fix fallback function  
- Staking: re-introduce governance team vesting withdraw
  • Loading branch information
tjcloa authored Apr 10, 2023
2 parents f1d4dfc + 7081a54 commit 38bee07
Show file tree
Hide file tree
Showing 143 changed files with 56,339 additions and 5,380 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ cache
coverage
types
reports
tmp
tmp
deployment/deployments
5 changes: 3 additions & 2 deletions .github/workflows/cron.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Fees Scheduler
name: Fees Scheduler Protocol

on:
schedule:
- cron: "0 0 * * FRI"
- cron: "0 4 * * FRI"
workflow_dispatch:

jobs:
build:
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/cron_amm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Fees Scheduler AMM

on:
schedule:
- cron: "0 0 * * THU"
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Setup node.js
uses: actions/setup-node@v1
with:
node-version: "14.x"
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Cache compiler installations
uses: actions/cache@v2
with:
path: |
~/.solcx
~/.vvm
key: ${{ runner.os }}-compiler-cache

# - name: Set pip cache directory path
# id: pip-cache-dir-path
# run: |
# echo "::set-output name=dir::$(pip cache dir)"

# - name: Restore pip cache
# uses: actions/cache@v2
# id: pip-cache
# with:
# path: |
# ${{ steps.pip-cache-dir-path.outputs.dir }}
# key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
# restore-keys: |
# ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
# ${{ runner.os }}-pip-

- name: Install python dependencies
run: pip install -r requirements.txt

- name: Withdraw Fees
run: echo $REWARDS_CRON && brownie networks import network-config.yaml true && brownie run scripts/contractInteraction/rewards_cron_amm.py --network=rsk-mainnet
env:
REWARDS_CRON: 1
FEE_CLAIMER: ${{secrets.FEE_CLAIMER}}
2 changes: 2 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ jobs:
- name: Checking Formatting
run: npm run lint && npm run prettier && npm run prettier-check
- name: Running Test
env:
NODE_OPTIONS: "--max_old_space_size=4096"
run: npm run test
# - name: Increasing the memory
# run: export NODE_OPTIONS="--max-old-space-size=7168"
Expand Down
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ abi
*.md
types/
venv/
deployment/deployments
tmp/
15 changes: 12 additions & 3 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
{
"overrides": [
{
"files": ["*.sol", "*.js", "*.test.js", "*.json"],
"files": ["*.js", "*.test.js", "*.json"],
"options": {
"printWidth": 99,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always"
"bracketSpacing": true
}
},
{
"files": "*.sol",
"options": {
"printWidth": 99,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": true
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion HARDHAT_FORKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ contract('example forking tests', () => {
params: [
{
forking: {
jsonRpcUrl: "https://mainnet.sovryn.app/rpc",
jsonRpcUrl: "https://mainnet4.sovryn.app/rpc",
blockNumber: 4272658,
},
},
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ OR
brownie networks add rsk testnet host=https://public-node.testnet.rsk.co chainid=31
```

Note: If you want to work with mainnet, please use host as `wss://mainnet.sovryn.app/ws` and chainid as `30`
Note: If you want to work with mainnet, please use host as `wss://mainnet.sovryn.app/websocket` and chainid as `30`

3. Deploy contracts locally
1. Deploy contracts locally

```bash
brownie run deploy_everything.py
Expand Down
112 changes: 102 additions & 10 deletions contracts/farm/LiquidityMining.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,36 @@ contract LiquidityMining is ILiquidityMining, LiquidityMiningStorage {
/**
* @notice Sets unlocked immediately percent.
* @param _unlockedImmediatelyPercent The % which determines how much will be unlocked immediately.
* @dev @dev 10000 is 100%
* @dev 10000 is 100%
*/
function setUnlockedImmediatelyPercent(uint256 _unlockedImmediatelyPercent)
external
onlyAuthorized
{
require(
_unlockedImmediatelyPercent < 10000,
"Unlocked immediately percent has to be less than 10000."
_unlockedImmediatelyPercent <= 10000,
"Unlocked immediately percent has to be less than equal to 10000."
);
unlockedImmediatelyPercent = _unlockedImmediatelyPercent;
}

/**
* @notice Sets unlocked immediately percent overwrite for specific pool token.
* @param _poolToken the address of pool token
* @param _poolTokenUnlockedImmediatelyPercent The % which determines how much will be unlocked immediately.
* @dev 10000 is 100%
*/
function setPoolTokenUnlockedImmediatelyPercent(
address _poolToken,
uint256 _poolTokenUnlockedImmediatelyPercent
) external onlyAuthorized {
require(
_poolTokenUnlockedImmediatelyPercent <= 10000,
"Unlocked immediately percent has to be less than equal to 10000."
);
poolTokensUnlockedImmediatelyPercent[_poolToken] = _poolTokenUnlockedImmediatelyPercent;
}

/**
* @notice sets wrapper proxy contract
* @dev can be set to zero address to remove wrapper
Expand Down Expand Up @@ -496,7 +513,13 @@ contract LiquidityMining is ILiquidityMining, LiquidityMiningStorage {
uint256 poolId = i;
_claimReward(poolId, userAddress, false);
}
lockedSOV.withdrawAndStakeTokensFrom(userAddress);

if (
lockedSOV.getLockedBalance(userAddress) > 0 ||
lockedSOV.getUnlockedBalance(userAddress) > 0
) {
lockedSOV.withdrawAndStakeTokensFrom(userAddress);
}
}

/**
Expand Down Expand Up @@ -582,22 +605,32 @@ contract LiquidityMining is ILiquidityMining, LiquidityMiningStorage {
bool _isCheckingBalance
) internal {
uint256 userAccumulatedReward = _user.accumulatedReward;
/// @dev get unlock immediate percent of the pool token.
uint256 calculatedUnlockedImmediatelyPercent = calcUnlockedImmediatelyPercent(_poolToken);

/// @dev Transfer if enough SOV balance on this LM contract.
uint256 balance = SOV.balanceOf(address(this));
if (balance >= userAccumulatedReward) {
totalUsersBalance = totalUsersBalance.sub(userAccumulatedReward);
_user.accumulatedReward = 0;

/// @dev Instead of transferring the reward to the LP (user),
/// deposit it into lockedSOV vault contract, but first
/// @dev If calculatedUnlockedImmediatelyPercent is 100%, transfer the reward to the LP (user).
/// else, deposit it into lockedSOV vault contract, but first
/// SOV deposit must be approved to move the SOV tokens
/// from this LM contract into the lockedSOV vault.
require(SOV.approve(address(lockedSOV), userAccumulatedReward), "Approve failed");
lockedSOV.deposit(_userAddress, userAccumulatedReward, unlockedImmediatelyPercent);
if (calculatedUnlockedImmediatelyPercent == 10000) {
SOV.transfer(_userAddress, userAccumulatedReward);
} else {
require(SOV.approve(address(lockedSOV), userAccumulatedReward), "Approve failed");
lockedSOV.deposit(
_userAddress,
userAccumulatedReward,
calculatedUnlockedImmediatelyPercent
);

if (_isStakingTokens) {
lockedSOV.withdrawAndStakeTokensFrom(_userAddress);
if (_isStakingTokens) {
lockedSOV.withdrawAndStakeTokensFrom(_userAddress);
}
}

/// @dev Event log.
Expand Down Expand Up @@ -731,4 +764,63 @@ contract LiquidityMining is ILiquidityMining, LiquidityMiningStorage {
UserInfo memory ui = getUserInfo(_poolToken, _user);
return ui.amount;
}

/**
* @notice returns the accumulated liquid reward for the given user for each pool token
* @param _user the address of the user
*/
function getUserAccumulatedRewardToBePaidLiquid(address _user)
external
view
returns (uint256)
{
uint256 length = poolInfoList.length;
uint256 result;
for (uint256 i = 0; i < length; i++) {
address _poolToken = address(poolInfoList[i].poolToken);
uint256 calculatedUnlockedImmediatelyPercent =
calcUnlockedImmediatelyPercent(_poolToken);
result = result.add(
calculatedUnlockedImmediatelyPercent.mul(_getUserAccumulatedReward(i, _user)).div(
10000
)
);
}

return result;
}

/**
* @notice returns the accumulated vested reward for the given user for each pool token
* @param _user the address of the user
*/
function getUserAccumulatedRewardToBeVested(address _user) external view returns (uint256) {
uint256 length = poolInfoList.length;
uint256 result;
for (uint256 i = 0; i < length; i++) {
address _poolToken = address(poolInfoList[i].poolToken);
uint256 calculatedUnlockedImmediatelyPercent =
calcUnlockedImmediatelyPercent(_poolToken);
result = result.add(
(10000 - calculatedUnlockedImmediatelyPercent)
.mul(_getUserAccumulatedReward(i, _user))
.div(10000)
);
}

return result;
}

/**
* @dev calculate the unlocked immediate percentage of specific pool token
* use the poolTokensUnlockedImmediatelyPercent by default, if it is not set, then use the unlockedImmediatelyPercent
*/
function calcUnlockedImmediatelyPercent(address _poolToken) public view returns (uint256) {
uint256 poolTokenUnlockedImmediatelyPercent =
poolTokensUnlockedImmediatelyPercent[_poolToken];
return
poolTokenUnlockedImmediatelyPercent > 0
? poolTokenUnlockedImmediatelyPercent
: unlockedImmediatelyPercent;
}
}
3 changes: 3 additions & 0 deletions contracts/farm/LiquidityMiningStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,7 @@ contract LiquidityMiningStorage is AdminRole {
// The % which determines how much will be unlocked immediately.
/// @dev 10000 is 100%
uint256 public unlockedImmediatelyPercent;

/// @dev overwrite the unlockedImmediatelyPercent for specific token.
mapping(address => uint256) public poolTokensUnlockedImmediatelyPercent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,7 @@ contract FeeSharingCollector is
/* Functions */

/// @dev fallback function to support rbtc transfer when unwrap the wrbtc.
function() external payable {
require(
msg.sender == address(protocol.wrbtcToken()),
"FeeSharingCollector::fallback: only wRBTC token calls allowed"
);
}
function() external payable {}

/**
* @notice Withdraw fees for the given token:
Expand Down
23 changes: 23 additions & 0 deletions contracts/governance/Staking/interfaces/IStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,29 @@ interface IStaking {
address receiver
) external;

/**
* @notice Withdraw the given amount of tokens.
* @param amount The number of tokens to withdraw.
* @param until The date until which the tokens were staked.
* @param receiver The receiver of the tokens. If not specified, send to the msg.sender
* @dev Can be invoked only by whitelisted contract passed to governanceWithdrawVesting
* @dev **WARNING** This function should not be no longer used by Sovryn Protocol.
* Sovryn protocol will use the cancelTeamVesting function for the withdrawal moving forward.
* */
function governanceWithdraw(
uint96 amount,
uint256 until,
address receiver
) external;

/**
* @notice Withdraw tokens for vesting contract.
* @param vesting The address of Vesting contract.
* @param receiver The receiver of the tokens. If not specified, send to the msg.sender
* @dev Can be invoked only by whitelisted contract passed to governanceWithdrawVesting.
* */
function governanceWithdrawVesting(address vesting, address receiver) external;

/**
* @notice Get available and punished amount for withdrawing.
* @param amount The number of tokens to withdraw.
Expand Down
10 changes: 6 additions & 4 deletions contracts/governance/Staking/modules/StakingVestingModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ contract StakingVestingModule is IFunctionsList, StakingShared {
);

// locked date must not exceed the MAX_DURATION
require(
lockedTS - block.timestamp <= MAX_DURATION,
"Invalid lock dates: exceed max duration"
);
if (lockedTS > block.timestamp) {
require(
lockedTS - block.timestamp <= MAX_DURATION,
"Invalid lock dates: exceed max duration"
);
}

// the value must not exceed the total staked at the given locked date
uint32 nStakeCheckpoints = numTotalStakingCheckpoints[lockedTS];
Expand Down
Loading

0 comments on commit 38bee07

Please sign in to comment.