Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions contracts/artifacts/abi/StakeTableV2.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "MAX_COMMISSION_BPS",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "MAX_METADATA_URI_LENGTH",
Expand Down
216 changes: 211 additions & 5 deletions contracts/rust/adapter/src/bindings/reward_claim.rs

Large diffs are not rendered by default.

216 changes: 211 additions & 5 deletions contracts/rust/adapter/src/bindings/stake_table_v2.rs

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions contracts/src/RewardClaim.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ contract RewardClaim is
/// intentional to ensure careful consideration and governance of security parameters.
uint256 public constant MAX_DAILY_LIMIT_BASIS_POINTS = 500; // 5%

/// @notice Basis points denominator (100% = 10000 bps)
uint256 public constant BPS_DENOMINATOR = 10000;

/// @notice Current day number (days since epoch)
uint256 private _currentDay;

Expand Down Expand Up @@ -156,7 +159,7 @@ contract RewardClaim is

// Set initial daily limit to 1% (100 basis points) of total supply
uint256 initialBps = 100; // 1%
uint256 _dailyLimit = (totalSupply * initialBps) / 10000;
uint256 _dailyLimit = (totalSupply * initialBps) / BPS_DENOMINATOR;
require(_dailyLimit > 0, ZeroDailyLimit());

__UUPSUpgradeable_init();
Expand Down Expand Up @@ -202,7 +205,7 @@ contract RewardClaim is
{
require(basisPoints > 0, ZeroDailyLimit());
require(basisPoints <= MAX_DAILY_LIMIT_BASIS_POINTS, DailyLimitTooHigh());
uint256 newLimit = (espToken.totalSupply() * basisPoints) / 10000;
uint256 newLimit = (espToken.totalSupply() * basisPoints) / BPS_DENOMINATOR;
require(newLimit > 0, ZeroDailyLimit());

// Due to computation based on current total supply, the new limit is very unlikely to be
Expand Down
13 changes: 9 additions & 4 deletions contracts/src/StakeTableV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ contract StakeTableV2 is StakeTable, PausableUpgradeable, AccessControlUpgradeab
/// @notice Maximum length for metadata URIs (in bytes)
uint256 public constant MAX_METADATA_URI_LENGTH = 2048;

/// @notice Maximum commission in basis points (100% = 10000 bps)
uint16 public constant MAX_COMMISSION_BPS = 10000;

/// @notice Minimum time interval between commission increases (in seconds)
uint256 public minCommissionIncreaseInterval;

Expand Down Expand Up @@ -588,7 +591,7 @@ contract StakeTableV2 is StakeTable, PausableUpgradeable, AccessControlUpgradeab
revert InvalidSchnorrSig();
}

if (commission > 10000) {
if (commission > MAX_COMMISSION_BPS) {
revert InvalidCommission();
}

Expand Down Expand Up @@ -654,7 +657,7 @@ contract StakeTableV2 is StakeTable, PausableUpgradeable, AccessControlUpgradeab
function updateCommission(uint16 newCommission) external virtual whenNotPaused {
address validator = msg.sender;
ensureValidatorActive(validator);
require(newCommission <= 10000, InvalidCommission());
require(newCommission <= MAX_COMMISSION_BPS, InvalidCommission());

CommissionTracking storage tracking = commissionTracking[validator];
uint16 currentCommission = tracking.commission;
Expand Down Expand Up @@ -726,7 +729,9 @@ contract StakeTableV2 is StakeTable, PausableUpgradeable, AccessControlUpgradeab
virtual
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(newMaxIncrease > 0 && newMaxIncrease <= 10000, InvalidRateLimitParameters());
require(
newMaxIncrease > 0 && newMaxIncrease <= MAX_COMMISSION_BPS, InvalidRateLimitParameters()
);
maxCommissionIncrease = newMaxIncrease;
emit MaxCommissionIncreaseUpdated(newMaxIncrease);
}
Expand All @@ -743,7 +748,7 @@ contract StakeTableV2 is StakeTable, PausableUpgradeable, AccessControlUpgradeab
address validator = initialCommissions[i].validator;
uint16 commission = initialCommissions[i].commission;

require(commission <= 10000, InvalidCommission());
require(commission <= MAX_COMMISSION_BPS, InvalidCommission());

ValidatorStatus status = validators[validator].status;
require(status != ValidatorStatus.Unknown, ValidatorInactive());
Expand Down
7 changes: 5 additions & 2 deletions contracts/test/MockStakeTableV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ contract MockStakeTableV2 is StakeTableV2 {

ensureValidatorNotRegistered(validator);
ensureNonZeroSchnorrKey(schnorrVK);
ensureNewKey(blsVK);
ensureNewKeys(blsVK, schnorrVK);

if (commission > 10000) {
if (commission > MAX_COMMISSION_BPS) {
revert InvalidCommission();
}

validateMetadataUri(metadataUri);

blsKeys[_hashBlsKey(blsVK)] = true;
schnorrKeys[_hashSchnorrKey(schnorrVK)] = true;
validators[validator] = Validator({ status: ValidatorStatus.Active, delegatedAmount: 0 });

// Store the initial commission for this validator
Expand Down
6 changes: 4 additions & 2 deletions contracts/test/RewardClaim/RewardClaim.Admin.Unit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ contract RewardClaimAdminTest is RewardClaimTest {
function test_SetDailyLimit_Success() public {
uint256 currentLimit = rewardClaim.dailyLimitWei();
uint256 basisPoints = 200; // 2%
uint256 expectedLimit = (espToken.totalSupply() * basisPoints) / 10000;
uint256 expectedLimit =
(espToken.totalSupply() * basisPoints) / rewardClaim.BPS_DENOMINATOR();

vm.prank(owner);
vm.expectEmit();
Expand Down Expand Up @@ -50,7 +51,8 @@ contract RewardClaimAdminTest is RewardClaimTest {
function test_SetDailyLimit_SuccessAtMaxBound() public {
uint256 currentLimit = rewardClaim.dailyLimitWei();
uint256 maxBasisPoints = rewardClaim.MAX_DAILY_LIMIT_BASIS_POINTS();
uint256 expectedLimit = (espToken.totalSupply() * maxBasisPoints) / 10000;
uint256 expectedLimit =
(espToken.totalSupply() * maxBasisPoints) / rewardClaim.BPS_DENOMINATOR();

vm.prank(owner);
vm.expectEmit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ contract RewardClaimHandler is RewardClaimTest {
uint256 maxBasisPoints = rewardClaim.MAX_DAILY_LIMIT_BASIS_POINTS();
uint256 basisPoints = _bound(limitSeed, 1, maxBasisPoints);

uint256 newLimit = (espToken.totalSupply() * basisPoints) / 10000;
uint256 newLimit = (espToken.totalSupply() * basisPoints) / rewardClaim.BPS_DENOMINATOR();
if (newLimit == rewardClaim.dailyLimitWei()) {
return;
}
Expand Down
16 changes: 14 additions & 2 deletions contracts/test/RewardClaim/RewardClaim.RateLimit.Unit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ contract RewardClaimRateLimitTest is RewardClaimMockTest {
checkLimitEnforced(claimer, DAILY_LIMIT + 1);

uint256 basisPoints = 200; // 2%
uint256 newLimit = (espToken.totalSupply() * basisPoints) / 10000;
uint256 newLimit = (espToken.totalSupply() * basisPoints) / rewardClaim.BPS_DENOMINATOR();
vm.prank(owner);
rewardClaim.setDailyLimit(basisPoints);

Expand All @@ -92,7 +92,7 @@ contract RewardClaimRateLimitTest is RewardClaimMockTest {
claim(DAILY_LIMIT);

uint256 basisPoints = 50; // 0.5%
uint256 newLimit = (espToken.totalSupply() * basisPoints) / 10000;
uint256 newLimit = (espToken.totalSupply() * basisPoints) / rewardClaim.BPS_DENOMINATOR();
vm.prank(owner);
rewardClaim.setDailyLimit(basisPoints);

Expand All @@ -118,4 +118,16 @@ contract RewardClaimRateLimitTest is RewardClaimMockTest {
vm.expectRevert();
rewardClaim.claimRewards(amount, "");
}

function test_BpsDenominator() public view {
assertEq(rewardClaim.BPS_DENOMINATOR(), 10000);
}

function test_DefaultDailyLimit() public view {
uint256 expectedBps = 100; // 1%
uint256 expectedLimit =
(espToken.totalSupply() * expectedBps) / rewardClaim.BPS_DENOMINATOR();
assertEq(rewardClaim.lastSetDailyLimitBasisPoints(), expectedBps);
assertEq(rewardClaim.dailyLimitWei(), expectedLimit);
}
}
3 changes: 2 additions & 1 deletion contracts/test/StakeTableV2Commission.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ contract StakeTableV2CommissionTest is Test {

function test_CommissionUpdate_DecreaseMaxDelta() public {
address validator = makeAddr("validator");
uint16 maxCommission = 10000;
uint16 maxCommission = proxy.MAX_COMMISSION_BPS();
stakeTableUpgradeTest.registerValidatorOnStakeTableV2(
validator, "123", maxCommission, proxy
);
Expand Down Expand Up @@ -218,6 +218,7 @@ contract StakeTableV2CommissionTest is Test {
// should fail
assertEq(proxy.minCommissionIncreaseInterval(), 7 days);
assertEq(proxy.maxCommissionIncrease(), 500);
assertEq(proxy.MAX_COMMISSION_BPS(), 10000);
}

function test_InitializeV2_RevertWhenInitialValidatorNotRegistered() public {
Expand Down