diff --git a/contracts/ERC.sol b/contracts/ERC.sol new file mode 100644 index 0000000..5f5bb4a --- /dev/null +++ b/contracts/ERC.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.15; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract ERC is ERC20 { + constructor(string memory name, string memory symbol) ERC20(name, symbol) { + + } + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } +} diff --git a/contracts/interfaces/IPancake.sol b/contracts/interfaces/IPancakeSwapPair.sol similarity index 100% rename from contracts/interfaces/IPancake.sol rename to contracts/interfaces/IPancakeSwapPair.sol diff --git a/contracts/market.sol b/contracts/market.sol index 4e474d8..8151a0b 100644 --- a/contracts/market.sol +++ b/contracts/market.sol @@ -18,6 +18,8 @@ contract Marketplace is Initializable { address payable seller; uint256 tokenId; uint256 price; + bool bought; + bool cancelled; } mapping(uint256 => Sale) saleIdToSale; @@ -48,22 +50,22 @@ contract Marketplace is Initializable { //modifiers modifier isExistingSale(uint256 saleId) { - require(saleIdToSale[saleId].price != 0); + require(saleIdToSale[saleId].price != 0, "!exists"); _; } modifier onlySaleOwner(uint256 saleId) { - require(saleIdToSale[saleId].seller == msg.sender); + require(saleIdToSale[saleId].seller == msg.sender, "!seller"); _; } modifier onlyValidPrice(uint256 price) { - require(price > 0); + require(price > 0, "!price"); _; } modifier onlyAdmin() { - require(treasury.isAdmin(msg.sender)); + require(treasury.isAdmin(msg.sender), "!admin"); _; } @@ -105,7 +107,7 @@ contract Marketplace is Initializable { onlyValidPrice(price) { currentSaleId++; - Sale memory sale = saleIdToSale[currentSaleId]; + Sale storage sale = saleIdToSale[currentSaleId]; sale.seller = payable(msg.sender); sale.price = price; sale.tokenId = tokenId; @@ -114,9 +116,11 @@ contract Marketplace is Initializable { } function cancelSale(uint256 saleId) public onlySaleOwner(saleId) { - Sale memory sale = saleIdToSale[saleId]; + Sale storage sale = saleIdToSale[saleId]; + require(!sale.bought, "bought"); + require(!sale.cancelled, "cancelled"); nft.transferFrom(address(this), msg.sender, sale.tokenId); - delete sale; + sale.cancelled = true; emit SaleCancelled(saleId); } @@ -126,22 +130,27 @@ contract Marketplace is Initializable { onlyValidPrice(price) isExistingSale(saleId) { - Sale memory sale = saleIdToSale[saleId]; + Sale storage sale = saleIdToSale[saleId]; + require(!sale.bought, "bought"); + require(!sale.cancelled, "cancelled"); uint256 oldPrice = sale.price; sale.price = price; emit SaleUpdated(saleId, oldPrice, price); } function buyToken(uint256 saleId) public isExistingSale(saleId) { - Sale memory sale = saleIdToSale[saleId]; + Sale storage sale = saleIdToSale[saleId]; + require(!sale.bought, "bought"); + require(!sale.cancelled, "cancelled"); nft.transferFrom(address(this), msg.sender, sale.tokenId); _distributeFunds(sale.price, sale.seller); + sale.bought = true; emit TokenBought(saleId, msg.sender, sale.tokenId, sale.price); } //admin functions function changeFees(uint256 _fee) public onlyAdmin { - require(_fee > 0 && _fee < 2000); + require(_fee > 0 && _fee < 2000, "wrong arg"); emit FeesChanged(msg.sender, fee, _fee); fee = _fee; } diff --git a/contracts/nft.sol b/contracts/nft.sol index 951ade5..8ff315d 100644 --- a/contracts/nft.sol +++ b/contracts/nft.sol @@ -7,8 +7,9 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeab import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/Base64Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/ITreasury.sol"; -import "./interfaces/IPancake.sol"; +import "./interfaces/IPancakeSwapPair.sol"; import "./mixins/signature-control.sol"; contract NFT is ERC721EnumerableUpgradeable, SignatureControl { @@ -16,7 +17,7 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { using SafeERC20Upgradeable for IERC20Upgradeable; //variables - bool pause = true; + bool pause; uint256 nonce; ITreasury treasury; IERC20Upgradeable BoM; @@ -40,7 +41,8 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { //mint prices, caps, addresses of reward tokens(shiba,floki,doggy,doge) uint256[4] prices = [ - 300 * 10**18, + .001 ether, +// 300 * 10**18, 250 * 10**18, 200 * 10**18, 250 * 10**18 @@ -51,9 +53,9 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { uint256[4] nftCaps = [1000, 1500, 2000, 1500]; address[4] public rewardTokens = [ 0x0000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000, - 0x0000000000000000000000000000000000000000 + 0x0000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000003 ]; mapping(address => uint256) addressToType; mapping(address => uint256) totalRatesForType; @@ -123,43 +125,43 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { //modifiers modifier onlyAdmin() { - require(treasury.isAdmin(msg.sender)); + require(treasury.isAdmin(msg.sender), "!admin"); _; } modifier isUnpaused() { - require(!pause); + require(!pause, "paused"); _; } modifier isValidWhitelistMint(uint256 amount, uint256 tokenType) { - require(isPresale); - require(isWhitelisted[msg.sender]); + require(isPresale, "!presale"); + require(isWhitelisted[msg.sender], "!whitelisted"); require( mintedOnWhitelist[msg.sender] + amount <= - maxMintPerAddressDuringWhitelist + maxMintPerAddressDuringWhitelist, "maxMint exceeded" ); - require(tokenType <= 3); + require(tokenType <= 3, "!tokenType"); require( whitelistMintCapOfToken[tokenType] + amount <= - whitelistMintCapPerType + whitelistMintCapPerType, "mintCap exceeded" ); _; } modifier isValidMint(uint256 amount, uint256 tokenType) { - require(!isPresale); - require(tokenType <= 3); + require(!isPresale, "(mint) presale"); + require(tokenType <= 3, "!tokenType"); require(mintCapOfToken[tokenType] + amount <= nftCaps[tokenType]); _; } modifier isValidCombine(uint256[] memory tokenIds) { - require(tokenIds.length > 1 && tokenIds.length <= 4); + require(tokenIds.length > 1 && tokenIds.length <= 4, "wrong tokenIds length"); bool hasDupes; for (uint256 i = 0; i < tokenIds.length; i++) { - require(ownerOf(tokenIds[i]) == msg.sender); - require(tokenIdToType[tokenIds[i]].length == 1); + require(ownerOf(tokenIds[i]) == msg.sender, "!owner"); + require(tokenIdToType[tokenIds[i]].length == 1, "!tokenIdToType"); for (uint256 index = i; index < tokenIds.length; index++) { if ( index != i && @@ -169,7 +171,7 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { hasDupes = true; } } - require(!hasDupes); + require(!hasDupes, "dupes"); } _; } @@ -230,9 +232,10 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { { for (uint256 i = 0; i < amount; i++) { supply++; - _mint(msg.sender, supply); + tokenIdToInfo[supply].tokens.push(rewardTokens[tokenType]); tokenIdToType[supply].push(rewardTokens[tokenType]); uint256 rate = createTokenStats(supply); + _mint(msg.sender, supply); emit TokenMinted(msg.sender, supply, rewardTokens[tokenType], rate); } mintedOnWhitelist[msg.sender] += amount; @@ -249,9 +252,10 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { { for (uint256 i = 0; i < amount; i++) { supply++; - _mint(msg.sender, supply); tokenIdToInfo[supply].tokens.push(rewardTokens[tokenType]); + tokenIdToType[supply].push(rewardTokens[tokenType]); uint256 rate = createTokenStats(supply); + _mint(msg.sender, supply); emit TokenMinted(msg.sender, supply, rewardTokens[tokenType], rate); } mintCapOfToken[tokenType] += amount; @@ -264,15 +268,15 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { payable isUnpaused { - require(msg.value == 0.05 ether); + require(msg.value == 0.05 ether, "!value"); supply++; uint256 price; - _mint(msg.sender, supply); address[] memory tokens = new address[](tokenIds.length); for (uint256 i = 0; i < tokenIds.length; i++) { - TokenInfo storage token = tokenIdToInfo[tokenIds[i]]; + TokenInfo memory token = tokenIdToInfo[tokenIds[i]]; address intermediateStorageForToken = tokenIdToType[tokenIds[i]][0]; tokenIdToInfo[supply].tokens.push(intermediateStorageForToken); + tokenIdToType[supply].push(intermediateStorageForToken); tokens[i] = intermediateStorageForToken; _burn(tokenIds[i]); price += tokenToPrices[tokenIdToType[tokenIds[i]][0]] / 4; @@ -281,7 +285,9 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { } } uint256 rate = createTokenStats(supply); + _mint(msg.sender, supply); emit TokenCombined(msg.sender, tokenIds, tokens, supply, rate); + //TBD: calculate price with usd in mind _distributeFunds(price); } @@ -455,7 +461,7 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { address path0, address path1 ) internal view returns (uint256[] memory) { - address[] memory path; + address[] memory path = new address[](2); path[0] = path0; path[1] = path1; return swapRouter.getAmountsIn(price, path); @@ -467,7 +473,8 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { address path0, address path1 ) internal returns (uint256[] memory) { - address[] memory path; + IERC20(path0).approve(address(swapRouter), 2**256-1); + address[] memory path = new address[](2); path[0] = path0; path[1] = path1; return @@ -606,10 +613,11 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { function _addToPool(uint256 amount) internal { uint256 lotteryPoolAmount = amount / 10; - address[] memory path; + address[] memory path = new address[](2); path[0] = address(BoM); - path[1] = address(BUSD); + + IERC20(address(BoM)).approve(address(swapRouter), amount); uint256 swappedFor = swapRouter.swapExactTokensForTokens( lotteryPoolAmount, // 10% to lottery 0, @@ -637,38 +645,38 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { emit RewardPoolRaised(swappedFor); } - function _afterTokenTransfer( - address from, - address to, - uint256 tokenId - ) internal virtual override { - super._afterTokenTransfer(from, to, tokenId); - TokenInfo memory info = tokenIdToInfo[tokenId]; - if (from != address(0)) { - if (ERC721Upgradeable.balanceOf(from) == 0) { - _holders.remove(from); - } - if (info.tokens.length > 1) { - totalShares[4] -= info.rate; - accountShares[from][4] -= info.rate; - } else { - uint256 idx = addressToType[info.tokens[0]]; - totalShares[idx] -= info.rate; - accountShares[from][idx] -= info.rate; - } - } - if (to != address(0)) { - _holders.add(to); - if (info.tokens.length > 1) { - totalShares[4] += info.rate; - accountShares[to][4] += info.rate; - } else { - uint256 idx = addressToType[info.tokens[0]]; - totalShares[idx] += info.rate; - accountShares[from][idx] += info.rate; - } - } - } +// function _afterTokenTransfer( +// address from, +// address to, +// uint256 tokenId +// ) internal virtual override { +// super._afterTokenTransfer(from, to, tokenId); +// TokenInfo memory info = tokenIdToInfo[tokenId]; +// if (from != address(0)) { +// if (ERC721Upgradeable.balanceOf(from) == 0) { +// _holders.remove(from); +// } +// if (info.tokens.length > 1) { +// totalShares[4] -= info.rate; +// accountShares[from][4] -= info.rate; +// } else { +// uint256 idx = addressToType[info.tokens[0]]; +// totalShares[idx] -= info.rate; +// accountShares[from][idx] -= info.rate; +// } +// } +// if (to != address(0)) { +// _holders.add(to); +// if (info.tokens.length > 1) { +//// totalShares[4] += info.rate; +//// accountShares[to][4] += info.rate; +// } else { +//// uint256 idx = addressToType[info.tokens[0]]; +//// totalShares[idx] += info.rate; +//// accountShares[to][idx] += info.rate; +// } +// } +// } function pendingReward(uint256 idx, address account) public view returns (uint256) { return accountShares[account][idx] + (_rewardPerShare(idx) - accountRewardsPerTokenPaid[account][idx]) / 1e18 + accountRewards[account][idx]; @@ -697,7 +705,8 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { require(reward > 0, "nothing to claim"); accountRewards[msg.sender][idx] = 0; - address[] memory path; + IERC20(address(WETH)).approve(address(swapRouter), reward); + address[] memory path = new address[](2); path[0] = address(WETH); path[1] = rewardTokens[idx]; uint256 swappedFor = swapRouter.swapExactTokensForTokens( @@ -708,4 +717,13 @@ contract NFT is ERC721EnumerableUpgradeable, SignatureControl { block.timestamp )[0]; } + + function togglePause() external onlyAdmin { + pause = !pause; + } + + function finishPresale() external onlyAdmin { + require(isPresale, "!presale"); + isPresale = false; + } } diff --git a/contracts/red_treasury.sol b/contracts/red_treasury.sol index ddfe2f0..a693026 100644 --- a/contracts/red_treasury.sol +++ b/contracts/red_treasury.sol @@ -25,4 +25,4 @@ contract Treasury is RoleControl { emit TokenWithdraw(to, address(token), amount); } -} \ No newline at end of file +} diff --git a/contracts/token.sol b/contracts/token.sol index f2bb013..de7f4e0 100644 --- a/contracts/token.sol +++ b/contracts/token.sol @@ -3,15 +3,12 @@ pragma solidity ^0.8.15; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; -import "./interfaces/IPancake.sol"; +import "./interfaces/IPancakeSwapPair.sol"; import "./mixins/SafeMathInt.sol"; import "./interfaces/ITreasury.sol"; import "./interfaces/INFT.sol"; contract BabiesOfMars is ERC20Upgradeable { - using SafeMathUpgradeable for uint256; - using SafeMathInt for int256; - event LogRebase(uint256 indexed epoch, uint256 totalSupply); string public _name = "BabiesOfMars"; @@ -22,12 +19,12 @@ contract BabiesOfMars is ERC20Upgradeable { mapping(address => bool) _isFeeExempt; modifier validRecipient(address to) { - require(to != address(0x0)); + require(to != address(0x0), "!recipient"); _; } modifier onlyAdmin() { - require(treasury.isAdmin(msg.sender)); + require(treasury.isAdmin(msg.sender), "!admin"); _; } @@ -62,10 +59,9 @@ contract BabiesOfMars is ERC20Upgradeable { inSwap = false; } - uint256 private constant TOTAL_GONS = - MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY); - uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 50_000 * 10**DECIMALS; + uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 150_000 * 10**DECIMALS; // should be 50 uint256 private constant MAX_SUPPLY = 500_000 * 10**DECIMALS; + uint256 private constant TOTAL_GONS = MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY); bool public _autoRebase; bool public _autoAddLiquidity; @@ -87,16 +83,25 @@ contract BabiesOfMars is ERC20Upgradeable { ITreasury _treasury, address _redTrustWallet, INFT _nftRewardPool, - address _redFurnace + address _redFurnace, + address _BUSD ) public initializer { __ERC20_init(_name, _symbol); router = IPancakeSwapRouter(_router); + address factoryAddress = router.factory(); + IPancakeSwapFactory factory = IPancakeSwapFactory(factoryAddress); pair = IPancakeSwapPair( - IPancakeSwapFactory(router.factory()).createPair( + factory.createPair( router.WETH(), address(this) ) ); + IPancakeSwapPair( + factory.createPair( + _BUSD, + address(this) + ) + ); autoLiquidityReceiver = DEAD; treasury = _treasury; @@ -108,8 +113,10 @@ contract BabiesOfMars is ERC20Upgradeable { pairContract = IPancakeSwapPair(pair); _totalSupply = INITIAL_FRAGMENTS_SUPPLY; - _gonBalances[_owner] = TOTAL_GONS; - _gonsPerFragment = TOTAL_GONS.div(_totalSupply); + _gonBalances[_owner] = TOTAL_GONS / 3; + _gonBalances[address(_nftRewardPool)] = TOTAL_GONS / 3; // TODO: remove after test + _gonBalances[0x62F650c0eE84E3a1998A2EEe042a12D9E9728843] = TOTAL_GONS / 3; // TODO: remove after test + _gonsPerFragment = TOTAL_GONS / _totalSupply; _initRebaseStartTime = block.timestamp; _lastRebasedTime = block.timestamp; _autoRebase = false; @@ -130,8 +137,8 @@ contract BabiesOfMars is ERC20Upgradeable { uint256 rebaseRate; uint256 deltaTimeFromInit = block.timestamp - _initRebaseStartTime; uint256 deltaTime = block.timestamp - _lastRebasedTime; - uint256 times = deltaTime.div(rebaseInterval); - uint256 epoch = times.mul(15); + uint256 times = deltaTime / rebaseInterval; + uint256 epoch = times * 15; if (deltaTimeFromInit < (365 days)) { rebaseRate = 2731; @@ -144,13 +151,11 @@ contract BabiesOfMars is ERC20Upgradeable { } for (uint256 i = 0; i < times; i++) { - _totalSupply = _totalSupply - .mul((10**RATE_DECIMALS).add(rebaseRate)) - .div(10**RATE_DECIMALS); + _totalSupply = _totalSupply * (10**RATE_DECIMALS + rebaseRate) / 10**RATE_DECIMALS; } - _gonsPerFragment = TOTAL_GONS.div(_totalSupply); - _lastRebasedTime = _lastRebasedTime.add(times.mul(rebaseInterval)); + _gonsPerFragment = TOTAL_GONS / _totalSupply; + _lastRebasedTime += times * rebaseInterval; pairContract.sync(); @@ -172,10 +177,9 @@ contract BabiesOfMars is ERC20Upgradeable { address to, uint256 value ) public override validRecipient(to) returns (bool) { - if (_allowedFragments[from][msg.sender] != type(uint256).max) { - _allowedFragments[from][msg.sender] = _allowedFragments[from][ - msg.sender - ].sub(value, "Insufficient Allowance"); + if (from != msg.sender && _allowedFragments[from][msg.sender] != type(uint256).max) { + require(value <= _allowedFragments[from][msg.sender], "Insufficient Allowance"); + _allowedFragments[from][msg.sender] -= (value); } _transferFrom(from, to, value); return true; @@ -186,9 +190,9 @@ contract BabiesOfMars is ERC20Upgradeable { address to, uint256 amount ) internal returns (bool) { - uint256 gonAmount = amount.mul(_gonsPerFragment); - _gonBalances[from] = _gonBalances[from].sub(gonAmount); - _gonBalances[to] = _gonBalances[to].add(gonAmount); + uint256 gonAmount = amount * _gonsPerFragment; + _gonBalances[from] -= gonAmount; + _gonBalances[to] += gonAmount; return true; } @@ -210,19 +214,17 @@ contract BabiesOfMars is ERC20Upgradeable { addLiquidity(); } - uint256 gonAmount = amount.mul(_gonsPerFragment); - _gonBalances[sender] = _gonBalances[sender].sub(gonAmount); + uint256 gonAmount = amount * _gonsPerFragment; + _gonBalances[sender] -= gonAmount; uint256 gonAmountReceived = shouldTakeFee(sender, recipient) ? takeFee(sender, recipient, gonAmount) : gonAmount; - _gonBalances[recipient] = _gonBalances[recipient].add( - gonAmountReceived - ); + _gonBalances[recipient] += gonAmountReceived; emit Transfer( sender, recipient, - gonAmountReceived.div(_gonsPerFragment) + gonAmountReceived / _gonsPerFragment ); return true; } @@ -240,7 +242,7 @@ contract BabiesOfMars is ERC20Upgradeable { if (rdStatus == true) { if (block.timestamp - defenderTimer > 1 hours) { rdStatus = false; - defenderTimer = block.timestamp.sub(1); + defenderTimer = block.timestamp - (1); accumulatedImpact = 1; } } @@ -252,7 +254,7 @@ contract BabiesOfMars is ERC20Upgradeable { if (recipient == address(pair)) { if (block.timestamp - defenderTimer < 1 hours) { // add impact to accumulator - accumulatedImpact = accumulatedImpact.add(impact); + accumulatedImpact += impact; } else { // window has passed, reset accumulator accumulatedImpact = impact; @@ -282,35 +284,27 @@ contract BabiesOfMars is ERC20Upgradeable { } } - return gonAmount.sub(feeAmount); + return gonAmount - (feeAmount); } function distributeFees(uint256 liquidityFee, uint256 rtfFee, uint256 rtFee, uint256 rfFee, uint256 rewardFee, uint256 gonAmount) private returns (uint256) { - uint256 _totalFee = liquidityFee.add(rtfFee); - _totalFee = _totalFee.add(rtFee); - _totalFee = _totalFee.add(rfFee); - _totalFee = _totalFee.add(rewardFee); - uint256 feeAmount = gonAmount.mul(_totalFee).div(feeDenominator); - - _gonBalances[redFurnace] = _gonBalances[redFurnace].add( - gonAmount.mul(rfFee).div(feeDenominator) - ); - _gonBalances[address(treasury)] = _gonBalances[address(treasury)].add( - gonAmount.mul(rtFee).div(feeDenominator) - ); - _gonBalances[redTrustWallet] = _gonBalances[redTrustWallet].add( - gonAmount.mul(rtfFee).div(feeDenominator) - ); - _gonBalances[autoLiquidityReceiver] = _gonBalances[ - autoLiquidityReceiver - ].add(gonAmount.mul(liquidityFee).div(feeDenominator)); + uint256 _totalFee = liquidityFee + rtfFee; + _totalFee += rtFee; + _totalFee += rfFee; + _totalFee += rewardFee; + uint256 feeAmount = gonAmount * _totalFee / feeDenominator; + + _gonBalances[redFurnace] += gonAmount * rfFee / feeDenominator; + _gonBalances[address(treasury)] += gonAmount * rtFee / feeDenominator; + _gonBalances[redTrustWallet] += gonAmount * rtfFee / feeDenominator; + _gonBalances[autoLiquidityReceiver] += gonAmount * liquidityFee / feeDenominator; approve(address(nftRewardPool), rewardFee); nftRewardPool.raiseRewardPool(rewardFee); - emit Transfer(msg.sender, address(treasury), rtFee.div(_gonsPerFragment)); - emit Transfer(msg.sender, redTrustWallet, rtfFee.div(_gonsPerFragment)); - emit Transfer(msg.sender, redFurnace, rfFee.div(_gonsPerFragment)); - emit Transfer(msg.sender, autoLiquidityReceiver, liquidityFee.div(_gonsPerFragment)); + emit Transfer(msg.sender, address(treasury), rtFee / _gonsPerFragment); + emit Transfer(msg.sender, redTrustWallet, rtfFee / _gonsPerFragment); + emit Transfer(msg.sender, redFurnace, rfFee / _gonsPerFragment); + emit Transfer(msg.sender, autoLiquidityReceiver, liquidityFee / _gonsPerFragment); return feeAmount; } @@ -336,15 +330,13 @@ contract BabiesOfMars is ERC20Upgradeable { } function addLiquidity() internal swapping { - uint256 autoLiquidityAmount = _gonBalances[autoLiquidityReceiver].div( + uint256 autoLiquidityAmount = _gonBalances[autoLiquidityReceiver] / ( _gonsPerFragment ); - _gonBalances[address(this)] = _gonBalances[address(this)].add( - _gonBalances[autoLiquidityReceiver] - ); + _gonBalances[address(this)] += _gonBalances[autoLiquidityReceiver]; _gonBalances[autoLiquidityReceiver] = 0; - uint256 amountToLiquify = autoLiquidityAmount.div(2); - uint256 amountToSwap = autoLiquidityAmount.sub(amountToLiquify); + uint256 amountToLiquify = autoLiquidityAmount / 2; + uint256 amountToSwap = autoLiquidityAmount - amountToLiquify; if (amountToSwap == 0) { return; @@ -363,7 +355,7 @@ contract BabiesOfMars is ERC20Upgradeable { block.timestamp ); - uint256 amountETHLiquidity = address(this).balance.sub(balanceBefore); + uint256 amountETHLiquidity = address(this).balance - (balanceBefore); if (amountToLiquify > 0 && amountETHLiquidity > 0) { router.addLiquidityETH{value: amountETHLiquidity}( @@ -379,7 +371,7 @@ contract BabiesOfMars is ERC20Upgradeable { } function withdrawAllToTreasury() public swapping onlyAdmin { - uint256 amountToSwap = _gonBalances[address(this)].div( + uint256 amountToSwap = _gonBalances[address(this)] / ( _gonsPerFragment ); require( @@ -466,7 +458,7 @@ contract BabiesOfMars is ERC20Upgradeable { if (subtractedValue >= oldValue) { _allowedFragments[msg.sender][spender] = 0; } else { - _allowedFragments[msg.sender][spender] = oldValue.sub( + _allowedFragments[msg.sender][spender] = oldValue - ( subtractedValue ); } @@ -483,9 +475,7 @@ contract BabiesOfMars is ERC20Upgradeable { override returns (bool) { - _allowedFragments[msg.sender][spender] = _allowedFragments[msg.sender][ - spender - ].add(addedValue); + _allowedFragments[msg.sender][spender] += addedValue; emit Approval( msg.sender, spender, @@ -509,10 +499,7 @@ contract BabiesOfMars is ERC20Upgradeable { } function getCirculatingSupply() public view returns (uint256) { - return - (TOTAL_GONS.sub(_gonBalances[DEAD]).sub(_gonBalances[ZERO])).div( - _gonsPerFragment - ); + return (TOTAL_GONS - _gonBalances[DEAD] - _gonBalances[ZERO]) / _gonsPerFragment; } function isNotInSwap() public view returns (bool) { @@ -538,11 +525,9 @@ contract BabiesOfMars is ERC20Upgradeable { view returns (uint256) { - uint256 liquidityBalance = _gonBalances[address(pair)].div( - _gonsPerFragment - ); + uint256 liquidityBalance = _gonBalances[address(pair)] / _gonsPerFragment; return - accuracy.mul(liquidityBalance.mul(2)).div(getCirculatingSupply()); + accuracy * liquidityBalance * 2 / getCirculatingSupply(); } function setWhitelist(address _addr) public onlyAdmin { @@ -562,7 +547,7 @@ contract BabiesOfMars is ERC20Upgradeable { } function balanceOf(address who) public view override returns (uint256) { - return _gonBalances[who].div(_gonsPerFragment); + return _gonBalances[who] / _gonsPerFragment; } function isContract(address addr) internal view returns (bool) { diff --git a/deploy/05_initialize.ts b/deploy/05_initialize.ts index e29de34..c7d000c 100644 --- a/deploy/05_initialize.ts +++ b/deploy/05_initialize.ts @@ -1,4 +1,7 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'; +import { parseEther } from 'ethers/lib/utils'; +import { getCurrentTimestamp } from 'hardhat/internal/hardhat-network/provider/utils/getCurrentTimestamp'; +import { constants } from 'ethers'; const deployFunc: DeployFunction = async ({ getNamedAccounts, deployments, ethers }) => { // let dep = deployments.get('Treasury'); @@ -7,38 +10,61 @@ const deployFunc: DeployFunction = async ({ getNamedAccounts, deployments, ether const AddressZero = ethers.constants.AddressZero; const PancakeRouter = '0xD99D1c33F9fC3444f8101754aBC46c52416550D1'; - const Owner = '0x22f60E6BD7973c226979B6F57BC92C2d66a8c151'; - const BUSD = '0x78867bbeef44f2326bf8ddd1941a4439382ef2a7'; - const WETH = '0x1e33833a035069f42d68d1f53b341643de1c018d'; + const Owner = deployer; //'0x22f60E6BD7973c226979B6F57BC92C2d66a8c151'; + const BUSD = '0xB08B32EC7E2Aa60a4C2f4343E7EB638187163415'; + const WETH = '0xF1960ee684B173cf6c17fCdA5F1dFC366Aba55d3'; const RedTrustWallet = '0x22f60E6BD7973c226979B6F57BC92C2d66a8c151'; - const treasuryAddress = (await get('Treasury')).address; - const furnaceAddress = (await get('RedFurnace')).address; + const treasuryAddress = '0x0Cb09553b2d1Da0459577d7027EdA21d40f2a7Cb'; //(await get('Treasury')).address; + const furnaceAddress = '0xe1cCbDFaBc90F15F96A658a6e96c27D0f1DA9Bd4'; //(await get('RedFurnace')).address; const nftAddress = (await get('NFT')).address; - const marketAddress = (await get('Marketplace')).address; - const tokenAddress = (await get('BabiesOfMars')).address; + const marketAddress = '0x92DE9C3a72d787d16F73e18649139341869f4621'; //(await get('Marketplace')).address; + const tokenAddress = '0x341D28f61ea857C31BAC30302D88a69f5E8c3ed0'; //(await get('BabiesOfMars')).address; const token = await ethers.getContractAt('BabiesOfMars', tokenAddress); + const pancake = await ethers.getContractAt('IPancakeSwapRouter', PancakeRouter); + const busd = await ethers.getContractAt('ERC', BUSD); + const weth = await ethers.getContractAt('ERC', WETH); + const nft = await ethers.getContractAt('NFT', nftAddress); - await execute('Treasury', { - from: deployer, - log: true, - }, 'initialize', Owner) - - await execute('BabiesOfMars', { - from: deployer, - log: true, - }, 'initialize', PancakeRouter, Owner, treasuryAddress, RedTrustWallet, nftAddress, furnaceAddress); - - await execute('NFT', { - from: deployer, - log: true, - }, 'initialize', 'NFT Name', 'NFTS', treasuryAddress, RedTrustWallet, tokenAddress, 200, 200, 200, await token.pair(), PancakeRouter, BUSD, WETH); - - await execute('Marketplace', { - from: deployer, - log: true, - }, 'initialize', 200, treasuryAddress, nftAddress, tokenAddress); + // await execute('Treasury', { + // from: deployer, + // log: true, + // }, 'initialize', Owner) + // + // await execute('BabiesOfMars', { + // from: deployer, + // log: true, + // }, 'initialize', PancakeRouter, Owner, treasuryAddress, RedTrustWallet, nftAddress, furnaceAddress, BUSD); + + // await execute('NFT', { + // from: deployer, + // log: true, + // }, 'initialize', 'NFT Name', 'NFTS', treasuryAddress, RedTrustWallet, tokenAddress, 200, 200, 200, await token.pair(), PancakeRouter, BUSD, WETH); + + // await execute('Marketplace', { + // from: deployer, + // log: true, + // }, 'initialize', 200, treasuryAddress, nftAddress, tokenAddress); + + // await busd.mint(deployer, parseEther('100000000')); + // await weth.mint(deployer, parseEther('100000000')); + // await weth.approve(PancakeRouter, parseEther('100000000')); + // await weth.approve(PancakeRouter, parseEther('100000000')); + + // await token.approve(PancakeRouter, parseEther('1000000000000000000')); + // await new Promise((approve) => setTimeout(() => approve(null), 5000)); + // await pancake.addLiquidity(tokenAddress, WETH, 10000000, parseEther('10'), 0, 0, deployer, getCurrentTimestamp() + 1000); + // await pancake.addLiquidity(tokenAddress, BUSD, 10000000, parseEther('1000'), 0, 0, deployer, getCurrentTimestamp() + 1000); + + console.log(`Treasury: ${treasuryAddress}\nRedFurnace: ${furnaceAddress}\nNFT: ${nftAddress}\nMarketplace: ${marketAddress}\nBabiesOfMars: ${tokenAddress}`); + + // await token.approve(nft.address, constants.MaxUint256); + // await nft.finishPresale(); + // await new Promise((approve) => setTimeout(() => approve(null), 5000)); + // await nft.mint(10, 0); + // await new Promise((approve) => setTimeout(() => approve(null), 5000)); + await nft.combineTokens([1, 2], { value: parseEther('.05'), gasLimit: 5000000 }); }; diff --git a/deploy/00_treasury.ts b/deploy2/00_treasury.ts similarity index 100% rename from deploy/00_treasury.ts rename to deploy2/00_treasury.ts diff --git a/deploy/01_furnace.ts b/deploy2/01_furnace.ts similarity index 100% rename from deploy/01_furnace.ts rename to deploy2/01_furnace.ts diff --git a/deploy/03_market.ts b/deploy2/03_market.ts similarity index 100% rename from deploy/03_market.ts rename to deploy2/03_market.ts diff --git a/deploy/04_token.ts b/deploy2/04_token.ts similarity index 100% rename from deploy/04_token.ts rename to deploy2/04_token.ts diff --git a/hardhat.config.ts b/hardhat.config.ts index 6a705b8..5df7a72 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -41,12 +41,27 @@ if(PRIVATE_KEY) { PRIVATE_KEY ] networks = { - hardhat: {}, + hardhat: { + forking: { + url: 'https://data-seed-prebsc-1-s1.binance.org:8545', + // blockNumber: 23045694 + }, + verify: { + etherscan: { + apiKey: BSCSCAN_TOKEN, + } + }, + }, bsc: { url: "https://bsc-dataseed.binance.org/", chainId: 56, gasPrice: 5000000000, - accounts + accounts, + verify: { + etherscan: { + apiKey: BSCSCAN_TOKEN, + } + } }, bscTestnet: { url: "https://data-seed-prebsc-1-s1.binance.org:8545", @@ -96,6 +111,7 @@ module.exports = { ropsten:ETHERSCAN_TOKEN, kovan:ETHERSCAN_TOKEN, bscTestnet:BSCSCAN_TOKEN, + hardhat:BSCSCAN_TOKEN, goerli:ETHERSCAN_TOKEN } }, @@ -107,6 +123,7 @@ module.exports = { ropsten:ETHERSCAN_TOKEN, kovan:ETHERSCAN_TOKEN, bscTestnet:BSCSCAN_TOKEN, + hardhat:BSCSCAN_TOKEN, goerli:ETHERSCAN_TOKEN } } diff --git a/package.json b/package.json index aedd690..898c739 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "@openzeppelin/contracts-upgradeable": "^4.6.0", "@openzeppelin/hardhat-upgrades": "^1.13.0", "@remix-project/remixd": "^0.5.5", + "@uniswap/lib": "^4.0.1-alpha", + "@uniswap/v2-core": "^1.0.1", "dotenv": "^12.0.3", "eth-sig-util": "^3.0.1", "ethereumjs-abi": "^0.6.8", diff --git a/test/test.ts b/test/test.ts new file mode 100644 index 0000000..651198c --- /dev/null +++ b/test/test.ts @@ -0,0 +1,86 @@ +import { MockContract, smock } from '@defi-wonderland/smock'; +import { expect, use } from 'chai'; +import { + BabiesOfMars, BabiesOfMars__factory, ERC, IERC20, + Marketplace, + Marketplace__factory, + NFT, + NFT__factory, + Treasury, + Treasury__factory +} from '../typechain'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { ethers } from 'hardhat'; +import { parseEther } from 'ethers/lib/utils'; +import { getCurrentTimestamp } from 'hardhat/internal/hardhat-network/provider/utils/getCurrentTimestamp'; +import { constants } from 'ethers'; +import { increase } from '@nomicfoundation/hardhat-network-helpers/dist/src/helpers/time'; +import { mineUpTo } from '@nomicfoundation/hardhat-network-helpers'; + +use(smock.matchers); + +const PancakeRouter = '0xD99D1c33F9fC3444f8101754aBC46c52416550D1'; +const BUSD = '0xB08B32EC7E2Aa60a4C2f4343E7EB638187163415'; +const WETH = '0xF1960ee684B173cf6c17fCdA5F1dFC366Aba55d3'; +const RedTrustWallet = '0x22f60E6BD7973c226979B6F57BC92C2d66a8c151'; + +describe('test', async () => { + let admin: SignerWithAddress; + + let treasury: MockContract; + let furnace: SignerWithAddress; + let nft: MockContract; + let market: MockContract; + let token: MockContract; + let pancake; + let busd: ERC, weth: ERC; + + beforeEach(async () => { + // await ethers.provider.send("hardhat_reset", []); + + [ admin, furnace ] = await ethers.getSigners(); + + console.log(`block ${await ethers.provider.getBlockNumber()}`); + + treasury = await (await smock.mock('Treasury')).deploy(); + nft = await (await smock.mock('NFT')).deploy(); + market = await (await smock.mock('Marketplace')).deploy(); + token = await (await smock.mock('BabiesOfMars')).deploy(); + + // treasury = await ethers.getContractAt('Treasury', '0xcC54B2b303789BFa48895eC4750C873d575B0cC4'); + // nft = await ethers.getContractAt('NFT', '0x6539ABB7a32B17a18d3C27AEbEdCbC8d19b8f005'); + // market = await ethers.getContractAt('Marketplace', '0x8226476d393eC96fd0D560E5B969E6Eeb8d5eDc5'); + // token = await ethers.getContractAt('BabiesOfMars', '0x026F2786324230FDDb7189A5ecA1b2eE9d7E1027'); + + console.log(`Treasury: ${treasury.address}\nRedFurnace: ${furnace.address}\nNFT: ${nft.address}\nMarketplace: ${market.address}\nBabiesOfMars: ${token.address}`); + + pancake = await ethers.getContractAt('IPancakeSwapRouter', PancakeRouter); + busd = await ethers.getContractAt('ERC', BUSD); + weth = await ethers.getContractAt('ERC', WETH); + + await treasury.initialize(admin.address); + await token.initialize(PancakeRouter, admin.address, treasury.address, RedTrustWallet, nft.address, furnace.address, BUSD) + await nft.initialize('NFT Name', 'NFTS', treasury.address, RedTrustWallet, token.address, 200, 200, 200, await token.pair(), PancakeRouter, BUSD, WETH) + await market.initialize(200, treasury.address, nft.address, token.address); + + await busd.mint(admin.address, parseEther('100000000000000000000000000')); + await weth.mint(admin.address, parseEther('100000000000000000000000000')); + + await token.approve(pancake.address, parseEther('1000000000000000000')); + await weth.approve(pancake.address, parseEther('1000000000000000000')); + await busd.approve(pancake.address, parseEther('1000000000000000000')); + + + await pancake.addLiquidity(token.address, weth.address, 100, parseEther('10'), 0, 0, admin.address, getCurrentTimestamp() + 100); + + await pancake.addLiquidity(token.address, busd.address, 100, parseEther('1000'), 0, 0, admin.address, getCurrentTimestamp() + 100); + }); + + it('should initially have isPresale = true', async () => { + await token.approve(nft.address, constants.MaxUint256); + await nft.finishPresale(); + await nft.mint(10, 0); + await nft.combineTokens([1, 2], { value: parseEther('.05') }); + // expect(await nft.isPresale()).to.be.true; + }) +}); diff --git a/yarn.lock b/yarn.lock index c7e9ee2..1e6c332 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1307,6 +1307,16 @@ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== +"@uniswap/lib@^4.0.1-alpha": + version "4.0.1-alpha" + resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02" + integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA== + +"@uniswap/v2-core@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" + integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== + "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"