Skip to content

Commit

Permalink
update calculateUnlockRewards
Browse files Browse the repository at this point in the history
change calculateUnlockRewards params to receive an AludelData storage pointer and
a timestamp.

update gas-snapshot

Replace calculateUnlockRewards signature in IAludelV3
  • Loading branch information
itirabasso committed Jan 25, 2023
1 parent a96f5e1 commit f637188
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 158 deletions.
10 changes: 5 additions & 5 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ AludelFactoryTest:test_WHEN_launching_with_a_disabled_template_THEN_it_reverts()
AludelFactoryTest:test_WHEN_setting_a_different_fee_bps_and_recipient_THEN_its_passed_to_new_aludels() (gas: 663702)
AludelFactoryTest:test_WHEN_updating_a_program_with_empty_fields_THEN_it_isnt_updated() (gas: 69945)
AludelFactoryTest:test_WHEN_updating_an_unlisted_template_THEN_it_reverts() (gas: 22449)
AludelFactoryIntegrationTest:test_many_users_multiple_stakes() (gas: 1712688)
AludelFactoryIntegrationTest:test_stake() (gas: 413356)
AludelFactoryIntegrationTest:test_unstake() (gas: 457312)
AludelFactoryIntegrationTest:test_many_users_multiple_stakes() (gas: 1718998)
AludelFactoryIntegrationTest:test_stake() (gas: 413334)
AludelFactoryIntegrationTest:test_unstake() (gas: 458889)
AludelV3Test:test_aludel_stake_invalid_permission() (gas: 459631)
AludelV3Test:test_aludel_stake_not_enough_balance() (gas: 594655)
AludelV3Test:test_funding_shares() (gas: 861909)
AludelV3Test:test_funding_shares() (gas: 777083)
AludelV3Test:test_stakes_invalid_vault() (gas: 6238312)
AludelV3Test:test_stakes_max_stakes_reached() (gas: 3078097)
AludelV3Test:test_stakes_no_amount_staked() (gas: 256169)
AludelV3Test:test_stakes_total_stakes_units_calculations() (gas: 773105)
AludelV3Test:test_stakes_total_stakes_units_calculations() (gas: 773017)
AludelV3LibTest:test_calculateNewShares_no_previous_shares(uint128,uint128,uint128) (runs: 256, μ: 4498, ~: 4498)
AludelV3LibTest:test_calculateNewShares_with_previous_shares(uint128,uint128,uint128) (runs: 256, μ: 5347, ~: 5347)
AludelV3LibTest:test_calculateSharesLocked(uint128,uint16) (runs: 256, μ: 280185, ~: 280185)
Expand Down
27 changes: 5 additions & 22 deletions src/contracts/aludel/AludelV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -314,23 +314,11 @@ contract AludelV3 is IAludelV3, Ownable, Initializable, Powered {
return AludelV3Lib.calculateStakeUnits(amount, start, end);
}

function calculateUnlockedRewards(
RewardSchedule[] memory rewardSchedules,
uint256 rewardBalance,
uint256 sharesOutstanding,
uint256 timestamp
)
function calculateUnlockedRewards(uint256 timestamp)
public
pure
override
returns (uint256 unlockedRewards)
{
return AludelV3Lib.calculateUnlockedRewards(
rewardSchedules,
rewardBalance,
sharesOutstanding,
timestamp
);
view
returns (uint256 unlockedRewards) {
return AludelV3Lib.calculateUnlockedRewards(_aludel, timestamp);
}

function calculateReward(
Expand Down Expand Up @@ -633,12 +621,7 @@ contract AludelV3 is IAludelV3, Ownable, Initializable, Powered {
uint256 remainingRewards = AludelV3Lib.getRemainingRewards(_aludel);

// calculate vested portion of reward pool
uint256 unlockedRewards = AludelV3Lib.calculateUnlockedRewards(
_aludel.rewardSchedules,
remainingRewards,
_aludel.rewardSharesOutstanding,
block.timestamp
);
uint256 unlockedRewards = calculateUnlockedRewards(block.timestamp);

(uint256 reward, uint256 amount) = _unstake(
vault,
Expand Down
25 changes: 25 additions & 0 deletions src/contracts/aludel/AludelV3Lib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,29 @@ library AludelV3Lib {
return unlockedRewards;
}

function calculateCurrentUnlockedRewards(
IAludelV3.AludelData storage aludel
) internal view returns(uint256 unlockedRewards) {
unlockedRewards = AludelV3Lib.calculateUnlockedRewards(
aludel.rewardSchedules,
getRemainingRewards(aludel),
aludel.rewardSharesOutstanding,
block.timestamp
);
}

function calculateUnlockedRewards(
IAludelV3.AludelData storage aludel,
uint256 timestamp
) internal view returns(uint256 unlockedRewards) {
unlockedRewards = AludelV3Lib.calculateUnlockedRewards(
aludel.rewardSchedules,
getRemainingRewards(aludel),
aludel.rewardSharesOutstanding,
timestamp
);
}

function calculateReward(
uint256 unlockedRewards,
uint256 stakeAmount,
Expand Down Expand Up @@ -171,6 +194,8 @@ library AludelV3Lib {
}




/* state mutating functions */

function addRewardSchedule(
Expand Down
9 changes: 2 additions & 7 deletions src/contracts/aludel/IAludelV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,9 @@ interface IAludelV3 is IRageQuit {
pure
returns (uint256 stakeUnits);

function calculateUnlockedRewards(
RewardSchedule[] memory rewardSchedules,
uint256 rewardBalance,
uint256 sharesOutstanding,
uint256 timestamp
)
function calculateUnlockedRewards(uint256 timestamp)
external
pure
view
returns (uint256 unlockedRewards);

function calculateReward(
Expand Down
149 changes: 25 additions & 124 deletions src/test/AludelV3.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -136,180 +136,81 @@ contract AludelV3Test is Test {
}

function test_funding_shares() public {
// Scenario: Aludel is funded several times.
// Shares should unlock linearly.
// ______________________________________________
// | Outstanding | Locked | Unlocked |
// |==============================================|
// | 1. Admin funds 600 ether, for 1 minute |
// |---------------|--------------|---------------|
// | 6e26 | 6e26 | 0 |
// |---------------|--------------|---------------|
// | 2. 1 minute elapses |
// |---------------|--------------|---------------|
// | 6e26 | 0 | 6e25 |
// |---------------|--------------|---------------|
// | 3. Admin funds 600 ether, for 1 minute |
// |---------------|--------------|---------------|
// | 6e26 * 2 | 6e25 | 6e25 |
// |---------------|--------------|---------------|
// | 4. 1 minute elapses |
// |---------------|--------------|---------------|
// | 6e26 * 2 | 0 | 6e25 * 2 |
// |---------------|--------------|---------------|
// | 4. Admin funds 600 ether, for 1 minute |
// |---------------|--------------|---------------|
// | 6e26 * 3 | 6e25 * 5 | 6e25 * 2 |
// |---------------|--------------|---------------|
// | 5. 1 minute elapses |
// |---------------|--------------|---------------|
// | 6e26 * 3 | 0 | 6e25 * 3 |
// |---------------|--------------|---------------|
// | 6. Admin funds 600 ether, for 1 minute |
// | Admin funds 600 ether, for 2 minute |
// | 1 minute elapses |
// | Forth schedule is fully unlocked |
// | Fifth is half unlocked |
// |---------------|--------------|---------------|
// | 6e26 * 5 | 6e25 * 0.5 | 6e25 * 4.5 |
// |---------------|--------------|---------------|
// | 7. 1 minute elapses |
// | Fifth schedule is now fully unlocked |
// |---------------|--------------|---------------|
// | 6e26 * 5 | 0 | 6e25 * 5 |
// |---------------|--------------|---------------|

AludelV3.AludelData memory data = aludel.getAludelData();

AludelV3.AludelData memory data;

Utils.fundMockToken(admin.addr(), rewardToken, REWARD_AMOUNT * 5);

vm.startPrank(admin.addr());
rewardToken.approve(address(aludel), REWARD_AMOUNT * 5);

// 1. Admin funds 600 eth * 5 for 1 minute
aludel.fund(REWARD_AMOUNT, SCHEDULE_DURATION);

data = aludel.getAludelData();
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI);
assertEq(
aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp),
REWARD_AMOUNT * BASE_SHARES_PER_WEI
);

// 2. 1 minute elapses
// 2. Advance time 1 minute
vm.warp(block.timestamp + SCHEDULE_DURATION);

data = aludel.getAludelData();
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI);
assertEq(aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp), 0);

// 3. Admin funds 600 eth * 5 for 1 minute
aludel.fund(REWARD_AMOUNT, SCHEDULE_DURATION);

data = aludel.getAludelData();
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 2);
assertEq(
aludel.calculateUnlockedRewards(
data.rewardSchedules,
REWARD_AMOUNT,
data.rewardSharesOutstanding,
block.timestamp + SCHEDULE_DURATION
),
REWARD_AMOUNT
);
assertEq(aludel.calculateUnlockedRewards(block.timestamp), REWARD_AMOUNT);
assertEq(
aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp),
REWARD_AMOUNT * BASE_SHARES_PER_WEI
);

// 4. Admin funds 600 eth * 5 for 1 minute
aludel.fund(REWARD_AMOUNT, SCHEDULE_DURATION);

// 4. Advance time 1 minute
vm.warp(block.timestamp + SCHEDULE_DURATION);
data = aludel.getAludelData();
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 3);
assertEq(
aludel.calculateUnlockedRewards(
data.rewardSchedules,
REWARD_AMOUNT * 2,
data.rewardSharesOutstanding,
block.timestamp + SCHEDULE_DURATION
),
REWARD_AMOUNT * 2
);
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 2);
assertEq(aludel.calculateUnlockedRewards(block.timestamp), REWARD_AMOUNT * 2);
assertEq(
aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp),
REWARD_AMOUNT * BASE_SHARES_PER_WEI * 2
0
);

data = aludel.getAludelData();

assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 3);
assertEq(
aludel.calculateUnlockedRewards(
data.rewardSchedules,
REWARD_AMOUNT * 3,
data.rewardSharesOutstanding,
block.timestamp + SCHEDULE_DURATION
),
REWARD_AMOUNT * 3
);

// 5. 1 minute elapses
// 5. Admin funds 600 eth * 5 for 1 minute
// 1 minute elapses
aludel.fund(REWARD_AMOUNT, SCHEDULE_DURATION);
vm.warp(block.timestamp + SCHEDULE_DURATION);

data = aludel.getAludelData();

assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 3);

assertEq(aludel.calculateUnlockedRewards(block.timestamp), REWARD_AMOUNT * 3);
assertEq(
aludel.calculateUnlockedRewards(
data.rewardSchedules,
REWARD_AMOUNT * 3,
data.rewardSharesOutstanding,
block.timestamp + SCHEDULE_DURATION
),
REWARD_AMOUNT * 3
aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp),
0
);
assertEq(aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp), 0);

// 6. Admin funds 600 eth * 5 for 1 minute
// Admin funds 600 eth * 5 for 2 minute
// 1 minute elapses
aludel.fund(REWARD_AMOUNT, SCHEDULE_DURATION);

// 6. Admin funds 600 eth * 5 for 2 minute
aludel.fund(REWARD_AMOUNT, SCHEDULE_DURATION * 2);

// 6. 1 minute elapses
vm.warp(block.timestamp + SCHEDULE_DURATION);

data = aludel.getAludelData();
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 5);
// previous four periods amounts and half of the fifth.
// previous four schedule amounts and half of the fifth.
assertEq(
aludel.calculateUnlockedRewards(
data.rewardSchedules,
REWARD_AMOUNT * 5,
data.rewardSharesOutstanding,
block.timestamp
),
aludel.calculateUnlockedRewards(block.timestamp),
REWARD_AMOUNT * 4 + REWARD_AMOUNT / 2
);
// fifth schedule shares are half-locked
assertEq(
aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp),
REWARD_AMOUNT * BASE_SHARES_PER_WEI / 2
);

// 6. 1 minute elapses
vm.warp(block.timestamp + SCHEDULE_DURATION);

data = aludel.getAludelData();
assertEq(data.rewardSharesOutstanding, REWARD_AMOUNT * BASE_SHARES_PER_WEI * 5);
assertEq(
aludel.calculateUnlockedRewards(
data.rewardSchedules,
REWARD_AMOUNT * 5,
data.rewardSharesOutstanding,
block.timestamp
),
REWARD_AMOUNT * 5
);

// Fifth schedule shares are now fully unlocked
assertEq(aludel.calculateSharesLocked(data.rewardSchedules, block.timestamp), 0);
}

function test_stakes_no_amount_staked() public {
Expand Down

0 comments on commit f637188

Please sign in to comment.