Skip to content

Commit

Permalink
Merge pull request #161 from futureversecom/SM-118-staking-power
Browse files Browse the repository at this point in the history
SM-118 Staking Power
  • Loading branch information
teinnt authored Feb 20, 2024
2 parents dfaca97 + ea6f0cf commit 7656d31
Show file tree
Hide file tree
Showing 27 changed files with 821 additions and 226 deletions.
8 changes: 8 additions & 0 deletions common/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const DeployedContractNames = {
rewardsManager: 'RewardsManager',
directory: 'Directory',
syloTicketing: 'SyloTicketing',
seekerPowerOracle: 'SeekerPowerOracle',
};

export const ContractNames = {
Expand Down Expand Up @@ -48,6 +49,7 @@ export type ContractAddresses = {
directory: string;
syloTicketing: string;
seekers: string;
seekerPowerOracle: string;
futurepassRegistrar: string;
};

Expand Down Expand Up @@ -105,6 +107,11 @@ export function connectContracts(
provider,
);

const seekerPowerOracle = factories.SeekerPowerOracle__factory.connect(
contracts.seekerPowerOracle,
provider,
);

const futurepassRegistrar =
factories.TestFuturepassRegistrar__factory.connect(
contracts.futurepassRegistrar,
Expand All @@ -122,6 +129,7 @@ export function connectContracts(
directory,
syloTicketing,
seekers,
seekerPowerOracle,
futurepassRegistrar,
};
}
20 changes: 10 additions & 10 deletions contracts/Registries.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ contract Registries is IRegistries, Initializable, Ownable2StepUpgradeable, IERC
* that will be allocated to the Node's stakers. This is global, and is
* currently set for all Nodes.
*/
uint16 public defaultPayoutPercentage;
uint32 public defaultPayoutPercentage;

event DefaultPayoutPercentageUpdated(uint16 defaultPayoutPercentage);
event DefaultPayoutPercentageUpdated(uint32 defaultPayoutPercentage);

error NonceCannotBeReused();
error EndMustBeGreaterThanStart();
error PercentageCannotExceed10000();
error PercentageCannotExceed100000();
error PublicEndpointCannotBeEmpty();
error SeekerAccountMustOwnSeekerId();
error SeekerAccountMustBeMsgSender();
Expand All @@ -68,13 +68,13 @@ contract Registries is IRegistries, Initializable, Ownable2StepUpgradeable, IERC

function initialize(
IERC721 rootSeekers,
uint16 _defaultPayoutPercentage
uint32 _defaultPayoutPercentage
) external initializer {
if (address(rootSeekers) == address(0)) {
revert RootSeekersCannotBeZeroAddress();
}
if (_defaultPayoutPercentage > 10000) {
revert PercentageCannotExceed10000();
if (_defaultPayoutPercentage > 100000) {
revert PercentageCannotExceed100000();
}

Ownable2StepUpgradeable.__Ownable2Step_init();
Expand All @@ -95,11 +95,11 @@ contract Registries is IRegistries, Initializable, Ownable2StepUpgradeable, IERC
* @notice Set the global default payout percentage value. Only callable
* by the owner.
* @param _defaultPayoutPercentage The payout percentage as a value where the
* denominator is 10000.
* denominator is 100000.
*/
function setDefaultPayoutPercentage(uint16 _defaultPayoutPercentage) external onlyOwner {
if (_defaultPayoutPercentage > 10000) {
revert PercentageCannotExceed10000();
function setDefaultPayoutPercentage(uint32 _defaultPayoutPercentage) external onlyOwner {
if (_defaultPayoutPercentage > 100000) {
revert PercentageCannotExceed100000();
}

defaultPayoutPercentage = _defaultPayoutPercentage;
Expand Down
16 changes: 15 additions & 1 deletion contracts/SeekerPowerOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

import "./interfaces/ISeekerPowerOracle.sol";

Expand All @@ -13,7 +14,7 @@ import "./interfaces/ISeekerPowerOracle.sol";
* a Seeker's power level via a restricted oracle account call. Seeker Power can also
* be set by any account if the correct Oracle signature proof is provided.
*/
contract SeekerPowerOracle is ISeekerPowerOracle, Initializable, Ownable2StepUpgradeable {
contract SeekerPowerOracle is ISeekerPowerOracle, Initializable, Ownable2StepUpgradeable, ERC165 {
/**
* @notice The oracle account. This contract accepts any attestations of
* Seeker power that have been signed by this account.
Expand All @@ -36,13 +37,26 @@ contract SeekerPowerOracle is ISeekerPowerOracle, Initializable, Ownable2StepUpg
error UnauthorizedRegisterSeekerPowerCall();
error NonceCannotBeReused();
error PowerCannotBeZero();
error OracleCannotBeZeroAddress();

function initialize(address _oracle) external initializer {
Ownable2StepUpgradeable.__Ownable2Step_init();

if (_oracle == address(0)) {
revert OracleCannotBeZeroAddress();
}

oracle = _oracle;
}

/**
* @notice Returns true if the contract implements the interface defined by
* `interfaceId` from ERC165.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(ISeekerPowerOracle).interfaceId;
}

/**
* @notice Sets the oracle account.
* @param _oracle The oracle account.
Expand Down
4 changes: 2 additions & 2 deletions contracts/epochs/EpochsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ contract EpochsManager is IEpochsManager, Initializable, Ownable2StepUpgradeable
uint128 baseLiveWinProb,
uint128 expiredWinProb,
uint256 ticketDuration,
uint16 decayRate
uint32 decayRate
) = _ticketingParameters.getTicketingParameters();

uint256 nextEpochId = getNextEpochId();
Expand Down Expand Up @@ -232,7 +232,7 @@ contract EpochsManager is IEpochsManager, Initializable, Ownable2StepUpgradeable
activeSeekers[nextEpoch][seekerId] = msg.sender;

_directory._rewardsManager().initializeNextRewardPool(msg.sender);
_directory.joinNextDirectory(msg.sender);
_directory.joinNextDirectory(msg.sender, seekerId);

emit EpochJoined(nextEpoch, msg.sender, seekerId);
}
Expand Down
6 changes: 3 additions & 3 deletions contracts/interfaces/IRegistries.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pragma solidity ^0.8.18;
interface IRegistries {
struct Registry {
// Percentage of a tickets value that will be rewarded to
// delegated stakers expressed as a fraction of 10000.
// delegated stakers expressed as a fraction of 100000.
// This value is currently locked to the default payout percentage
// until epochs are implemented.
uint16 payoutPercentage;
uint32 payoutPercentage;
// Public http/s endpoint to retrieve additional metadata
// about the node.
// The current metadata schema is as follows:
Expand All @@ -23,7 +23,7 @@ interface IRegistries {

function register(string calldata publicEndpoint) external;

function setDefaultPayoutPercentage(uint16 _defaultPayoutPercentage) external;
function setDefaultPayoutPercentage(uint32 _defaultPayoutPercentage) external;

function setSeekerAccount(
address seekerAccount,
Expand Down
4 changes: 2 additions & 2 deletions contracts/interfaces/epochs/IEpochsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ interface IEpochsManager {
// Zero here represents the epoch has not yet ended.

// registry variables
uint16 defaultPayoutPercentage;
uint32 defaultPayoutPercentage;
// ticketing variables
uint16 decayRate;
uint32 decayRate;
uint256 faceValue;
uint128 baseLiveWinProb;
uint128 expiredWinProb;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ interface ITicketingParameters {

function setExpiredWinProb(uint128 _expiredWinProb) external;

function setDecayRate(uint16 _decayRate) external;
function setDecayRate(uint32 _decayRate) external;

function setTicketDuration(uint256 _ticketDuration) external;

function getTicketingParameters()
external
view
returns (uint256, uint128, uint128, uint256, uint16);
returns (uint256, uint128, uint128, uint256, uint32);
}
2 changes: 1 addition & 1 deletion contracts/interfaces/staking/IDirectory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface IDirectory {

function setCurrentDirectory(uint256 epochId) external;

function joinNextDirectory(address stakee) external;
function joinNextDirectory(address stakee, uint256 seekerId) external;

function scan(uint128 point) external view returns (address stakee);

Expand Down
4 changes: 3 additions & 1 deletion contracts/interfaces/staking/IStakingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ interface IStakingManager {

function setUnlockDuration(uint256 _unlockDuration) external;

function setMinimumStakeProportion(uint16 _minimumStakeProportion) external;
function setMinimumStakeProportion(uint32 _minimumStakeProportion) external;

function addStake(uint256 amount, address stakee) external;

Expand All @@ -49,6 +49,8 @@ interface IStakingManager {

function cancelUnlocking(uint256 amount, address stakee) external;

function calculateCapacityFromSeekerPower(uint256 seekerId) external view returns (uint256);

function calculateMaxAdditionalDelegatedStake(address stakee) external view returns (uint256);

function getTotalManagedStake() external view returns (uint256);
Expand Down
21 changes: 13 additions & 8 deletions contracts/libraries/SyloUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,24 @@ error TargetNotSupportInterface(string name, bytes4 interfaceId);

library SyloUtils {
/**
* @dev Percentages are expressed as a ratio where 10000 is the denominator.
* @dev The maximum possible SYLO that exists in the network.
*/
uint256 public constant MAX_SYLO = 10_000_000_000 ether;

/**
* @dev Percentages are expressed as a ratio where 100000 is the denominator.
* A large denominator allows for more precision, e.g representing 12.5%
* can be done as 1250 / 10000
* can be done as 12500 / 100000
*/
uint16 public constant PERCENTAGE_DENOMINATOR = 10000;
uint32 public constant PERCENTAGE_DENOMINATOR = 100000;

/**
* @dev Multiply a value by a given percentage. Converts the provided
* uint128 value to uint256 to avoid any reverts on overflow.
* @param value The value to multiply.
* @param percentage The percentage, as a ratio of 10000.
* @param percentage The percentage, as a ratio of 100000.
*/
function percOf(uint128 value, uint16 percentage) internal pure returns (uint256) {
function percOf(uint128 value, uint32 percentage) internal pure returns (uint256) {
return (uint256(value) * percentage) / PERCENTAGE_DENOMINATOR;
}

Expand All @@ -32,10 +37,10 @@ library SyloUtils {
* @param numerator The numerator limited to a uint128 value to prevent
* phantom overflow.
* @param denominator The denominator.
* @return The percentage, as a ratio of 10000.
* @return The percentage, as a ratio of 100000.
*/
function asPerc(uint128 numerator, uint256 denominator) internal pure returns (uint16) {
return SafeCast.toUint16((uint256(numerator) * PERCENTAGE_DENOMINATOR) / denominator);
function asPerc(uint128 numerator, uint256 denominator) internal pure returns (uint32) {
return SafeCast.toUint32((uint256(numerator) * PERCENTAGE_DENOMINATOR) / denominator);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions contracts/mocks/TestSyloUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pragma solidity ^0.8.18;
import "../libraries/SyloUtils.sol";

contract TestSyloUtils {
function percOf(uint128 value, uint16 percentage) public pure returns (uint256) {
function percOf(uint128 value, uint32 percentage) public pure returns (uint256) {
return SyloUtils.percOf(value, percentage);
}

function asPerc(uint128 numerator, uint256 denominator) public pure returns (uint16) {
function asPerc(uint128 numerator, uint256 denominator) public pure returns (uint32) {
return SyloUtils.asPerc(numerator, denominator);
}

Expand Down
12 changes: 6 additions & 6 deletions contracts/payments/ticketing/TicketingParameters.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ contract TicketingParameters is
* probability that will be decayed once a ticket has expired.
* Example: 80% decayRate indicates that a ticket will decay down to 20% of its
* base win probability upon reaching the block before its expiry.
* The value is expressed as a fraction of 10000.
* The value is expressed as a fraction of 100000.
*/
uint16 public decayRate;
uint32 public decayRate;

event FaceValueUpdated(uint256 faceValue);
event BaseLiveWinProbUpdated(uint128 baseLiveWinprob);
event ExpiredWinProbUpdated(uint128 expiredWinProb);
event TicketDurationUpdated(uint256 ticketDuration);
event DecayRateUpdated(uint16 decayRate);
event DecayRateUpdated(uint32 decayRate);

error FaceValueCannotBeZero();
error TicketDurationCannotBeZero();
Expand All @@ -67,7 +67,7 @@ contract TicketingParameters is
uint256 _faceValue,
uint128 _baseLiveWinProb,
uint128 _expiredWinProb,
uint16 _decayRate,
uint32 _decayRate,
uint256 _ticketDuration
) external initializer {
if (_faceValue == 0) {
Expand Down Expand Up @@ -136,7 +136,7 @@ contract TicketingParameters is
* @param _decayRate The decay rate as a percentage, where the
* denominator is 10000.
*/
function setDecayRate(uint16 _decayRate) external onlyOwner {
function setDecayRate(uint32 _decayRate) external onlyOwner {
decayRate = _decayRate;
emit DecayRateUpdated(_decayRate);
}
Expand Down Expand Up @@ -166,7 +166,7 @@ contract TicketingParameters is
function getTicketingParameters()
external
view
returns (uint256, uint128, uint128, uint256, uint16)
returns (uint256, uint128, uint128, uint256, uint32)
{
return (faceValue, baseLiveWinProb, expiredWinProb, ticketDuration, decayRate);
}
Expand Down
Loading

0 comments on commit 7656d31

Please sign in to comment.