Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SM-118 Staking Power #161

Merged
merged 10 commits into from
Feb 20, 2024
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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update the comment above too. Also comments in percOf, asPerc, setDecayRate, minimumStakeProportion.

* denominator is 100000.

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
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

Check warning on line 4 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts/token/ERC721/IERC721.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 4 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts/token/ERC721/IERC721.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

Check warning on line 5 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts/utils/introspection/ERC165.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 5 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts/utils/introspection/ERC165.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";

Check warning on line 6 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 6 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

Check warning on line 7 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 7 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

import "../Registries.sol";

Check warning on line 9 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path ../Registries.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 9 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path ../Registries.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "../staking/Directory.sol";

Check warning on line 10 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path ../staking/Directory.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

Check warning on line 10 in contracts/epochs/EpochsManager.sol

View workflow job for this annotation

GitHub Actions / build

global import of path ../staking/Directory.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "../interfaces/epochs/IEpochsManager.sol";
import "../payments/ticketing/TicketingParameters.sol";

Expand Down Expand Up @@ -142,7 +142,7 @@
uint128 baseLiveWinProb,
uint128 expiredWinProb,
uint256 ticketDuration,
uint16 decayRate
uint32 decayRate
) = _ticketingParameters.getTicketingParameters();

uint256 nextEpochId = getNextEpochId();
Expand Down Expand Up @@ -232,7 +232,7 @@
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
Loading