Skip to content

Commit 91f4835

Browse files
committed
transfer to treasury
1 parent 7883520 commit 91f4835

File tree

8 files changed

+85
-40
lines changed

8 files changed

+85
-40
lines changed

contracts/gov/GovPool.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ contract GovPool is
254254

255255
_unlock(msg.sender);
256256

257-
_govUserKeeper.redeemTokens(msg.sender, receiver, amount);
257+
_govUserKeeper.redeemTokens(msg.sender, receiver, amount, coreProperties);
258258
}
259259

260260
function delegate(

contracts/gov/settings/GovSettings.sol

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ contract GovSettings is IGovSettings, OwnableUpgradeable {
9898
function createNewStaking(
9999
uint64 lockTime,
100100
uint256 rewardMultiplier,
101-
uint256 redeemPenalty
101+
uint256 redeemPenalty,
102+
bool allowStakingUpgrade
102103
) external override onlyOwner {
103104
require(
104105
lockTime > 0 &&
@@ -108,7 +109,13 @@ contract GovSettings is IGovSettings, OwnableUpgradeable {
108109
);
109110

110111
uint256 id = ++totalStakes;
111-
stakingList[id] = StakingInfo(lockTime, rewardMultiplier, redeemPenalty, false);
112+
stakingList[id] = StakingInfo(
113+
lockTime,
114+
rewardMultiplier,
115+
redeemPenalty,
116+
allowStakingUpgrade,
117+
false
118+
);
112119
}
113120

114121
function closeStaking(uint256 id) external override onlyOwner {

contracts/gov/user-keeper/GovUserKeeper.sol

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import "../../interfaces/gov/user-keeper/IGovUserKeeper.sol";
2222
import "../../interfaces/gov/settings/IGovSettings.sol";
2323
import "../../interfaces/gov/IGovPool.sol";
2424
import "../../interfaces/gov/ERC721/powers/IERC721Power.sol";
25+
import "../../interfaces/core/ICoreProperties.sol";
2526

2627
import "../../libs/math/MathHelper.sol";
2728
import "../../libs/gov/gov-user-keeper/GovUserKeeperView.sol";
@@ -125,7 +126,8 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
125126
function redeemTokens(
126127
address payer,
127128
address receiver,
128-
uint256 amount
129+
uint256 amount,
130+
ICoreProperties coreProperties
129131
) external override onlyOwner withSupportedToken {
130132
require(amount > 0, "GovUK: empty redeem");
131133
require(_isStaked(payer), "GovUK: not staked");
@@ -137,10 +139,14 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
137139

138140
uint256 redeemPenalty = stakeInfo.redeemPenalty;
139141
require(redeemPenalty != type(uint256).max, "GovUK: redeem forbidden");
140-
uint256 redeemToGovpoolAmount = amount.percentage(redeemPenalty);
142+
uint256 redeemToGovPoolAmount = amount.percentage(redeemPenalty);
143+
144+
(uint256 commission, address dexeTreasury) = coreProperties.getDEXECommissionPercentages();
145+
uint256 redeemToDexeAmount = redeemToGovPoolAmount.percentage(commission);
141146

142-
_sendNativeOrToken(owner(), redeemToGovpoolAmount);
143-
_sendNativeOrToken(receiver, amount - redeemToGovpoolAmount);
147+
_sendNativeOrToken(dexeTreasury, redeemToDexeAmount);
148+
_sendNativeOrToken(owner(), redeemToGovPoolAmount - redeemToDexeAmount);
149+
_sendNativeOrToken(receiver, amount - redeemToGovPoolAmount);
144150
}
145151

146152
function delegateTokens(
@@ -516,7 +522,7 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
516522

517523
IGovSettings.StakingInfo memory oldStakeInfo = _getStakeInfo(userStake.stakeId);
518524

519-
if (oldStakeInfo.lockTime < newStakeInfo.lockTime) {
525+
if (oldStakeInfo.lockTime < newStakeInfo.lockTime && oldStakeInfo.allowStakingUpgrade) {
520526
_stake(userStake, id);
521527
return;
522528
}
@@ -800,7 +806,7 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
800806
nativeAmount -= value;
801807
}
802808

803-
function getStakingMultiplier(address user) public view returns (uint256) {
809+
function getStakingMultiplier(address user) public view override returns (uint256) {
804810
Stake storage currentStake = _stakes[user];
805811
uint256 id = currentStake.stakeId;
806812

contracts/interfaces/gov/settings/IGovSettings.sol

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ interface IGovSettings {
5555
/// @param lockTime the lock time of the stake
5656
/// @param rewardMultiplier the reward bonus for the staker
5757
/// @param redeemPenalty the percent substracted for early unstake, 0-100*10**25, uint.max if not allowed
58+
/// @param allowStakingUpgrade the possibility to switch to long-term staking without penalties
5859
/// @param disabled the state of staking
5960
struct StakingInfo {
6061
uint64 lockTime;
6162
uint256 rewardMultiplier;
6263
uint256 redeemPenalty;
64+
bool allowStakingUpgrade;
6365
bool disabled;
6466
}
6567

@@ -95,7 +97,8 @@ interface IGovSettings {
9597
function createNewStaking(
9698
uint64 lockTime,
9799
uint256 rewardMultiplier,
98-
uint256 redeemPenalty
100+
uint256 redeemPenalty,
101+
bool allowStakingUpgrade
99102
) external;
100103

101104
/// @notice Disables active staking

contracts/interfaces/gov/user-keeper/IGovUserKeeper.sol

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,13 @@ interface IGovUserKeeper {
114114
/// @param payer the address from whom to redeem the tokens
115115
/// @param receiver the redeem receiver address
116116
/// @param amount the erc20 redeeming amount
117-
function redeemTokens(address payer, address receiver, uint256 amount) external;
117+
/// @param coreProperties the CoreProperties contract address
118+
function redeemTokens(
119+
address payer,
120+
address receiver,
121+
uint256 amount,
122+
ICoreProperties coreProperties
123+
) external;
118124

119125
/// @notice The function for delegating tokens
120126
/// @param delegator the address of delegator
@@ -378,4 +384,9 @@ interface IGovUserKeeper {
378384
uint256 value,
379385
uint256 amount
380386
) external view returns (uint256 nativeAmount);
387+
388+
/// @notice The function for getting the staking multiplier for a user
389+
/// @param user the address of the user
390+
/// @return the multiplier amount with 25 digits precision
391+
function getStakingMultiplier(address user) external view returns (uint256);
381392
}

contracts/libs/gov/gov-pool/GovPoolRewards.sol

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "@openzeppelin/contracts/utils/math/Math.sol";
77
import "../../../interfaces/core/ICoreProperties.sol";
88

99
import "../../../interfaces/gov/IGovPool.sol";
10+
import "../../../interfaces/gov/user-keeper/IGovUserKeeper.sol";
1011
import "../../../interfaces/gov/ERC721/multipliers/IAbstractERC721Multiplier.sol";
1112

1213
import "../../utils/TokenBalance.sol";
@@ -224,12 +225,24 @@ library GovPoolRewards {
224225

225226
function _getMultipliedRewards(address user, uint256 amount) internal view returns (uint256) {
226227
(address nftMultiplier, , , ) = IGovPool(address(this)).getNftContracts();
228+
(, address userKeeper, , , ) = IGovPool(address(this)).getHelperContracts();
229+
230+
uint256 multiplierReward;
231+
uint256 stakingReward;
227232

228233
if (nftMultiplier != address(0)) {
229-
amount += IAbstractERC721Multiplier(nftMultiplier).getExtraRewards(user, amount);
234+
multiplierReward = IAbstractERC721Multiplier(nftMultiplier).getExtraRewards(
235+
user,
236+
amount
237+
);
230238
}
231239

232-
return amount;
240+
stakingReward = amount.ratio(
241+
IGovUserKeeper(userKeeper).getStakingMultiplier(user),
242+
PRECISION
243+
);
244+
245+
return amount + multiplierReward + stakingReward;
233246
}
234247

235248
function _getVotingRewards(

test/gov/GovPool.test.js

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -816,22 +816,22 @@ describe("GovPool", () => {
816816
});
817817

818818
it("must be govPool to create staking", async () => {
819-
await truffleAssert.reverts(settings.createNewStaking(1, 1, 0), "Ownable: caller is not the owner");
819+
await truffleAssert.reverts(settings.createNewStaking(1, 1, 0, false), "Ownable: caller is not the owner");
820820
});
821821

822822
it("staking must have correct parameters", async () => {
823823
await truffleAssert.reverts(
824-
settings.createNewStaking(0, 1, 0, { from: govPool.address }),
824+
settings.createNewStaking(0, 1, 0, false, { from: govPool.address }),
825825
"GovSettings: wrong staking info",
826826
);
827827

828828
await truffleAssert.reverts(
829-
settings.createNewStaking(1, 0, 0, { from: govPool.address }),
829+
settings.createNewStaking(1, 0, 0, false, { from: govPool.address }),
830830
"GovSettings: wrong staking info",
831831
);
832832

833833
await truffleAssert.reverts(
834-
settings.createNewStaking(1, 1, wei("1000000001"), { from: govPool.address }),
834+
settings.createNewStaking(1, 1, wei("1000000001"), false, { from: govPool.address }),
835835
"GovSettings: wrong staking info",
836836
);
837837
});
@@ -840,23 +840,23 @@ describe("GovPool", () => {
840840
assert.equal(await settings.totalStakes(), 0);
841841
await truffleAssert.reverts(settings.getStakingSettings(1), "GovSettings: invalid id");
842842

843-
await settings.createNewStaking(1, 1, 0, { from: govPool.address });
843+
await settings.createNewStaking(1, 1, 0, false, { from: govPool.address });
844844
assert.equal(await settings.totalStakes(), 1);
845-
await settings.createNewStaking(2, 2, 1, { from: govPool.address });
845+
await settings.createNewStaking(2, 2, 1, false, { from: govPool.address });
846846
assert.equal(await settings.totalStakes(), 2);
847847
const list = await settings.getStakingSettingsList([1, 2]);
848-
assert.deepEqual(list[0], ["1", "1", "0", false]);
849-
assert.deepEqual(list[1], ["2", "2", "1", false]);
848+
assert.deepEqual(list[0], ["1", "1", "0", false, false]);
849+
assert.deepEqual(list[1], ["2", "2", "1", false, false]);
850850
});
851851

852852
it("could disable staking", async () => {
853-
await settings.createNewStaking(1, 1, 0, { from: govPool.address });
854-
assert.deepEqual(await settings.getStakingSettings(1), ["1", "1", "0", false]);
853+
await settings.createNewStaking(1, 1, 0, false, { from: govPool.address });
854+
assert.deepEqual(await settings.getStakingSettings(1), ["1", "1", "0", false, false]);
855855

856856
await truffleAssert.reverts(settings.closeStaking(1), "Ownable: caller is not the owner");
857857

858858
await settings.closeStaking(1, { from: govPool.address });
859-
assert.deepEqual(await settings.getStakingSettings(1), ["1", "1", "0", true]);
859+
assert.deepEqual(await settings.getStakingSettings(1), ["1", "1", "0", false, true]);
860860
});
861861

862862
it("can't disable invalid staking", async () => {
@@ -879,15 +879,15 @@ describe("GovPool", () => {
879879
});
880880

881881
it("cant stake on disabled tier", async () => {
882-
await settings.createNewStaking(5, 1, 0, { from: govPool.address });
882+
await settings.createNewStaking(5, 1, 0, false, { from: govPool.address });
883883
await settings.closeStaking(1, { from: govPool.address });
884884
await truffleAssert.reverts(userKeeper.stake(1), "GovUK: staking tier is disabled");
885885
});
886886

887887
it("cant stake if already staked", async () => {
888-
await settings.createNewStaking(10, 1, 0, { from: govPool.address });
888+
await settings.createNewStaking(10, 1, 0, false, { from: govPool.address });
889889
await userKeeper.stake(1);
890-
await settings.createNewStaking(5, 1, 0, { from: govPool.address });
890+
await settings.createNewStaking(5, 1, 0, false, { from: govPool.address });
891891
await truffleAssert.reverts(userKeeper.stake(2), "GovUK: Already staked");
892892
});
893893

@@ -897,7 +897,7 @@ describe("GovPool", () => {
897897
await setTime((await getCurrentBlockTime()) + 1);
898898
await govPool.withdraw.call(OWNER, wei("100"), [1, 2, 3]);
899899

900-
await settings.createNewStaking(5, 1, 0, { from: govPool.address });
900+
await settings.createNewStaking(5, 1, 0, false, { from: govPool.address });
901901
await userKeeper.stake(1);
902902
await truffleAssert.reverts(govPool.withdraw(OWNER, wei("100"), [1, 2, 3]), "GovUK: staked");
903903

@@ -906,7 +906,7 @@ describe("GovPool", () => {
906906

907907
it("could withdraw from disabled tier", async () => {
908908
await govPool.deposit(wei("100"), []);
909-
await settings.createNewStaking(100, 1, 0, { from: govPool.address });
909+
await settings.createNewStaking(100, 1, 0, false, { from: govPool.address });
910910
await userKeeper.stake(1);
911911

912912
await truffleAssert.reverts(govPool.withdraw(OWNER, wei("100"), []), "GovUK: staked");
@@ -918,7 +918,7 @@ describe("GovPool", () => {
918918

919919
it("could withdraw after staking end", async () => {
920920
await govPool.deposit(wei("100"), []);
921-
await settings.createNewStaking(100, 1, 0, { from: govPool.address });
921+
await settings.createNewStaking(100, 1, 0, false, { from: govPool.address });
922922
await userKeeper.stake(1);
923923

924924
await truffleAssert.reverts(govPool.withdraw(OWNER, wei("100"), []), "GovUK: staked");
@@ -930,40 +930,40 @@ describe("GovPool", () => {
930930

931931
it("could restake after staking end", async () => {
932932
await govPool.deposit(wei("100"), []);
933-
await settings.createNewStaking(100, 1, 0, { from: govPool.address });
933+
await settings.createNewStaking(100, 1, 0, false, { from: govPool.address });
934934
await userKeeper.stake(1);
935935

936936
await truffleAssert.reverts(govPool.withdraw(OWNER, wei("100"), []), "GovUK: staked");
937937

938938
await setTime((await getCurrentBlockTime()) + 100);
939939

940-
await settings.createNewStaking(100, 2, 0, { from: govPool.address });
940+
await settings.createNewStaking(100, 2, 0, false, { from: govPool.address });
941941

942942
await userKeeper.stake(2);
943943
});
944944

945945
it("could restake to a longer tier", async () => {
946946
await govPool.deposit(wei("100"), []);
947-
await settings.createNewStaking(100, 1, 0, { from: govPool.address });
947+
await settings.createNewStaking(100, 1, 0, true, { from: govPool.address });
948948
await userKeeper.stake(1);
949949

950950
await truffleAssert.reverts(govPool.withdraw(OWNER, wei("100"), []), "GovUK: staked");
951951

952-
await settings.createNewStaking(200, 2, 0, { from: govPool.address });
952+
await settings.createNewStaking(200, 2, 0, false, { from: govPool.address });
953953

954954
await userKeeper.stake(2);
955955
});
956956

957957
it("cant redeem from user keeper", async () => {
958958
await truffleAssert.reverts(
959-
userKeeper.redeemTokens(OWNER, OWNER, wei("100")),
959+
userKeeper.redeemTokens(OWNER, OWNER, wei("100"), OWNER),
960960
"Ownable: caller is not the owner",
961961
);
962962
});
963963

964964
it("cant redeem zero tokens", async () => {
965965
await govPool.deposit(wei("100"), []);
966-
await settings.createNewStaking(100, 1, 50, { from: govPool.address });
966+
await settings.createNewStaking(100, 1, 50, false, { from: govPool.address });
967967
await userKeeper.stake(1);
968968

969969
await truffleAssert.reverts(govPool.withdraw(OWNER, wei("100"), []), "GovUK: staked");
@@ -978,23 +978,25 @@ describe("GovPool", () => {
978978

979979
it("cant redeem when redeem forbidden", async () => {
980980
await govPool.deposit(wei("100"), []);
981-
await settings.createNewStaking(100, 1, MAX_UINT, { from: govPool.address });
981+
await settings.createNewStaking(100, 1, MAX_UINT, false, { from: govPool.address });
982982
await userKeeper.stake(1);
983983

984984
await truffleAssert.reverts(govPool.redeemTokens(OWNER, wei("100")), "GovUK: redeem forbidden");
985985
});
986986

987987
it("could redeem", async () => {
988988
await govPool.deposit(wei("100"), []);
989-
await settings.createNewStaking(100, 1, PERCENTAGE_50, { from: govPool.address });
989+
await settings.createNewStaking(100, 1, PERCENTAGE_50, false, { from: govPool.address });
990990
await userKeeper.stake(1);
991991

992992
const ownerBalance = (await token.balanceOf(OWNER)).plus(wei("50"));
993-
const govPoolBalance = (await token.balanceOf(govPool.address)).plus(wei("50"));
993+
const govPoolBalance = (await token.balanceOf(govPool.address)).plus(wei("40"));
994+
const treasuryBalance = (await token.balanceOf(ETHER_ADDR)).plus(wei("10"));
994995
await govPool.redeemTokens(OWNER, wei("100"));
995996

996997
assert.equal((await token.balanceOf(OWNER)).toFixed(), ownerBalance.toFixed());
997998
assert.equal((await token.balanceOf(govPool.address)).toFixed(), govPoolBalance.toFixed());
999+
assert.equal((await token.balanceOf(ETHER_ADDR)).toFixed(), treasuryBalance.toFixed());
9981000
});
9991001
});
10001002

test/gov/GovUserKeeper.test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,10 @@ describe("GovUserKeeper", () => {
10531053

10541054
await truffleAssert.reverts(userKeeper.delegateTokens(OWNER, OWNER, wei("100")), "GovUK: token is not supported");
10551055

1056-
await truffleAssert.reverts(userKeeper.redeemTokens(OWNER, OWNER, wei("100")), "GovUK: token is not supported");
1056+
await truffleAssert.reverts(
1057+
userKeeper.redeemTokens(OWNER, OWNER, wei("100"), OWNER),
1058+
"GovUK: token is not supported",
1059+
);
10571060

10581061
await truffleAssert.reverts(
10591062
userKeeper.delegateTokensTreasury(OWNER, wei("100")),

0 commit comments

Comments
 (0)