Skip to content
Open
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
14 changes: 14 additions & 0 deletions contracts/farm/LiquidityMining.sol
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,20 @@ contract LiquidityMining is ILiquidityMining, LiquidityMiningStorage {
_updatePool(poolId);
_updateReward(pool, user);

// Calculate the user's share of the pool
uint256 totalPoolTokens = pool.poolToken.balanceOf(address(this));
uint256 userShare = user.amount.mul(PRECISION).div(totalPoolTokens);

// Calculate the undistributed rewards
uint256 undistributedRewards = user.accumulatedReward; // user.accumulatedReward.mul(PRECISION.add(userShare)).div(PRECISION); // 2nd try // user.accumulatedReward.mul(PRECISION.sub(userShare)).div(PRECISION); // 1st try // 3rd try

// Update the pool's accumulatedRewardPerShare to redistribute the undistributed rewards
if (undistributedRewards > 0 && totalPoolTokens > user.amount) {
pool.accumulatedRewardPerShare = pool.accumulatedRewardPerShare.add(
undistributedRewards.mul(PRECISION).div(totalPoolTokens.sub(user.amount))
);
}

totalUsersBalance = totalUsersBalance.sub(user.accumulatedReward);
uint256 userAmount = user.amount;
uint256 userAccumulatedReward = user.accumulatedReward;
Expand Down
128 changes: 128 additions & 0 deletions tests/farm/LiquidityMining.js
Original file line number Diff line number Diff line change
Expand Up @@ -2592,6 +2592,134 @@ contract("LiquidityMining", (accounts) => {
expect(reward1).bignumber.equal("15");
expect(reward2).bignumber.equal("5");
});

it.only("check calculation for two users, same token (shares taken into account)", async () => {
const token = token1;
const amount = amount1;
await token.mint(account2, amount);
await token.approve(liquidityMining.address, amount, { from: account2 });

const initialBlockNumber = await web3.eth.getBlockNumber();
console.log("initialBlockNumber", initialBlockNumber);
const initialBalance = await token1.balanceOf(account1);
console.log("initialBalance", initialBalance.toString());

await liquidityMining.deposit(token.address, amount, ZERO_ADDRESS, { from: account1 });
const blockNumberAfterFirstDeposit = await web3.eth.getBlockNumber();
console.log("blockNumberAfterFirstDeposit", blockNumberAfterFirstDeposit);
const balanceAfterFirstDeposit = await token1.balanceOf(account1);
console.log("balanceAfterFirstDeposit", balanceAfterFirstDeposit.toString());
const reward001 = await liquidityMining.getUserAccumulatedReward(
token.address,
account1
);
console.log("reward user 1 after first deposit", reward001.toString());
const reward002 = await liquidityMining.getUserAccumulatedReward(
token.address,
account2
);
console.log("reward user 2 after first deposit", reward002.toString());

// because automining is on, the following will advance a block
await liquidityMining.deposit(token.address, amount, ZERO_ADDRESS, { from: account2 });
const blockNumberAfterSecondDeposit = await web3.eth.getBlockNumber();
console.log("blockNumberAfterSecondDeposit", blockNumberAfterSecondDeposit);
// sanity checks
expect(
await liquidityMining.getUserAccumulatedReward(token.address, account1)
).bignumber.equal("10");
expect(
await liquidityMining.getUserAccumulatedReward(token.address, account2)
).bignumber.equal("0");
const reward101 = await liquidityMining.getUserAccumulatedReward(
token.address,
account1
);
console.log("reward user 1 after second deposit", reward101.toString());
const reward102 = await liquidityMining.getUserAccumulatedReward(
token.address,
account2
);
console.log("reward user 2 after second deposit", reward102.toString());

await mineBlock();
const blockNumberAfterFirstJump = await web3.eth.getBlockNumber();
console.log("blockNumberAfterFirstJump", blockNumberAfterFirstJump);
expect(
await liquidityMining.getUserAccumulatedReward(token.address, account2)
).bignumber.equal("5");
const reward1 = await liquidityMining.getUserAccumulatedReward(
token.address,
account1
);
console.log("reward user 1 after first jump", reward1.toString());
const reward2 = await liquidityMining.getUserAccumulatedReward(
token.address,
account2
);
console.log("reward user 2 after first jump", reward2.toString());

// for the first block, user 1 will receive the reward of 10 (reward given per block for 100% of shares)
// for the second block:
// - user 1 owns 1/2 of the shares => expected reward = 5 (total 10 + 5 = 15)
// - user 2 owns 1/2 of the shares => expected reward = 5
expect(reward1).bignumber.equal("15");
expect(reward2).bignumber.equal("5");

// 1 block pass here due to automining, 5 reward to each account
await liquidityMining.emergencyWithdraw(token1.address, { from: account1 });
const blockNumberAfterEmergencyWithdraw = await web3.eth.getBlockNumber();
console.log("blockNumberAfterEmergencyWithdraw", blockNumberAfterEmergencyWithdraw);
const balanceAfterEmergencyWithdraw = await token1.balanceOf(account1);
console.log("balanceAfterEmergencyWithdraw", balanceAfterEmergencyWithdraw.toString());

const reward01 = await liquidityMining.getUserAccumulatedReward(
token.address,
account1
);
console.log("reward01", reward01.toString());
const reward02 = await liquidityMining.getUserAccumulatedReward(
token.address,
account2
);
console.log("reward02", reward02.toString());

// 1 block pass here
await mineBlock();
const blockNumberAfterSecondJump = await web3.eth.getBlockNumber();
console.log("blockNumberAfterSecondJump", blockNumberAfterSecondJump);
const reward11 = await liquidityMining.getUserAccumulatedReward(
token.address,
account1
);
expect(reward11).bignumber.equal("0");
console.log("reward user 1 after jump after emergency withdraw", reward11.toString());
const reward22 = await liquidityMining.getUserAccumulatedReward(
token.address,
account2
);
console.log("reward user 2 after jump after emergency withdraw", reward22.toString());
//Since account 1 has made emergencyWithdraw so account2 should get all unfinalized rewards
// Fails since update pool and user reward reduces reward to 20
// expect(reward22).bignumber.equal("40");
expect(reward22).bignumber.equal("40");

await mineBlock();
const blockNumberAfterThirdJump = await web3.eth.getBlockNumber();
console.log("blockNumberAfterThirdJump", blockNumberAfterThirdJump);
const reward31 = await liquidityMining.getUserAccumulatedReward(
token.address,
account1
);
expect(reward31).bignumber.equal("0");
console.log("reward user 1 after third jump", reward31.toString());
const reward32 = await liquidityMining.getUserAccumulatedReward(
token.address,
account2
);
console.log("reward user 2 after third jump", reward32.toString());
expect(reward32).bignumber.equal("50");
});
});

describe("getEstimatedReward", () => {
Expand Down
Loading