Skip to content

Commit

Permalink
Merge pull request #192 from dexe-network/feature/nativeCoin
Browse files Browse the repository at this point in the history
Feature/native coin
  • Loading branch information
todesstille authored Apr 18, 2024
2 parents 0a479dc + 7799a39 commit dac37d0
Show file tree
Hide file tree
Showing 36 changed files with 591 additions and 49 deletions.
26 changes: 26 additions & 0 deletions contracts/core/ContractsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract ContractsRegistry is IContractsRegistry, MultiOwnableContractsRegistry,
string public constant POOL_REGISTRY_NAME = "POOL_REGISTRY";

string public constant DEXE_NAME = "DEXE";
string public constant WETH_NAME = "WETH";
string public constant USD_NAME = "USD";
string public constant BABT_NAME = "BABT";
string public constant DEXE_EXPERT_NFT_NAME = "DEXE_EXPERT_NFT";
Expand All @@ -27,6 +28,7 @@ contract ContractsRegistry is IContractsRegistry, MultiOwnableContractsRegistry,
string public constant TREASURY_NAME = "TREASURY";

string public constant CORE_PROPERTIES_NAME = "CORE_PROPERTIES";
string public constant NETWORK_PROPERTIES_NAME = "NETWORK_PROPERTIES";

string public constant SPHEREX_ENGINE_NAME = "SPHEREX_ENGINE";
string public constant POOL_SPHEREX_ENGINE_NAME = "POOL_SPHEREX_ENGINE";
Expand All @@ -42,6 +44,22 @@ contract ContractsRegistry is IContractsRegistry, MultiOwnableContractsRegistry,
_setSphereXEngine(CORE_PROPERTIES_NAME, sphereXEngine);
}

function addContracts(
string[] calldata names_,
address[] calldata contractAddresses_
) external onlyOwner {
uint256 length = names_.length;

require(
contractAddresses_.length == length,
"Contracts Registry: names and addresses lengths don't match"
);

for (uint256 i = 0; i < length; i++) {
_addContract(names_[i], contractAddresses_[i]);
}
}

function protectContractFunctions(
string calldata contractName,
bytes4[] calldata selectors
Expand Down Expand Up @@ -72,6 +90,10 @@ contract ContractsRegistry is IContractsRegistry, MultiOwnableContractsRegistry,
return getContract(DEXE_NAME);
}

function getWETHContract() external view override returns (address) {
return getContract(WETH_NAME);
}

function getUSDContract() external view override returns (address) {
return getContract(USD_NAME);
}
Expand All @@ -88,6 +110,10 @@ contract ContractsRegistry is IContractsRegistry, MultiOwnableContractsRegistry,
return getContract(CORE_PROPERTIES_NAME);
}

function getNetworkPropertiesContract() external view override returns (address) {
return getContract(NETWORK_PROPERTIES_NAME);
}

function getBABTContract() external view override returns (address) {
return getContract(BABT_NAME);
}
Expand Down
12 changes: 12 additions & 0 deletions contracts/core/network-properties/BSCProperties.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "../../interfaces/core/INetworkProperties.sol";

contract BSCProperties is INetworkProperties {
uint256 private constant BNB_SUPPLY = 150_000_000 * 10 ** 18;

function getNativeSupply() external view override returns (uint256) {
return BNB_SUPPLY;
}
}
4 changes: 2 additions & 2 deletions contracts/factory/PoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ contract PoolFactory is IPoolFactory, AbstractPoolFactory {
TokenSaleProposal(tokenSaleProxy).__TokenSaleProposal_init(poolProxy);

GovSettings(govPoolDeps.settingsAddress).transferOwnership(poolProxy);
GovUserKeeper(govPoolDeps.userKeeperAddress).transferOwnership(poolProxy);
GovUserKeeper(payable(govPoolDeps.userKeeperAddress)).transferOwnership(poolProxy);
GovValidators(govPoolDeps.validatorsAddress).transferOwnership(poolProxy);
ERC721Expert(govPoolDeps.expertNftAddress).transferOwnership(poolProxy);
ERC721Multiplier(govPoolDeps.nftMultiplierAddress).transferOwnership(poolProxy);
Expand Down Expand Up @@ -214,7 +214,7 @@ contract PoolFactory is IPoolFactory, AbstractPoolFactory {
parameters.validatorsParams.validators,
parameters.validatorsParams.balances
);
GovUserKeeper(govPoolDeps.userKeeperAddress).__GovUserKeeper_init(
GovUserKeeper(payable(govPoolDeps.userKeeperAddress)).__GovUserKeeper_init(
parameters.userKeeperParams.tokenAddress,
parameters.userKeeperParams.nftAddress,
parameters.userKeeperParams.individualPower,
Expand Down
29 changes: 24 additions & 5 deletions contracts/gov/GovPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ contract GovPool is
_babt = ISBT721(registry.getBABTContract());
_dexeExpertNft = IERC721Expert(registry.getDexeExpertNftContract());
_poolRegistry = registry.getPoolRegistryContract();

IGovUserKeeper(_govUserKeeper).setDependencies(contractsRegistry, bytes(""));
}

function unlock(address user) external override onlyBABTHolder {
Expand All @@ -156,12 +158,19 @@ contract GovPool is
_proposals.execute(proposalId);
}

function deposit(uint256 amount, uint256[] calldata nftIds) external override onlyBABTHolder {
function deposit(
uint256 amount,
uint256[] calldata nftIds
) external payable override onlyBABTHolder {
require(amount > 0 || nftIds.length > 0, "Gov: empty deposit");
_checkValue(amount);

_lockBlock(DEPOSIT_WITHDRAW, msg.sender);

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

_govUserKeeper.depositNfts.exec(msg.sender, nftIds);

emit Deposited(amount, nftIds, msg.sender);
Expand Down Expand Up @@ -262,9 +271,10 @@ contract GovPool is
address delegatee,
uint256 amount,
uint256[] calldata nftIds
) external override onlyThis {
) 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);

Expand All @@ -273,9 +283,14 @@ contract GovPool is
if (amount != 0) {
address token = _govUserKeeper.tokenAddress();

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

_govUserKeeper.delegateTokensTreasury(delegatee, amount);
_govUserKeeper.delegateTokensTreasury{value: msg.value}(delegatee, amount);
}

if (nftIds.length != 0) {
Expand Down Expand Up @@ -615,4 +630,8 @@ 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");
}
}
83 changes: 73 additions & 10 deletions contracts/gov/user-keeper/GovUserKeeper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import "@solarity/solidity-lib/libs/arrays/Paginator.sol";
import "@solarity/solidity-lib/libs/arrays/ArrayHelper.sol";
import "@solarity/solidity-lib/libs/data-structures/memory/Vector.sol";

import "@uniswap/v2-periphery/contracts/interfaces/IWETH.sol";

import "../../interfaces/core/IContractsRegistry.sol";
import "../../interfaces/core/INetworkProperties.sol";
import "../../interfaces/gov/user-keeper/IGovUserKeeper.sol";
import "../../interfaces/gov/IGovPool.sol";
import "../../interfaces/gov/ERC721/powers/IERC721Power.sol";
Expand All @@ -40,6 +44,9 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad

mapping(uint256 => uint256) internal _nftLockedNums; // tokenId => locked num

address public wethAddress;
address public networkPropertiesAddress;

event SetERC20(address token);
event SetERC721(address token);

Expand Down Expand Up @@ -73,16 +80,31 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
}
}

function setDependencies(address contractsRegistry, bytes memory) external onlyOwner {
IContractsRegistry registry = IContractsRegistry(contractsRegistry);

wethAddress = registry.getWETHContract();
networkPropertiesAddress = registry.getNetworkPropertiesContract();
}

function depositTokens(
address payer,
address receiver,
uint256 amount
) external override onlyOwner withSupportedToken {
) external payable override onlyOwner withSupportedToken {
address token = tokenAddress;
uint256 fullAmount = amount;

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

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

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

function withdrawTokens(
Expand All @@ -93,7 +115,6 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
UserInfo storage payerInfo = _usersInfo[payer];
BalanceInfo storage payerBalanceInfo = payerInfo.balances[IGovPool.VoteType.PersonalVote];

address token = tokenAddress;
uint256 balance = payerBalanceInfo.tokens;
uint256 maxTokensLocked = payerInfo.maxTokensLocked;

Expand All @@ -104,7 +125,7 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad

payerBalanceInfo.tokens = balance - amount;

IERC20(token).safeTransfer(receiver, amount.from18Safe(token));
_sendNativeOrToken(receiver, amount);
}

function delegateTokens(
Expand Down Expand Up @@ -134,7 +155,11 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
function delegateTokensTreasury(
address delegatee,
uint256 amount
) external override onlyOwner withSupportedToken {
) external payable override onlyOwner withSupportedToken {
if (msg.value != 0) {
_wrapNative(msg.value);
}

_usersInfo[delegatee].balances[IGovPool.VoteType.TreasuryVote].tokens += amount;
}

Expand Down Expand Up @@ -173,9 +198,7 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad

delegateeBalanceInfo.tokens = balance - amount;

address token = tokenAddress;

IERC20(token).safeTransfer(msg.sender, amount.from18Safe(token));
_sendNativeOrToken(msg.sender, amount);
}

function depositNfts(
Expand Down Expand Up @@ -477,6 +500,8 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
_setERC721Address(_nftAddress, individualPower, nftsTotalSupply);
}

receive() external payable {}

function nftAddress() external view override returns (address) {
return _nftInfo.nftAddress;
}
Expand Down Expand Up @@ -516,6 +541,11 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
}

ownedBalance = ERC20(tokenAddress).balanceOf(voter).to18(tokenAddress);

if (_isWrapped()) {
ownedBalance += address(voter).balance;
}

totalBalance += ownedBalance;
}

Expand Down Expand Up @@ -601,7 +631,11 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
address token = tokenAddress;

if (token != address(0)) {
power = IERC20(token).totalSupply().to18(token);
if (_isWrapped()) {
power = INetworkProperties(networkPropertiesAddress).getNativeSupply();
} else {
power = IERC20(token).totalSupply().to18(token);
}
}

token = _nftInfo.nftAddress;
Expand Down Expand Up @@ -715,6 +749,19 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
);
}

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

if (_isWrapped()) {
_unwrapNative(amount);

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

function _cleanDelegatee(UserInfo storage delegatorInfo, address delegatee) internal {
BalanceInfo storage delegatedBalance = delegatorInfo.delegatedBalances[delegatee];

Expand Down Expand Up @@ -780,4 +827,20 @@ contract GovUserKeeper is IGovUserKeeper, OwnableUpgradeable, ERC721HolderUpgrad
function _withSupportedNft() internal view {
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 _unwrapNative(uint256 value) internal {
IWETH(wethAddress).withdraw(value);
}

function _isWrapped() internal view returns (bool) {
address _wethAddress = wethAddress;

return _wethAddress != address(0) && wethAddress == tokenAddress;
}
}
8 changes: 8 additions & 0 deletions contracts/interfaces/core/IContractsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ interface IContractsRegistry {
/// @return DEXE token contract address
function getDEXEContract() external view returns (address);

/// @notice Used in dependency injection mechanism
/// @return Wrapped native coin contract address
function getWETHContract() external view returns (address);

/// @notice Used in dependency injection mechanism
/// @return Platform's native USD token contract address. This may be USDT/BUSD/USDC/DAI/FEI
function getUSDContract() external view returns (address);
Expand All @@ -39,6 +43,10 @@ interface IContractsRegistry {
/// @return CoreProperties contract address
function getCorePropertiesContract() external view returns (address);

/// @notice Used in dependency injection mechanism
/// @return NetworkProperties contract address
function getNetworkPropertiesContract() external view returns (address);

/// @notice Used in dependency injection mechanism
/// @return BABT contract address
function getBABTContract() external view returns (address);
Expand Down
8 changes: 8 additions & 0 deletions contracts/interfaces/core/INetworkProperties.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface INetworkProperties {
/// @notice Used in native coin governance mechanism
/// @return The current full supply of native coin
function getNativeSupply() external view returns (uint256);
}
4 changes: 2 additions & 2 deletions contracts/interfaces/gov/IGovPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ interface IGovPool {
/// @notice The function for depositing tokens to the pool
/// @param amount the erc20 deposit amount
/// @param nftIds the array of nft ids to deposit
function deposit(uint256 amount, uint256[] calldata nftIds) external;
function deposit(uint256 amount, uint256[] calldata nftIds) external payable;

/// @notice The function for withdrawing deposited tokens
/// @param receiver the withdrawal receiver address
Expand All @@ -383,7 +383,7 @@ interface IGovPool {
address delegatee,
uint256 amount,
uint256[] calldata nftIds
) external;
) external payable;

/// @notice The function for undelegating delegated tokens
/// @param delegatee the undelegation target address (person who will be undelegated)
Expand Down
Loading

0 comments on commit dac37d0

Please sign in to comment.