diff --git a/.env.example b/.env.example index 32dc6d1e..ef4fcd9c 100644 --- a/.env.example +++ b/.env.example @@ -13,4 +13,4 @@ COINMARKETCAP_KEY = "COINMARKETCAP API KEY" TYPECHAIN_TARGET = "TYPECHAIN TARGET" # Environment -ENVIRONMENT = "PROD|STAGE|DEV|STAGE_SEPOLIA|DEV_SEPOLIA|DEV_AMOY|DEV_OPTIMISM|DEV_BASE" +ENVIRONMENT = "PROD|STAGE|DEV|PROD_ETH|STAGE_SEPOLIA|DEV_SEPOLIA|DEV_AMOY|DEV_OPTIMISM|DEV_BASE" diff --git a/contracts/mock/tokens/BABTMockOwnableUpgradeable.sol b/contracts/mock/tokens/BABTMockOwnableUpgradeable.sol new file mode 100644 index 00000000..75cb286f --- /dev/null +++ b/contracts/mock/tokens/BABTMockOwnableUpgradeable.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "../../interfaces/core/ISBT721.sol"; + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +contract BABTMockOwnableUpgradeable is ISBT721, Initializable, UUPSUpgradeable { + mapping(uint256 => address) private _ownerMap; + mapping(address => uint256) private _tokenMap; + + uint256 private _tokenId; + + address public owner; + + modifier onlyOwner() { + require(msg.sender == owner, "Ownable: caller is not the owner"); + _; + } + + function __BABTMock_init() external initializer { + owner = msg.sender; + } + + function attest(address to) external onlyOwner returns (uint256) { + require(to != address(0), "Address is empty"); + require(_tokenMap[to] == 0, "SBT already exists"); + + uint256 tokenId = _tokenId; + tokenId++; + + _tokenMap[to] = tokenId; + _ownerMap[tokenId] = to; + + emit Attest(to, tokenId); + emit Transfer(address(0), to, tokenId); + + _tokenId = tokenId; + return tokenId; + } + + function revoke(address from) external onlyOwner { + require(from != address(0), "Address is empty"); + require(_tokenMap[from] > 0, "The account does not have any SBT"); + + uint256 tokenId = _tokenMap[from]; + + _tokenMap[from] = 0; + _ownerMap[tokenId] = address(0); + + emit Revoke(from, tokenId); + emit Transfer(from, address(0), tokenId); + } + + function burn() external { + require(_tokenMap[msg.sender] > 0, "The account does not have any SBT"); + + uint256 tokenId = _tokenMap[msg.sender]; + + _tokenMap[msg.sender] = 0; + _ownerMap[tokenId] = address(0); + + emit Burn(msg.sender, tokenId); + emit Transfer(msg.sender, address(0), tokenId); + } + + function balanceOf(address owner) external view returns (uint256) { + return _tokenMap[owner] > 0 ? 1 : 0; + } + + function tokenIdOf(address from) external view returns (uint256) { + require(_tokenMap[from] > 0, "The wallet has not attested any SBT"); + return _tokenMap[from]; + } + + function ownerOf(uint256 tokenId) external view returns (address) { + require(_ownerMap[tokenId] != address(0), "Invalid tokenId"); + return _ownerMap[tokenId]; + } + + function totalSupply() external view returns (uint256) { + return _tokenId; + } + + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} +} diff --git a/deploy/config/configs/prod-ethereum.conf.js b/deploy/config/configs/prod-ethereum.conf.js new file mode 100644 index 00000000..0b374d0a --- /dev/null +++ b/deploy/config/configs/prod-ethereum.conf.js @@ -0,0 +1,194 @@ +const { ZERO_ADDR, PRECISION } = require("../../../scripts/utils/constants.js"); +const { wei } = require("../../../scripts/utils/utils.js"); + +const { getBytesPolynomialPowerInit } = require("../utils.js"); + +const owners = ["0x04130F8679394e3A8d55568F2189c3F3BF48ecbb"]; + +const tokens = { + DEXE: "0xde4EE8057785A7e8e800Db58F9784845A5C2Cbd6", + BUSD: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + USDT: "0xdac17f958d2ee523a2206206994597c13d831ec7", + BABT: "0x0000000000000000000000000000000000000000", + WBNB: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", +}; + +const uniswap = { + router: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", + quoter: "0x61fFE014bA17989E743c5F6cB21bF9697530B21e", +}; + +const NETWORK_PROPERTIES_CONTRACT_NAME = "ETHProperties"; + +const DEXE_DAO_NAME = "DeXe Protocol"; + +const DOCUMENT_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; + +const DEFAULT_CORE_PROPERTIES = { + govVotesLimit: 50, + govCommissionPercentage: PRECISION.times(30).toFixed(), + tokenSaleProposalCommissionPercentage: PRECISION.toFixed(), + micropoolVoteRewardsPercentage: PRECISION.times(20).toFixed(), + treasuryVoteRewardsPercentage: PRECISION.times(1.618).toFixed(), +}; + +const DEFAULT_POOL_TYPES = [ + ["0", uniswap.router, "0"], + ["1", uniswap.quoter, "100"], + ["1", uniswap.quoter, "500"], + ["1", uniswap.quoter, "3000"], + ["1", uniswap.quoter, "10000"], +]; + +const POOL_PARAMETERS = { + settingsParams: { + proposalSettings: [ + { + earlyCompletion: true, + delegatedVotingAllowed: false, + validatorsVote: false, + duration: 432000, // 5 days + durationValidators: 432000, // 5 days + quorum: PRECISION.times("5").toFixed(), // 5% + quorumValidators: PRECISION.times("51").toFixed(), // 51% + minVotesForVoting: wei("13"), // 13 votes + minVotesForCreating: wei("10000"), // 10000 votes + executionDelay: 1800, // 30 mins + rewardsInfo: { + rewardToken: ZERO_ADDR, + creationReward: 0, + executionReward: 0, + voteRewardsCoefficient: 0, + }, + executorDescription: "default", + }, + { + earlyCompletion: true, + delegatedVotingAllowed: false, + validatorsVote: false, + duration: 432000, // 5 days + durationValidators: 432000, // 5 days + quorum: PRECISION.times("5").toFixed(), // 5% + quorumValidators: PRECISION.times("51").toFixed(), // 51% + minVotesForVoting: wei("13"), // 13 votes + minVotesForCreating: wei("10000"), // 10000 votes + executionDelay: 1800, // 30 mins + rewardsInfo: { + rewardToken: ZERO_ADDR, + creationReward: 0, + executionReward: 0, + voteRewardsCoefficient: 0, + }, + executorDescription: "internal", + }, + { + earlyCompletion: true, + delegatedVotingAllowed: false, + validatorsVote: false, + duration: 432000, // 5 days + durationValidators: 432000, // 5 days + quorum: PRECISION.times("5").toFixed(), // 5% + quorumValidators: PRECISION.times("51").toFixed(), // 51% + minVotesForVoting: wei("13"), // 13 votes + minVotesForCreating: wei("10000"), // 10000 votes + executionDelay: 1800, // 30 mins + rewardsInfo: { + rewardToken: ZERO_ADDR, + creationReward: 0, + executionReward: 0, + voteRewardsCoefficient: 0, + }, + executorDescription: "validators", + }, + ], + additionalProposalExecutors: [], + }, + validatorsParams: { + name: "DEXE Validator Token", + symbol: "DEXEVT", + proposalSettings: { + duration: 432000, // 5 days + executionDelay: 1800, // 30 mins + quorum: PRECISION.times("51").toFixed(), // 51% + }, + validators: [], + balances: [], + }, + userKeeperParams: { + tokenAddress: tokens.DEXE, + nftAddress: ZERO_ADDR, + individualPower: 0, + nftsTotalSupply: 0, + }, + tokenParams: { + name: "", + symbol: "", + users: [], + cap: 0, + mintedTotal: 0, + amounts: [], + }, + votePowerParams: { + voteType: 1, + initData: getBytesPolynomialPowerInit(PRECISION.times("1.08"), PRECISION.times("0.92"), PRECISION.times("0.97")), + presetAddress: ZERO_ADDR, + }, + verifier: ZERO_ADDR, + onlyBABTHolders: false, + descriptionURL: "", + name: DEXE_DAO_NAME, +}; + +const DP_SETTINGS = { + earlyCompletion: true, + delegatedVotingAllowed: true, + validatorsVote: false, + duration: 432000, // 5 days + durationValidators: 432000, // 5 days + quorum: PRECISION.times("5").toFixed(), // 5% + quorumValidators: PRECISION.times("51").toFixed(), // 51% + minVotesForVoting: wei("13"), // 13 votes + minVotesForCreating: wei("10000"), // 10000 votes + executionDelay: 1800, // 30 mins + rewardsInfo: { + rewardToken: ZERO_ADDR, + creationReward: 0, + executionReward: 0, + voteRewardsCoefficient: 0, + }, + executorDescription: "distribution-proposal", +}; + +const TOKENSALE_SETTINGS = { + earlyCompletion: true, + delegatedVotingAllowed: false, + validatorsVote: false, + duration: 432000, // 5 days + durationValidators: 432000, // 5 days + quorum: PRECISION.times("5").toFixed(), // 5% + quorumValidators: PRECISION.times("51").toFixed(), // 51% + minVotesForVoting: wei("13"), // 13 votes + minVotesForCreating: wei("10000"), // 10000 votes + executionDelay: 1800, // 30 mins + rewardsInfo: { + rewardToken: ZERO_ADDR, + creationReward: 0, + executionReward: 0, + voteRewardsCoefficient: 0, + }, + executorDescription: "tokensale-proposal", +}; + +module.exports = { + owners, + tokens, + uniswap, + NETWORK_PROPERTIES_CONTRACT_NAME, + DEXE_DAO_NAME, + DOCUMENT_HASH, + DEFAULT_CORE_PROPERTIES, + DEFAULT_POOL_TYPES, + POOL_PARAMETERS, + DP_SETTINGS, + TOKENSALE_SETTINGS, +}; diff --git a/deploy/config/utils.js b/deploy/config/utils.js index ecf05840..ae4985b1 100644 --- a/deploy/config/utils.js +++ b/deploy/config/utils.js @@ -11,6 +11,10 @@ const getConfig = () => { return require("./configs/dev.conf.js"); } + if (process.env.ENVIRONMENT == "PROD_ETH") { + return require("./configs/prod-ethereum.conf.js"); + } + if (process.env.ENVIRONMENT == "STAGE_SEPOLIA") { return require("./configs/stage-sepolia.conf.js"); } diff --git a/package.json b/package.json index a8b842f8..d11df17a 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "private-network": "npx hardhat node", "private-network-fork": "npx hardhat node --fork https://mainnet.infura.io/v3/$(grep INFURA_KEY .env | cut -d '\"' -f2)", "deploy-dev": "npx hardhat migrate --network localhost", + "deploy-ethereum": "npx hardhat migrate --network ethereum --verify", "deploy-sepolia": "npx hardhat migrate --network sepolia --verify", "deploy-amoy": "npx hardhat migrate --network amoy --verify", "deploy-chapel": "npx hardhat migrate --network chapel --verify",