Skip to content

Commit

Permalink
native decimals (#193)
Browse files Browse the repository at this point in the history
* native decimals

* moved logic to userKeeper

* fixes and coverage

* withdraw

* handle zero amount in rewards

* coverage

* fixes
  • Loading branch information
todesstille authored Apr 25, 2024
1 parent dac37d0 commit 3eeae7c
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 37 deletions.
21 changes: 8 additions & 13 deletions contracts/gov/GovPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,10 @@ contract GovPool is
uint256[] calldata nftIds
) external payable override onlyBABTHolder {
require(amount > 0 || nftIds.length > 0, "Gov: empty deposit");
_checkValue(amount);

_lockBlock(DEPOSIT_WITHDRAW, msg.sender);

if (amount != 0) {
if (amount != 0 || msg.value != 0) {
_govUserKeeper.depositTokens{value: msg.value}(msg.sender, msg.sender, amount);
}

Expand Down Expand Up @@ -274,20 +273,20 @@ contract GovPool is
) external payable override onlyThis {
require(amount > 0 || nftIds.length > 0, "Gov: empty delegation");
require(getExpertStatus(delegatee), "Gov: delegatee is not an expert");
_checkValue(amount);

_lockBlock(DELEGATE_UNDELEGATE_TREASURY, msg.sender);

_unlock(delegatee);

if (amount != 0) {
if (amount != 0 || msg.value != 0) {
address token = _govUserKeeper.tokenAddress();
uint256 amountWithNativeDecimals = _govUserKeeper.getAmountWithNativeDecimals(
msg.value,
amount
);

if (amount != msg.value) {
IERC20(token).safeTransfer(
address(_govUserKeeper),
(amount - msg.value).from18Safe(token)
);
if (amountWithNativeDecimals != 0) {
IERC20(token).safeTransfer(address(_govUserKeeper), amountWithNativeDecimals);
}

_govUserKeeper.delegateTokensTreasury{value: msg.value}(delegatee, amount);
Expand Down Expand Up @@ -630,8 +629,4 @@ contract GovPool is
"Gov: not BABT holder"
);
}

function _checkValue(uint256 amount) internal view {
require(msg.value <= amount, "Gov: value is greater than amount to transfer");
}
}
53 changes: 33 additions & 20 deletions contracts/gov/user-keeper/GovUserKeeper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,15 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
uint256 amount
) external payable override onlyOwner withSupportedToken {
address token = tokenAddress;
uint256 fullAmount = amount;
uint256 amountWithNativeDecimals = getAmountWithNativeDecimals(msg.value, amount);

if (msg.value != 0) {
_wrapNative(msg.value);
amount -= msg.value;
}
_handleNative(msg.value, true);

if (amount > 0) {
IERC20(token).safeTransferFrom(payer, address(this), amount.from18Safe(token));
if (amountWithNativeDecimals > 0) {
IERC20(token).safeTransferFrom(payer, address(this), amountWithNativeDecimals);
}

_usersInfo[receiver].balances[IGovPool.VoteType.PersonalVote].tokens += fullAmount;
_usersInfo[receiver].balances[IGovPool.VoteType.PersonalVote].tokens += amount;
}

function withdrawTokens(
Expand Down Expand Up @@ -156,9 +153,7 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
address delegatee,
uint256 amount
) external payable override onlyOwner withSupportedToken {
if (msg.value != 0) {
_wrapNative(msg.value);
}
_handleNative(msg.value, true);

_usersInfo[delegatee].balances[IGovPool.VoteType.TreasuryVote].tokens += amount;
}
Expand Down Expand Up @@ -749,16 +744,32 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
);
}

function getAmountWithNativeDecimals(
uint256 value,
uint256 amount
) public view returns (uint256 nativeAmount) {
require(
value == 0 || _isWrapped(),
"GovUK: should not send ether if Gov token is not native"
);

nativeAmount = amount.from18Safe(tokenAddress);
require(nativeAmount >= value, "GovUK: ether value is greater than amount");

nativeAmount -= value;
}

function _sendNativeOrToken(address receiver, uint256 amount) internal {
address token = tokenAddress;
amount = amount.from18Safe(token);

if (_isWrapped()) {
_unwrapNative(amount);
_handleNative(amount, false);

(bool ok, ) = payable(receiver).call{value: amount}("");
require(ok, "GovUK: can't send ether");
} else {
IERC20(token).safeTransfer(receiver, amount.from18Safe(token));
IERC20(token).safeTransfer(receiver, amount);
}
}

Expand Down Expand Up @@ -828,14 +839,16 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
require(_nftInfo.nftAddress != address(0), "GovUK: nft is not supported");
}

function _wrapNative(uint256 value) internal {
require(_isWrapped(), "GovUK: not native token pool");

IWETH(wethAddress).deposit{value: value}();
}
function _handleNative(uint256 value, bool wrapping) internal {
if (value == 0) {
return;
}

function _unwrapNative(uint256 value) internal {
IWETH(wethAddress).withdraw(value);
if (wrapping) {
IWETH(wethAddress).deposit{value: value}();
} else {
IWETH(wethAddress).withdraw(value);
}
}

function _isWrapped() internal view returns (bool) {
Expand Down
9 changes: 9 additions & 0 deletions contracts/interfaces/gov/user-keeper/IGovUserKeeper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,13 @@ interface IGovUserKeeper {
address delegator,
address delegatee
) external view returns (uint256 delegatedPower);

/// @notice The function for getting the wrapped token amount, not covered by ether
/// @param value the ether value sent alongside the call
/// @param amount the total amount of wrapped ether with 18 decimals
/// @return nativeAmount the amount of wrapped ether with native decimals minus ether value
function getAmountWithNativeDecimals(
uint256 value,
uint256 amount
) external view returns (uint256 nativeAmount);
}
6 changes: 5 additions & 1 deletion contracts/libs/utils/TokenBalance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ library TokenBalance {
uint256 amount,
TransferType transferType
) internal returns (uint256) {
if (amount == 0) {
return 0;
}

uint256 balance = normThisBalance(token);

require(balance >= amount || transferType == TransferType.TryMint, "Insufficient funds");
Expand Down Expand Up @@ -57,7 +61,7 @@ library TokenBalance {
}

function sendFunds(IERC20 token, address receiver, uint256 amount) internal {
token.safeTransfer(receiver, amount.from18(address(token)));
token.safeTransfer(receiver, amount.from18Safe(address(token)));
}

function thisBalance(address token) internal view returns (uint256) {
Expand Down
29 changes: 26 additions & 3 deletions test/gov/GovPool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -693,14 +693,26 @@ describe("GovPool", () => {
});

it("cant deposit ether if gov token is not native", async () => {
await truffleAssert.reverts(govPool.deposit(wei("100"), [], { value: 100 }), "GovUK: not native token pool");
await truffleAssert.reverts(
govPool.deposit(wei("100"), [], { value: 100 }),
"GovUK: should not send ether if Gov token is not native",
);
});

it("cant overdeposit ether", async () => {
await switchWeth(0, token.address);

await truffleAssert.reverts(
govPool.deposit(1, [1, 2, 3], { value: 2 }),
"Gov: value is greater than amount to transfer",
"GovUK: ether value is greater than amount",
);

await truffleAssert.reverts(
govPool.deposit(0, [1, 2, 3], { value: 1 }),
"DecimalsConverter: conversion failed",
);

await switchWeth(0, weth.address);
});

it("could deposit ether", async () => {
Expand Down Expand Up @@ -3660,6 +3672,13 @@ describe("GovPool", () => {
await truffleAssert.reverts(delegateTreasury(THIRD, "0", []), "Gov: empty delegation");
});

it("should not delegate treasury if incorrect amount and value", async () => {
await truffleAssert.reverts(
delegateTreasury(THIRD, "0", [11], wei("1")),
"GovUK: should not send ether if Gov token is not native",
);
});

it("should create proposal for delegateTreasury and undelegateTreasury", async () => {
assert.equal((await token.balanceOf(THIRD)).toFixed(), "0");
assert.equal((await nft.balanceOf(THIRD)).toFixed(), "0");
Expand Down Expand Up @@ -3757,7 +3776,7 @@ describe("GovPool", () => {

await truffleAssert.reverts(
delegateTreasury(THIRD, wei("100"), [], wei("200")),
"Gov: value is greater than amount to transfer",
"GovUK: ether value is greater than amount",
);

await delegateTreasury(THIRD, wei("100"), [], wei("100"));
Expand Down Expand Up @@ -5283,6 +5302,10 @@ describe("GovPool", () => {
await govPool.transferCreditAmount([CREDIT_TOKEN_1.address], ["1000"], SECOND, { from: VALIDATORS });

assert.equal((await CREDIT_TOKEN_1.balanceOf(SECOND)).toFixed(), "1000");

await govPool.transferCreditAmount([CREDIT_TOKEN_1.address], ["0"], SECOND, { from: VALIDATORS });

assert.equal((await CREDIT_TOKEN_1.balanceOf(SECOND)).toFixed(), "1000");
});

it("cant get more than month limit", async () => {
Expand Down

0 comments on commit 3eeae7c

Please sign in to comment.