Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshowlett977 committed Aug 27, 2021
2 parents 71d15dd + b4b73a5 commit 51f8507
Show file tree
Hide file tree
Showing 13 changed files with 450 additions and 102 deletions.
15 changes: 12 additions & 3 deletions contracts/governance/Staking/WeightedStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ contract WeightedStaking is Checkpoints {
* @return The number of votes the account had as of the given block.
* */
function getPriorTotalStakesForDate(uint256 date, uint256 blockNumber) public view returns (uint96) {
require(blockNumber < block.number, "WeightedStaking::getPriorTotalStakesForDate: not yet determined");
require(blockNumber < _getCurrentBlockNumber(), "WeightedStaking::getPriorTotalStakesForDate: not yet determined");

uint32 nCheckpoints = numTotalStakingCheckpoints[date];
if (nCheckpoints == 0) {
Expand Down Expand Up @@ -173,7 +173,7 @@ contract WeightedStaking is Checkpoints {
uint256 date,
uint256 blockNumber
) public view returns (uint96) {
require(blockNumber < block.number, "WeightedStaking::getPriorStakeByDateForDelegatee: not yet determined");
require(blockNumber < _getCurrentBlockNumber(), "WeightedStaking::getPriorStakeByDateForDelegatee: not yet determined");

uint32 nCheckpoints = numDelegateStakingCheckpoints[account][date];
if (nCheckpoints == 0) {
Expand Down Expand Up @@ -299,7 +299,7 @@ contract WeightedStaking is Checkpoints {
uint256 date,
uint256 blockNumber
) internal view returns (uint96) {
require(blockNumber < block.number, "WeightedStaking::getPriorUserStakeAndDate: not yet determined");
require(blockNumber < _getCurrentBlockNumber(), "WeightedStaking::getPriorUserStakeAndDate: not yet determined");

date = _adjustDateForOrigin(date);
uint32 nCheckpoints = numUserStakingCheckpoints[account][date];
Expand Down Expand Up @@ -333,6 +333,15 @@ contract WeightedStaking is Checkpoints {
return userStakingCheckpoints[account][date][lower].stake;
}

/**
* @notice Determine the current Block Number
* @dev This is segregated from the _getPriorUserStakeByDate function to better test
* advancing blocks functionality using Mock Contracts
* */
function _getCurrentBlockNumber() internal view returns (uint256) {
return block.number;
}

/**************** SHARED FUNCTIONS *********************/

/**
Expand Down
54 changes: 31 additions & 23 deletions contracts/governance/StakingRewards/StakingRewards.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ contract StakingRewards is StakingRewardsStorage, Initializable {
require(Address.isContract(_SOV), "_SOV not a contract");
SOV = IERC20(_SOV);
staking = _staking;
startTime = block.timestamp;
setMaxDuration(26 * TWO_WEEKS);
startTime = staking.timestampToLockDate(block.timestamp);
setMaxDuration(15 * TWO_WEEKS);
deploymentBlock = _getCurrentBlockNumber();
}

/**
Expand All @@ -48,7 +49,7 @@ contract StakingRewards is StakingRewardsStorage, Initializable {
* */
function stop() external onlyOwner {
require(stopBlock == 0, "Already stopped");
stopBlock = block.number;
stopBlock = _getCurrentBlockNumber();
}

/**
Expand Down Expand Up @@ -120,8 +121,6 @@ contract StakingRewards is StakingRewardsStorage, Initializable {
* @param _receiverAddress The address where the tokens has to be transferred.
*/
function withdrawTokensByOwner(address _receiverAddress) external onlyOwner {
require(_receiverAddress != address(0), "receiver address invalid");

uint256 value = SOV.balanceOf(address(this));
_transferSOV(_receiverAddress, value);
}
Expand All @@ -132,7 +131,6 @@ contract StakingRewards is StakingRewardsStorage, Initializable {
* @param _amount the amount to be transferred
*/
function _transferSOV(address _receiver, uint256 _amount) internal {
require(_receiver != address(0), "receiver address invalid");
require(_amount != 0, "amount invalid");
require(SOV.transfer(_receiver, _amount), "transfer failed");
emit RewardWithdrawn(_receiver, _amount);
Expand All @@ -146,34 +144,44 @@ contract StakingRewards is StakingRewardsStorage, Initializable {
* @return The timestamp of last withdrawal
* @return The accumulated reward
*/
function getStakerCurrentReward(bool considerMaxDuration) public view returns (uint256 withdrawalTime, uint256 amount) {
uint256 count;
function getStakerCurrentReward(bool considerMaxDuration) public view returns (uint256 lastWithdrawalInterval, uint256 amount) {
uint256 weightedStake;
uint256 lastFinalisedBlock = block.number - 1;
uint256 lastFinalisedBlock = _getCurrentBlockNumber() - 1;
uint256 currentTS = block.timestamp;
address staker = msg.sender;
uint256 addedMaxDuration;
uint256 duration;
if (withdrawals[staker] == 0) {
require((currentTS.sub(startTime)) > TWO_WEEKS, "allowed after 14 days of start");
withdrawalTime = startTime;
} else {
require(currentTS > withdrawals[staker], "allowed after 14 days");
withdrawalTime = withdrawals[staker];
}
uint256 referenceBlock;
address staker = msg.sender;
uint256 lastWithdrawal = withdrawals[staker];

uint256 lastStakingInterval = staking.timestampToLockDate(currentTS);
lastWithdrawalInterval = lastWithdrawal > 0 ? lastWithdrawal : startTime;
if (lastStakingInterval < lastWithdrawalInterval) return (0, 0);

if (considerMaxDuration) {
duration = maxDuration;
addedMaxDuration = lastWithdrawalInterval.add(maxDuration);
duration = addedMaxDuration < currentTS ? staking.timestampToLockDate(addedMaxDuration) : lastStakingInterval;
} else {
duration = currentTS;
duration = lastStakingInterval;
}

for (uint256 i = withdrawalTime; i <= currentTS && i <= withdrawalTime.add(duration); i += TWO_WEEKS) {
count++;
weightedStake = weightedStake.add(_computeRewardForDate(staker, lastFinalisedBlock, i));
for (uint256 i = lastWithdrawalInterval; i < duration; i += TWO_WEEKS) {
referenceBlock = lastFinalisedBlock.sub(((currentTS.sub(i)).div(30)));
if (referenceBlock < deploymentBlock) referenceBlock = deploymentBlock;
weightedStake = weightedStake.add(_computeRewardForDate(staker, referenceBlock, i));
}

if (weightedStake == 0) return (0, 0);
withdrawalTime += count.mul(TWO_WEEKS);
lastWithdrawalInterval = duration;
amount = weightedStake.mul(BASE_RATE).div(DIVISOR);
}

/**
* @notice Determine the current Block Number
* @dev This is segregated from the _getPriorUserStakeByDate function to better test
* advancing blocks functionality using Mock Contracts
* */
function _getCurrentBlockNumber() internal view returns (uint256) {
return block.number;
}
}
9 changes: 6 additions & 3 deletions contracts/governance/StakingRewards/StakingRewardsStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ contract StakingRewardsStorage is Ownable {
IStaking public staking;

/// @notice 2 weeks in seconds.
uint256 constant TWO_WEEKS = 1209600;
uint256 public constant TWO_WEEKS = 1209600;

/// @notice Annual Base Rate - it is the maximum interest rate(APY)
uint256 constant BASE_RATE = 2975;
uint256 public constant BASE_RATE = 2975;

/// @notice DIVISOR is set as 2600000 = 26 (num periods per year) * 10 (max voting weight) * 10000 (2975 -> 0.2975)
uint256 constant DIVISOR = 2600000;
uint256 public constant DIVISOR = 2600000;

/// @notice Maximum duration to collect rewards at one go
uint256 public maxDuration;
Expand All @@ -45,4 +45,7 @@ contract StakingRewardsStorage is Ownable {

/// @notice User Address -> Claimed Balance
mapping(address => uint256) public claimedBalances;

/// @notice Represents the block when the StakingRwards Program is started
uint256 public deploymentBlock;
}
24 changes: 24 additions & 0 deletions contracts/mockup/BlockMockUp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pragma solidity 0.5.17;

/**
* @title Used to get and set mock block number.
*/
contract BlockMockUp {
uint256 public blockNum;

/**
* @notice To get the `blockNum`.
* @return _blockNum The block number.
*/
function getBlockNum() public view returns (uint256 _blockNum) {
return blockNum;
}

/**
* @notice To set the `blockNum`.
* @param _blockNum The block number.
*/
function setBlockNum(uint256 _blockNum) public {
blockNum = _blockNum;
}
}
25 changes: 25 additions & 0 deletions contracts/mockup/StakingMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
pragma solidity ^0.5.17;

import "../governance/Staking/Staking.sol";
import "./BlockMockUp.sol";

contract StakingMock is Staking {
///@notice the block mock up contract
BlockMockUp public blockMockUp;

/**
* @notice gets block number from BlockMockUp
* @param _blockMockUp the address of BlockMockUp
*/
function setBlockMockUpAddr(address _blockMockUp) public onlyOwner {
require(_blockMockUp != address(0), "block mockup address invalid");
blockMockUp = BlockMockUp(_blockMockUp);
}

/**
* @notice Determine the current Block Number from BlockMockUp
* */
function _getCurrentBlockNumber() internal view returns (uint256) {
return blockMockUp.getBlockNum();
}
}
31 changes: 31 additions & 0 deletions contracts/mockup/StakingRewardsMockUp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
pragma solidity ^0.5.17;

import "../governance/StakingRewards/StakingRewards.sol";
import "./BlockMockUp.sol";

/**
* @title Staking Rewards Contract MockUp
* @notice This is used for Testing
* */
contract StakingRewardsMockUp is StakingRewards {
///@notice the block mock up contract
BlockMockUp public blockMockUp;

using SafeMath for uint256;

/**
* @notice gets block number from BlockMockUp
* @param _blockMockUp the address of BlockMockUp
*/
function setBlockMockUpAddr(address _blockMockUp) public onlyOwner {
require(_blockMockUp != address(0), "block mockup address invalid");
blockMockUp = BlockMockUp(_blockMockUp);
}

/**
* @notice Determine the current Block Number from BlockMockUp
* */
function _getCurrentBlockNumber() internal view returns (uint256) {
return blockMockUp.getBlockNum();
}
}
1 change: 0 additions & 1 deletion scripts/contractInteraction/contract_interaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,3 @@ def main():
conf.loadConfig()

#call the function you want here

5 changes: 4 additions & 1 deletion scripts/contractInteraction/mainnet_contracts.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,8 @@

"BridgeRSK": "0x1CcAd820B6d031B41C54f1F3dA11c0d48b399581",
"Aggregator-ETH-RSK": "0x4bF113905d7F69202106f613308bb02c84aaDF2F",
"RSK-ETHes": "0xFe878227c8F334038DAb20a99fC3B373fFe0a755"
"RSK-ETHes": "0xFe878227c8F334038DAb20a99fC3B373fFe0a755",

"StakingRewardsProxy": "0x8304FB3614c728B712e94F9D4DF6719fede6517F",
"StakingRewards": "0xbE3044cf732ff952DA518Bd8c58907798DDf0aA2"
}
4 changes: 3 additions & 1 deletion scripts/contractInteraction/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,6 @@ def lookupCurrentPoolReserveBalances(userAddress):
print('user balance ', userBal)

print('user has in SOV', userBal/poolSupply * sovBal)
print('user has in BTC', userBal/poolSupply * wrbtcBal)
print('user has in BTC', userBal/poolSupply * wrbtcBal)


6 changes: 4 additions & 2 deletions scripts/contractInteraction/testnet_contracts.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@
"Aggregator-ETH-RSK": "0x04D92DaA8f3Ef7bD222195e8D1DbE8D89A8CebD3",

"OracleV1Pool-WRBTC/SOV": "0x28A05da0939853F7Bc9D5A17C9550D2769eE93D3",
"StakingRewardsProxy": "0x38424A525a35089388065f050008866631128182",
"StakingRewards": "0x5B7dda87074F12244a7AD19Dd40B02Bd62bC9511"

"WatcherContract": "0x3583155D5e87491dACDc15f7D0032C12D5D0ece0",
"StakingRewardsProxy": "0x18eF0ff12f1b4D30104B4680D485D026C26D164D",
"StakingRewards": "0xd2F9a3c1b9B71BBdA7Bb6B6D1741BA29654F571d"
}
11 changes: 8 additions & 3 deletions scripts/contractInteraction/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ def getBalance(contractAddress, acct):
print(balance)
return balance

def buyWRBTC():
def buyWRBTC(amount):
contract = Contract.from_abi("WRBTC", address=conf.contracts["WRBTC"], abi=WRBTC.abi, owner=conf.acct)
tx = contract.deposit({'value':1e18})
tx = contract.deposit({'value':amount})
tx.info()
print("New balance: ", contract.balanceOf(conf.acct))

Expand All @@ -35,7 +35,12 @@ def transferTokensFromWallet(tokenContract, receiver, amount):
token = Contract.from_abi("Token", address= tokenContract, abi = TestToken.abi, owner=conf.acct)
token.transfer(receiver, amount)

def sendToWatcher(tokenAddress, amount):
if(tokenAddress == conf.contracts['WRBTC']):
buyWRBTC(amount)
transferTokensFromWallet(conf.contracts['WRBTC'], conf.contracts['WatcherContract'], amount)

def approveFromMS(tokenContract, receiver, amount):
token = Contract.from_abi("Token", address= tokenContract, abi = TestToken.abi, owner=conf.acct)
data = token.approve.encode_input(receiver, amount)
sendWithMultisig(conf.contracts['multisig'], tokenContract, data, conf.acct)
sendWithMultisig(conf.contracts['multisig'], tokenContract, data, conf.acct)
Loading

0 comments on commit 51f8507

Please sign in to comment.