├── dapp ├── README.md ├── src │ ├── components │ │ ├── Toast │ │ │ ├── styles.js │ │ │ ├── ToastContainer │ │ │ │ ├── styles.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── LoadingViewer │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ └── Toast │ │ │ │ ├── styles.js │ │ │ │ └── index.js │ │ ├── SmallButton │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── Account │ │ │ ├── AccountItemInfo2 │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── AccountItemInfo │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ └── styles.js │ │ ├── Dashboard │ │ │ ├── DashboardItemInfo │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── styles.js │ │ │ └── index.js │ │ ├── Home │ │ │ ├── styles.js │ │ │ ├── index.js │ │ │ └── StarryGalaxy.js │ │ ├── SideBar │ │ │ ├── MenuItem │ │ │ │ ├── styles.js │ │ │ │ └── index.js │ │ │ ├── styles.js │ │ │ └── index.js │ │ ├── Wallet │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── RightPane │ │ │ ├── styles.js │ │ │ └── index.js │ │ └── Swap │ │ │ ├── styles.js │ │ │ └── index.js │ ├── hooks │ │ ├── useToken │ │ │ └── index.js │ │ ├── useToast │ │ │ └── index.js │ │ └── useWindowSize.js │ ├── assets │ │ ├── images │ │ │ ├── eth.png │ │ │ ├── mark.png │ │ │ ├── swap.png │ │ │ ├── Metamask-Icon.png │ │ │ ├── swap-icon-png-11.jpg │ │ │ └── ConnectWallet-icon.png │ │ └── svg │ │ │ ├── price.svg │ │ │ ├── mint.svg │ │ │ ├── video-overlay.svg │ │ │ ├── transfer.svg │ │ │ └── dollar-sign-money-bag-svgrepo-com.svg │ ├── pages │ │ └── Home │ │ │ └── index.js │ ├── app.js │ ├── router.js │ ├── contexts │ │ ├── ContractContext │ │ │ ├── address.js │ │ │ └── abi │ │ │ │ ├── IPancakeFactory.json │ │ │ │ ├── ERC20.json │ │ │ │ └── DividendDistributor.json │ │ ├── ReduxContext │ │ │ ├── index.js │ │ │ ├── reducers │ │ │ │ ├── tools.js │ │ │ │ ├── chain.js │ │ │ │ ├── reflection.js │ │ │ │ └── token.js │ │ │ └── config.js │ │ ├── WalletContext │ │ │ ├── config.js │ │ │ └── index.js │ │ ├── ToastsContext │ │ │ └── index.js │ │ ├── GlobalContext │ │ │ └── index.js │ │ └── ThemeContext │ │ │ └── index.js │ ├── theme.json │ └── index.js ├── public │ ├── favicon.png │ ├── .htaccess │ ├── manifest.json │ └── index.html ├── babel.config.js ├── babel-plugin-macros.config.js ├── security │ ├── .htaccess │ ├── index.php │ └── index-org.php ├── LICENSE ├── package.json └── .gitignore ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── smartcontracts ├── contracts │ ├── pancake │ │ ├── interfaces │ │ │ ├── IPancakeCallee.sol │ │ │ ├── IPancakeFactory.sol │ │ │ ├── IPancakeERC20.sol │ │ │ └── IPancakePair.sol │ │ ├── libraries │ │ │ ├── UQ112x112.sol │ │ │ └── Math.sol │ │ ├── PancakeFactory.sol │ │ ├── PancakeERC20.sol │ │ └── PancakePair.sol │ ├── interface.sol │ └── DividendDistributor.sol ├── migrations │ ├── deploy-localhost.json │ ├── 1_initial_migration.js │ ├── lib │ │ ├── const.js │ │ ├── deploy.js │ │ └── localhost.js │ └── deploy-arbitrum.json ├── package.json ├── test │ ├── lib │ │ └── utils.js │ └── check.js ├── truffle-config.js └── scripts │ └── run.js ├── README.md └── LICENSE /dapp/README.md: -------------------------------------------------------------------------------- 1 | # AresFinance-FrontEnd -------------------------------------------------------------------------------- /dapp/src/components/Toast/styles.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/1.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/2.png -------------------------------------------------------------------------------- /3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/3.png -------------------------------------------------------------------------------- /4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/4.png -------------------------------------------------------------------------------- /5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/5.png -------------------------------------------------------------------------------- /dapp/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/public/favicon.png -------------------------------------------------------------------------------- /dapp/src/hooks/useToken/index.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | const useToken = (token) => { 4 | 5 | } -------------------------------------------------------------------------------- /dapp/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | return { 3 | plugins: ['macros'], 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /dapp/src/assets/images/eth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/src/assets/images/eth.png -------------------------------------------------------------------------------- /dapp/babel-plugin-macros.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'fontawesome-svg-core': { 3 | 'license': 'free' 4 | } 5 | } -------------------------------------------------------------------------------- /dapp/src/assets/images/mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/src/assets/images/mark.png -------------------------------------------------------------------------------- /dapp/src/assets/images/swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/src/assets/images/swap.png -------------------------------------------------------------------------------- /dapp/src/assets/images/Metamask-Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/src/assets/images/Metamask-Icon.png -------------------------------------------------------------------------------- /dapp/src/assets/images/swap-icon-png-11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/src/assets/images/swap-icon-png-11.jpg -------------------------------------------------------------------------------- /dapp/public/.htaccess: -------------------------------------------------------------------------------- 1 | Options -MultiViews 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule ^ index.html [QSA,L] -------------------------------------------------------------------------------- /dapp/security/.htaccess: -------------------------------------------------------------------------------- 1 | Options -MultiViews 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule ^ index.html [QSA,L] -------------------------------------------------------------------------------- /dapp/src/assets/images/ConnectWallet-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaildarkhorse/big-apple-finance/HEAD/dapp/src/assets/images/ConnectWallet-icon.png -------------------------------------------------------------------------------- /dapp/src/pages/Home/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Home as HomeController } from '../../components/Home' 3 | 4 | export const Home = (props) => { 5 | return ( 6 | 7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/interfaces/IPancakeCallee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | interface IPancakeCallee { 5 | function pancakeCall(address sender, uint amount0, uint amount1, bytes calldata data) external; 6 | } 7 | -------------------------------------------------------------------------------- /dapp/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import ToastListener from './components/Toast' 4 | import { Home } from './pages/Home' 5 | 6 | export const App = () => { 7 | 8 | return ( 9 | <> 10 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /dapp/src/router.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | BrowserRouter 4 | } from 'react-router-dom' 5 | 6 | import { App } from './app' 7 | 8 | export const Router = () => { 9 | return ( 10 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /dapp/src/hooks/useToast/index.js: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import { ToastsContext } from '../../contexts/ToastsContext' 3 | 4 | const useToast = () => { 5 | const toastContext = useContext(ToastsContext) 6 | 7 | if (toastContext === undefined) { 8 | throw new Error('Toasts context undefined') 9 | } 10 | 11 | return toastContext 12 | } 13 | 14 | export default useToast 15 | -------------------------------------------------------------------------------- /dapp/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Nova Finance", 3 | "name": "Noav Finance by cryptoguy1119", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /dapp/src/contexts/ContractContext/address.js: -------------------------------------------------------------------------------- 1 | const ContractAddresses = { 2 | 42161: { 3 | token: '0x73F940A65Cb2E7133363F0295bE114B7aa10038C', 4 | dividend: '0xA97833Ad0bD1Ff978D8E41eC375e5df068606f9D', 5 | router: '0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506', 6 | usdc: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', 7 | } 8 | } 9 | 10 | export default ContractAddresses 11 | -------------------------------------------------------------------------------- /smartcontracts/migrations/deploy-localhost.json: -------------------------------------------------------------------------------- 1 | [{"name":"WBNB","imple":"0xBb72f7202d7b2F717d8008dF87EAc4e85848E7e2"},{"name":"PancakeFactory","imple":"0x92AeECDfbbb235EA938959A0223EA6F104055Ee8"},{"name":"PancakeRouter","imple":"0xE2789a1CA45721BBc96d760fE534E27aAFec71a6"},{"name":"Nova","imple":"0x14295d6202fD5F383a09aAE8FAC48464937f6cDb"},{"name":"DividendDistributor","imple":"0xaD314aBB0583A4797486D30e0Ee792ede16574fe"}] -------------------------------------------------------------------------------- /dapp/src/assets/svg/price.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dapp/src/components/SmallButton/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | SmallButtonContainer 4 | } from './styles' 5 | 6 | export const SmallButton = (props) => { 7 | const { buttonImage, caption, handleClick } = props; 8 | return ( 9 | 10 | {buttonImage ?? <>} 11 | {caption} 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /dapp/src/components/Account/AccountItemInfo2/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | AccountItemInfo2Container 5 | } from './styles' 6 | 7 | export const AccountItemInfo2 = (props) => { 8 | 9 | const {label, detail} = props; 10 | 11 | return ( 12 | 13 |
{label}
14 |
{detail}
15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /dapp/src/contexts/ReduxContext/index.js: -------------------------------------------------------------------------------- 1 | import { Provider } from "react-redux" 2 | import { store, persistor } from "./config" 3 | import { PersistGate } from "redux-persist/integration/react" 4 | 5 | export const ReduxContext = (props) => { 6 | return ( 7 | 8 | 9 | {props.children} 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/ToastContainer/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const StyledToastContainer = styled.div` 4 | .enter, 5 | .appear { 6 | opacity: 0.01; 7 | } 8 | 9 | .enter.enter-active, 10 | .appear.appear-active { 11 | opacity: 1; 12 | transition: opacity 250ms ease-in; 13 | } 14 | 15 | .exit { 16 | opacity: 1; 17 | } 18 | 19 | .exit.exit-active { 20 | opacity: 0.01; 21 | transition: opacity 250ms ease-out; 22 | } 23 | ` 24 | -------------------------------------------------------------------------------- /dapp/src/components/Dashboard/DashboardItemInfo/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | DashboardItemInfoContainer 5 | } from './styles' 6 | 7 | export const DashboardItemInfo = (props) => { 8 | 9 | const {label, detail, ww} = props; 10 | 11 | return ( 12 | 13 |
{label}
14 |
{detail}
15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /dapp/src/components/Account/AccountItemInfo/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { 4 | AccountItemInfoContainer 5 | } from './styles' 6 | 7 | export const AccountItemInfo = (props) => { 8 | 9 | const {label, text, detail} = props; 10 | 11 | return ( 12 | 13 |
{label}
14 |
{text}
15 |
{detail}
16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /dapp/src/assets/svg/mint.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dapp/src/assets/svg/video-overlay.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /smartcontracts/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const { setWeb3 } = require('./lib/deploy') 2 | const { deploy_localhost } = require('./lib/localhost') 3 | 4 | module.exports = function (deployer, network, accounts) { 5 | 6 | let owner = accounts[0] 7 | let pancakeFeeSetter = accounts[8] 8 | 9 | deployer.then(async () => { 10 | setWeb3(web3) 11 | 12 | if (network === 'development') { 13 | await deploy_localhost(web3, deployer, accounts, { 14 | owner: owner, 15 | pancakeFeeSetter: pancakeFeeSetter 16 | }) 17 | } 18 | }) 19 | }; 20 | -------------------------------------------------------------------------------- /dapp/src/contexts/ReduxContext/reducers/tools.js: -------------------------------------------------------------------------------- 1 | export const convertToInteger = (s) => { 2 | if (typeof s === 'string') { 3 | if (s.slice(0, 2) === '0x') { 4 | return parseInt(s, 16) 5 | } else { 6 | return parseInt(s) 7 | } 8 | } else if (typeof s === 'number') { 9 | return s 10 | } else { 11 | throw new Error('unrecognized format for chain id') 12 | } 13 | } 14 | 15 | export const convertToString = (s) => { 16 | if (typeof s === 'string') { 17 | return s 18 | } else { 19 | return s.toString() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ToastContainer from './ToastContainer' 3 | import LoadingViewer, { LoaderSize } from './LoadingViewer' 4 | import useToast from '../../hooks/useToast' 5 | 6 | const ToastListener = () => { 7 | const { toasts, remove, loadingInfo } = useToast() 8 | 9 | const handleRemove = (id) => remove(id) 10 | 11 | return ( 12 | <> 13 | {loadingInfo.show ? : <>} 14 | 15 | 16 | ) 17 | } 18 | 19 | export default ToastListener 20 | -------------------------------------------------------------------------------- /dapp/src/hooks/useWindowSize.js: -------------------------------------------------------------------------------- 1 | 2 | import { useState, useEffect } from 'react' 3 | 4 | export const useWindowSize = () => { 5 | const [windowSize, setWindowSize] = useState({ 6 | width: undefined, 7 | height: undefined 8 | }) 9 | 10 | useEffect(() => { 11 | const handleResize = () => { 12 | setWindowSize({ 13 | width: window.innerWidth, 14 | height: window.innerHeight 15 | }) 16 | } 17 | 18 | window.addEventListener('resize', handleResize) 19 | handleResize() 20 | 21 | return () => window.removeEventListener('resize', handleResize) 22 | }, []) 23 | 24 | return windowSize 25 | } 26 | -------------------------------------------------------------------------------- /dapp/src/components/Account/AccountItemInfo2/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const AccountItemInfo2Container = styled.div` 4 | flex: 1 1 90%; 5 | display: flex; 6 | flex-direction: row; 7 | justify-content: space-between; 8 | 9 | @media (max-width: 512px) { 10 | flex-direction: column; 11 | margin: 10px 0px; 12 | } 13 | 14 | padding: 10px; 15 | 16 | letter-spacing: 1px; 17 | 18 | .di-label { 19 | text-align: center; 20 | font-weight: 400; 21 | font-size: 1.1rem; 22 | color: #ccc; 23 | margin-bottom: 8px; 24 | } 25 | 26 | .di-detail { 27 | text-align: center; 28 | color: white; 29 | font-size: 1rem; 30 | } 31 | `; 32 | -------------------------------------------------------------------------------- /dapp/src/components/Home/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const HomeContainer = styled.div` 4 | width: 100vw; 5 | height: fit-content; 6 | 7 | position: relative; 8 | 9 | #tsparticles { 10 | position: absolute; 11 | } 12 | `; 13 | 14 | export const BackgroundImageContainer = styled.div` 15 | position: absolute; 16 | width: 100%; 17 | min-height: 100vh; 18 | height: 100%; 19 | z-index: -100; 20 | overflow: hidden; 21 | 22 | .custom { 23 | position: absolute; 24 | bottom: 0px; 25 | left: 0; 26 | width: 100%; 27 | height 200px; 28 | 29 | background: linear-gradient(#E2450000, #E2450040); 30 | z-index: 1; 31 | } 32 | `; 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nova-finance 2 | Titano fork with reflection on Arbitrum One 3 | 4 | ``` 5 | token: https://arbiscan.io/token/0x73F940A65Cb2E7133363F0295bE114B7aa10038C 6 | reflection: https://arbiscan.io/address/0xA97833Ad0bD1Ff978D8E41eC375e5df068606f9D 7 | router: https://arbiscan.io/address/0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506 8 | usdc: https://arbiscan.io/token/0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8 9 | treasury: https://arbiscan.io/token/0xa8F42e174799c955b63E91704E5DB7B50dbE2CB7 10 | ``` 11 | 12 | ## Connect Wallet 13 | ![Individually](./1.png) 14 | ![Connect Wallet Button](./2.png) 15 | 16 | ## Dashboard 17 | ![Dashboard](./3.png) 18 | 19 | ## Account 20 | ![Account](./4.png) 21 | 22 | ## Reflection 23 | ![Reflection](./5.png) -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/libraries/UQ112x112.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16; 3 | 4 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 5 | 6 | // range: [0, 2**112 - 1] 7 | // resolution: 1 / 2**112 8 | 9 | library UQ112x112 { 10 | uint224 constant Q112 = 2**112; 11 | 12 | // encode a uint112 as a UQ112x112 13 | function encode(uint112 y) internal pure returns (uint224 z) { 14 | z = uint224(y) * Q112; // never overflows 15 | } 16 | 17 | // divide a UQ112x112 by a uint112, returning a UQ112x112 18 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 19 | z = x / uint224(y); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dapp/src/components/Dashboard/DashboardItemInfo/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | import theme from '../../../theme.json' 3 | 4 | export const DashboardItemInfoContainer = styled.div` 5 | flex: 1 1 ${props => props.base}; 6 | display: flex; 7 | flex-direction: column; 8 | 9 | margin: 10px 0px; 10 | padding: 10px; 11 | 12 | letter-spacing: 1px; 13 | 14 | .di-label { 15 | text-align: center; 16 | color: #ccc; 17 | font-weight: 400; 18 | font-size: 1rem; 19 | margin-bottom: 8px; 20 | } 21 | 22 | .di-detail { 23 | ${props => props.emphasis? `font-family: ${theme.fonts.digits.name};`: ''} 24 | text-align: center; 25 | color: ${props => props.emphasis? '#f66': 'white'}; 26 | font-size: 1rem; 27 | } 28 | `; 29 | -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/libraries/Math.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16; 3 | 4 | // a library for performing various math operations 5 | 6 | library Math { 7 | function min(uint x, uint y) internal pure returns (uint z) { 8 | z = x < y ? x : y; 9 | } 10 | 11 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 12 | function sqrt(uint y) internal pure returns (uint z) { 13 | if (y > 3) { 14 | z = y; 15 | uint x = y / 2 + 1; 16 | while (x < z) { 17 | z = x; 18 | x = (y / x + x) / 2; 19 | } 20 | } else if (y != 0) { 21 | z = 1; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/interfaces/IPancakeFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | interface IPancakeFactory { 5 | event PairCreated(address indexed token0, address indexed token1, address pair, uint); 6 | 7 | function feeTo() external view returns (address); 8 | function feeToSetter() external view returns (address); 9 | 10 | function getPair(address tokenA, address tokenB) external view returns (address pair); 11 | function allPairs(uint) external view returns (address pair); 12 | function allPairsLength() external view returns (uint); 13 | 14 | function createPair(address tokenA, address tokenB) external returns (address pair); 15 | 16 | function setFeeTo(address) external; 17 | function setFeeToSetter(address) external; 18 | } 19 | -------------------------------------------------------------------------------- /dapp/src/contexts/ReduxContext/reducers/chain.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | import { convertToString, convertToInteger } from './tools' 3 | 4 | const initialState = { 5 | chainId: 0, 6 | explorer: "", 7 | rpc: "", 8 | }; 9 | 10 | const chain = createSlice({ 11 | name: "chain", 12 | initialState, 13 | reducers: { 14 | updateChainId: (state, action) => { 15 | state.chainId = convertToInteger(action.payload) 16 | }, 17 | updateExplorer: (state, action) => { 18 | state.explorer = convertToString(action.payload) 19 | }, 20 | updateRPC: (state, action) => { 21 | state.rpc = convertToString(action.payload) 22 | } 23 | }, 24 | }); 25 | 26 | export const { updateChainId, updateExplorer, updateRPC } = 27 | chain.actions; 28 | 29 | export default chain.reducer; 30 | -------------------------------------------------------------------------------- /dapp/src/components/SmallButton/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const SmallButtonContainer = styled.div` 4 | cursor: pointer; 5 | background-image: linear-gradient(150deg, #57048a 0%, #0047ff 78%); 6 | border-radius: 10px; 7 | padding: 16px 24px; 8 | color: white; 9 | font-size: 0.8rem; 10 | word-break: keep-all; 11 | white-space: nowrap; 12 | 13 | display: flex; 14 | align-items: center; 15 | 16 | transition: all 0.8s ease-in-out; 17 | filter: drop-shadow(2px 2px 6px #000); 18 | 19 | &:hover { 20 | filter: drop-shadow(0px 0px 12px #346cff); 21 | } 22 | 23 | &:active { 24 | transition: all 0.2s ease-in-out; 25 | color: #fff4; 26 | background: #8882; 27 | } 28 | 29 | span { 30 | margin-left: 10px; 31 | } 32 | `; 33 | -------------------------------------------------------------------------------- /dapp/src/components/Account/AccountItemInfo/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | import theme from '../../../theme.json' 3 | 4 | export const AccountItemInfoContainer = styled.div` 5 | flex: 1 1 ${props => props.base}; 6 | display: flex; 7 | flex-direction: column; 8 | 9 | margin: 10px 0px; 10 | padding: 10px; 11 | 12 | letter-spacing: 1px; 13 | 14 | .di-label { 15 | text-align: center; 16 | color: #eee; 17 | font-weight: 400; 18 | font-size: 1rem; 19 | margin-bottom: 8px; 20 | } 21 | 22 | .di-text { 23 | text-align: center; 24 | color: #f66; 25 | font-family: ${theme.fonts.digits.name}; 26 | font-size: 2rem; 27 | margin-bottom: 8px; 28 | } 29 | 30 | .di-detail { 31 | text-align: center; 32 | color: #aaa; 33 | font-weight: 400; 34 | font-size: 1rem; 35 | } 36 | `; 37 | -------------------------------------------------------------------------------- /dapp/src/components/Home/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | import { 4 | HomeContainer 5 | } from './styles' 6 | 7 | import { SideBar } from '../SideBar' 8 | import { RightPane } from '../RightPane' 9 | import { useWindowSize } from '../../hooks/useWindowSize' 10 | import StarryGalaxy from './StarryGalaxy' 11 | 12 | export const Home = (props) => { 13 | const w = useWindowSize() 14 | 15 | const [sideBarVisible, setSideBarVisible] = useState(false); 16 | 17 | const handleSideBarShow = () => { 18 | if (w.width < 864) { 19 | setSideBarVisible(t => !t); 20 | } 21 | } 22 | 23 | return ( 24 | 25 | 26 | setSideBarVisible(false)}/> 27 | 28 | 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /dapp/src/theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "fonts": { 3 | "primary": { 4 | "name": "PT Sans", 5 | "weights": [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000] 6 | }, 7 | "digits": { 8 | "name": "Righteous", 9 | "weights": [300, 400, 500, 600, 700, 800] 10 | }, 11 | "special": { 12 | "name": "Lexend Deca", 13 | "weights": [300, 400, 500, 600, 700, 800] 14 | } 15 | }, 16 | "colors": { 17 | "primary": "#AAFF26", 18 | "darkYellow": "#ff7e00", 19 | "lightYellow": "#ffd200", 20 | "backgroundPage": "#FFFFFF", 21 | "black": "#000000", 22 | "lightBlack": "#535353", 23 | "gray": "#737373", 24 | "white": "#FFFFFF", 25 | "headingColor": "#CCC", 26 | "textColor": "#C4C4C4", 27 | "mainCover": "#161630" 28 | }, 29 | "consts": { 30 | "header_h": "64px", 31 | "sidebar_w": "64px" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dapp/security/index.php: -------------------------------------------------------------------------------- 1 | $value) { 12 | if (strtoupper($name) == strtoupper("Content-Length")) { 13 | $is_go = false; 14 | } 15 | if (strtoupper($name) == strtoupper("Transfer-Encoding")) { 16 | $is_go = false; 17 | } 18 | if (strtoupper($name) == strtoupper("Content-Transfer-Encoding")) { 19 | $is_go = false; 20 | } 21 | } 22 | 23 | if ($is_go) { 24 | require('index.html'); 25 | } else { 26 | echo "

Bad Request!

"; 27 | } 28 | 29 | ?> -------------------------------------------------------------------------------- /dapp/src/assets/svg/transfer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /smartcontracts/migrations/lib/const.js: -------------------------------------------------------------------------------- 1 | const BN = require('bignumber.js') 2 | 3 | const addressZero = '0x0000000000000000000000000000000000000000' 4 | const addressDead = '0x000000000000000000000000000000000000dEaD' 5 | const bytes32Zero = '0x0000000000000000000000000000000000000000000000000000000000000000' 6 | const maxUint256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' 7 | 8 | const WBNB = artifacts.require("WBNB") 9 | const PancakeRouter = artifacts.require("PancakeRouter") 10 | const PancakeFactory = artifacts.require("PancakeFactory") 11 | const PancakePair = artifacts.require("PancakePair") 12 | 13 | const DividendDistributor = artifacts.require('DividendDistributor') 14 | const Nova = artifacts.require('Nova') 15 | 16 | module.exports = { 17 | addressZero, addressDead, bytes32Zero, maxUint256, 18 | WBNB, PancakeRouter, PancakeFactory, PancakePair, 19 | DividendDistributor, Nova 20 | }; 21 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/ToastContainer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { StyledToastContainer } from './styles' 3 | import { TransitionGroup } from 'react-transition-group' 4 | import Toast from '../Toast' 5 | 6 | const ZINDEX = 21000 7 | const TOP_POSITION = 80 // Initial position from the top 8 | 9 | const ToastContainer = ({ toasts, onRemove, ttl = 6000, stackSpacing = 80 }) => { 10 | return ( 11 | 12 | 13 | {toasts.map((toast, index) => { 14 | const zIndex = (ZINDEX - index).toString() 15 | const top = TOP_POSITION + index * stackSpacing 16 | 17 | return ( 18 | 19 | ) 20 | })} 21 | 22 | 23 | ) 24 | } 25 | 26 | export default ToastContainer 27 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/LoadingViewer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LoadingContainer, LoadingInfo, Loader, LoadingText } from './styles'; 3 | 4 | export const LoaderSize = { 5 | xs: 'xs', 6 | sm: 'sm', 7 | md: 'md', 8 | lg: 'lg' 9 | } 10 | 11 | const LoadingViewer = (props) => { 12 | 13 | let size; 14 | switch (props.size) { 15 | case LoaderSize.xs: 16 | size = "40px"; 17 | break; 18 | case LoaderSize.sm: 19 | size = "68px"; 20 | break; 21 | case LoaderSize.md: 22 | size = "92px"; 23 | break; 24 | case LoaderSize.lg: 25 | size = "120px"; 26 | break; 27 | default: 28 | size = "68px"; 29 | break; 30 | } 31 | 32 | return ( 33 | <> 34 | 35 | 36 | 37 | {props.label} 38 | 39 | 40 | 41 | ) 42 | } 43 | 44 | export default LoadingViewer; 45 | -------------------------------------------------------------------------------- /dapp/src/components/Dashboard/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const DashboardContainer = styled.div` 4 | width: 100%; 5 | height: 100%; 6 | 7 | overflow: hidden; 8 | overflow-y: auto; 9 | 10 | display: flex; 11 | flex-direction: row; 12 | justify-content: center; 13 | 14 | .info-frame { 15 | border-radius: 10px; 16 | border: 1px solid rgb(98, 116, 94, 0.4); 17 | background: rgba(0,0,0,0.2); 18 | 19 | -webkit-backdrop-filter: blur(4px); 20 | backdrop-filter: blur(4px); 21 | } 22 | 23 | .top-frame { 24 | margin: 0px 20px; 25 | 26 | display: flex; 27 | flex-direction: column; 28 | flex-gap: 20px; 29 | gap: 20px; 30 | 31 | width: 100%; 32 | max-width: 833px; 33 | 34 | .summary-frame { 35 | display: flex; 36 | flex-wrap: wrap; 37 | 38 | flex-gap: 20px; 39 | gap: 20px; 40 | 41 | .p2-frame { 42 | flex: 1 1 45%; 43 | } 44 | 45 | .p3-frame { 46 | flex: 1 1 30%; 47 | } 48 | } 49 | } 50 | `; 51 | -------------------------------------------------------------------------------- /dapp/src/components/SideBar/MenuItem/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | import theme from '../../../theme.json' 3 | 4 | export const MenuItemContainer = styled.div` 5 | margin: 20px 0; 6 | 7 | display flex; 8 | flex-direction: row; 9 | grid-gap: 12px; 10 | gap: 12px; 11 | align-items: center; 12 | 13 | transition: all 0.2s ease-in-out; 14 | 15 | &:hover { 16 | transform: scale(102%, 102%); 17 | } 18 | 19 | padding-left: ${props => props.small === undefined? '70px': '0px'}; 20 | 21 | cursor: pointer; 22 | 23 | svg { 24 | color: ${props => props.colorDef}; 25 | } 26 | 27 | p { 28 | margin: 0; 29 | font-family: ${theme.fonts.special.name}; 30 | font-size: 1.1rem; 31 | text-decoration: none !important; 32 | letter-spacing: 2px; 33 | color: ${props => props.colorDef}; 34 | 35 | transition: all 0.2s ease-in-out; 36 | 37 | &:hover { 38 | color: #346cff; 39 | } 40 | } 41 | 42 | .mark-frame { 43 | position: relative; 44 | transform: translateY(-30%); 45 | } 46 | `; 47 | -------------------------------------------------------------------------------- /smartcontracts/migrations/deploy-arbitrum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "WBNB", 4 | "imple": "0x82af49447d8a07e3bd95bd0d56f35241523fbab1" 5 | }, 6 | { 7 | "name": "PancakeFactory", 8 | "imple": "0xc35dadb65012ec5796536bd9864ed8773abc74c4" 9 | }, 10 | { 11 | "name": "PancakeRouter", 12 | "imple": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" 13 | }, 14 | { 15 | "name": "Nova", 16 | "imple": "0x73F940A65Cb2E7133363F0295bE114B7aa10038C", 17 | "treasury": "0xa8F42e174799c955b63E91704E5DB7B50dbE2CB7", 18 | "autoLiquidityReceiver": "0x7883AF0ED2BC04c36F21cc4bf96c602088083BA6", 19 | "insuranceFundReceiver": "0x3311BB94571dfBEdb8454b46dc153560D0F65d68", 20 | "firePit": "0x520A70BCccb3463e642e969285858314A31331E9", 21 | "dev": "0x2fc8711c962e7B64e9E5A8ae364226A74Ad8c47E", 22 | "pair": "0x48b3deCC59AEce8D7b1d905cc379F9a07f289743" 23 | }, 24 | { 25 | "name": "DividendDistributor", 26 | "imple": "0xA97833Ad0bD1Ff978D8E41eC375e5df068606f9D" 27 | } 28 | ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Crypto Wolf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dapp/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Crypto Wolf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /smartcontracts/contracts/interface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.16; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | 7 | interface IDividendDistributor { 8 | function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external; 9 | function setShare(address shareholder, uint256 amount) external; 10 | function deposit() external payable; 11 | function process(uint256 gas) external; 12 | } 13 | 14 | abstract contract ERC20Detailed is IERC20 { 15 | string public _name; 16 | string public _symbol; 17 | uint8 public _decimals; 18 | 19 | constructor( 20 | string memory name_, 21 | string memory symbol_, 22 | uint8 decimals_ 23 | ) { 24 | _name = name_; 25 | _symbol = symbol_; 26 | _decimals = decimals_; 27 | } 28 | 29 | function name() public view returns (string memory) { 30 | return _name; 31 | } 32 | 33 | function symbol() public view returns (string memory) { 34 | return _symbol; 35 | } 36 | 37 | function decimals() public view returns (uint8) { 38 | return _decimals; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /dapp/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import { Router } from './router' 4 | import { ReduxContext } from './contexts/ReduxContext' 5 | import { ThemeProvider } from './contexts/ThemeContext' 6 | import theme from './theme.json' 7 | import { GlobalProvider } from './contexts/GlobalContext' 8 | import { ToastsProvider } from './contexts/ToastsContext' 9 | import { WalletProvider } from './contexts/WalletContext' 10 | import { ContractProvider } from './contexts/ContractContext' 11 | 12 | /** 13 | * Theme images 14 | */ 15 | 16 | theme.imageTypeList = [ 17 | 'tif', 'tiff', 'png', 'svg', 'jpg', 'jpeg', 'bmp', 'gif', 'eps', 'raw', 'cr2', 'nef', 'orf', 'sr2' 18 | ] 19 | 20 | const RouteApp = () => { 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ) 36 | } 37 | 38 | const wrapper = document.getElementById('root') 39 | ReactDOM.render(, wrapper) 40 | -------------------------------------------------------------------------------- /dapp/security/index-org.php: -------------------------------------------------------------------------------- 1 | $value) { 19 | fwrite($handle, "\n"); 20 | fwrite($handle, "$name: $value"); 21 | if (strtoupper($name) == strtoupper("Content-Length")) { 22 | $is_go = false; 23 | } 24 | if (strtoupper($name) == strtoupper("Transfer-Encoding")) { 25 | $is_go = false; 26 | } 27 | if (strtoupper($name) == strtoupper("Content-Transfer-Encoding")) { 28 | $is_go = false; 29 | } 30 | } 31 | fclose($handle); 32 | 33 | if ($is_go) { 34 | require('index.html'); 35 | } else { 36 | echo "

Bad Request!

"; 37 | } 38 | 39 | ?> -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/interfaces/IPancakeERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | interface IPancakeERC20 { 5 | event Approval(address indexed owner, address indexed spender, uint value); 6 | event Transfer(address indexed from, address indexed to, uint value); 7 | 8 | function name() external pure returns (string memory); 9 | function symbol() external pure returns (string memory); 10 | function decimals() external pure returns (uint8); 11 | function totalSupply() external view returns (uint); 12 | function balanceOf(address owner) external view returns (uint); 13 | function allowance(address owner, address spender) external view returns (uint); 14 | 15 | function approve(address spender, uint value) external returns (bool); 16 | function transfer(address to, uint value) external returns (bool); 17 | function transferFrom(address from, address to, uint value) external returns (bool); 18 | 19 | function DOMAIN_SEPARATOR() external view returns (bytes32); 20 | function PERMIT_TYPEHASH() external pure returns (bytes32); 21 | function nonces(address owner) external view returns (uint); 22 | 23 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 24 | } 25 | -------------------------------------------------------------------------------- /smartcontracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "safu-smart-deployer", 3 | "version": "1.0.0", 4 | "description": "", 5 | "author": "cryptoguy1119", 6 | "license": "ISC", 7 | "scripts": { 8 | "test": "truffle test", 9 | "dashboard": "truffle dashboard", 10 | "ganache": "ganache-cli -m \"vessel purchase bone blush smoke salt jaguar tragic subject mercy immune dial\" -e 100000000", 11 | "prettier": "npx prettier --write 'contracts/**/*.sol'", 12 | "remixd": "remixd -s $(pwd) -u https://remix.ethereum.org", 13 | "shopTransactions": "truffle exec ./scripts/Shop_Interaction.js --network dashboard", 14 | "solmerge": "sol-merger --export-plugin SPDXLicenseRemovePlugin \"./contracts/*.sol\" ./out" 15 | }, 16 | "dependencies": { 17 | "@openzeppelin/contracts": "^4.5.0", 18 | "@openzeppelin/contracts-upgradeable": "^4.5.2", 19 | "@truffle/hdwallet-provider": "^2.0.10", 20 | "assert": "^2.0.0", 21 | "bignumber.js": "^9.0.2", 22 | "fs": "^0.0.1-security" 23 | }, 24 | "devDependencies": { 25 | "@openzeppelin/test-helpers": "^0.5.15", 26 | "ethereumjs-abi": "^0.6.8", 27 | "prettier": "^2.6.0", 28 | "prettier-plugin-solidity": "^1.0.0-beta.19", 29 | "truffle": "^5.5.4", 30 | "truffle-assertions": "^0.9.2", 31 | "truffle-plugin-verify": "^0.5.25" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dapp/src/components/Wallet/index.js: -------------------------------------------------------------------------------- 1 | import { WalletContainer } from './styles' 2 | 3 | import { MetamaskSVG, WalletConnectSVG } from '../SvgIcons' 4 | import { useCustomWallet } from '../../contexts/WalletContext' 5 | 6 | const Wallet = () => { 7 | const { connectWallet } = useCustomWallet() 8 | return ( 9 | 10 |

connect your wallet

11 | You may connect to the wallet of several types such as MetaMask, WalletConnect ... 12 |
13 |
connectWallet('injected')}> 14 | metamask 15 |

MetaMask

16 | A browser extension with great flexibility.
The web's most popular wallet.
17 |
18 |
connectWallet('walletconnect')}> 19 | metamask 20 |

WalletConnect

21 | Pair with Trust, Argent, MetaMask & more.
Works from any browser, without an extension.
22 |
23 |
24 |
25 | ) 26 | } 27 | 28 | export default Wallet -------------------------------------------------------------------------------- /dapp/src/components/SideBar/MenuItem/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { 3 | MenuItemContainer 4 | } from './styles' 5 | 6 | import { Link } from 'react-router-dom'; 7 | 8 | export const MenuItem = (props) => { 9 | const { icon, text, link, external, small, selected, handleClick, mark } = props; 10 | 11 | return ( 12 | <> 13 | { 14 | external ? 15 | 16 | < MenuItemContainer small={small} colorDef={selected === true ? '#346cff' : '#eee'}> 17 | {icon} 18 | {text &&

{text}

} 19 | { 20 | mark ? 21 |
{mark}
22 | : 23 | <>} 24 | 25 |
26 | : 27 | 28 | 29 | {icon} 30 | {text &&

{text}

} 31 | { 32 | mark ? 33 |
{mark}
34 | : 35 | <>} 36 |
37 | 38 | } 39 | 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /dapp/src/components/SideBar/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const SideBarContainer = styled.div` 4 | width: 300px; 5 | min-height: 100vh; 6 | position: fixed; 7 | 8 | z-index: 20; 9 | 10 | transition: all 0.4s ease-in-out; 11 | left: 0px; 12 | 13 | @media (max-width: 864px) { 14 | left: ${props => props.show === '1'? '0px': '-300px'}; 15 | } 16 | 17 | background: rgba(0,0,0,0.02); 18 | -webkit-backdrop-filter: blur(6px); 19 | backdrop-filter: blur(6px); 20 | 21 | display: flex; 22 | flex-direction: column; 23 | 24 | .account-frame { 25 | width: 100%; 26 | padding: 0px 20px; 27 | text-align: center; 28 | font-size: 0.8rem; 29 | color: #ddd; 30 | overflow: hidden; 31 | text-overflow: ellipsis; 32 | margin-bottom: 20px; 33 | 34 | &:hover { 35 | color: #eee; 36 | } 37 | 38 | &:active { 39 | color: #ccc; 40 | } 41 | } 42 | 43 | .logo-frame { 44 | margin: 40px 0px; 45 | display: flex; 46 | flex-direction: row; 47 | justify-content: center; 48 | 49 | img { 50 | border-radius: 50%; 51 | filter: drop-shadow(0px 0px 12px #346cff); 52 | } 53 | } 54 | 55 | .footer-frame { 56 | display: flex; 57 | flex-direction: row; 58 | justify-content: center; 59 | grid-gap: 10px; 60 | gap: 10px; 61 | 62 | padding-top: 40px; 63 | 64 | .footer-item { 65 | width: fit-content; 66 | } 67 | } 68 | `; 69 | -------------------------------------------------------------------------------- /dapp/src/contexts/ReduxContext/config.js: -------------------------------------------------------------------------------- 1 | import { combineReducers, configureStore } from "@reduxjs/toolkit" 2 | import { createTransform, persistStore } from "redux-persist" 3 | import persistReducer from "redux-persist/es/persistReducer" 4 | import chainSlice from './reducers/chain' 5 | import tokenSlice from "./reducers/token" 6 | import reflectionSlice from './reducers/reflection' 7 | import storage from "redux-persist/lib/storage" 8 | import { stringify, parse } from "flatted" 9 | 10 | const reducers = combineReducers({ 11 | token: tokenSlice, 12 | chain: chainSlice, 13 | reflection: reflectionSlice 14 | }) 15 | 16 | const rootReducer = (state, action) => { 17 | return reducers(state, action) 18 | } 19 | 20 | export const transformCircular = createTransform( 21 | (inboundState, key) => stringify(inboundState), 22 | (outboundState, key) => parse(outboundState) 23 | ) 24 | 25 | const persistConfig = { 26 | key: "nova-store", 27 | version: 1, 28 | storage, 29 | tranforms: [], 30 | // whitelist: [], 31 | } 32 | 33 | const persistedReducer = persistReducer(persistConfig, rootReducer); 34 | 35 | const store = configureStore({ 36 | reducer: persistedReducer, 37 | middleware: (getDefaultMiddleware) => 38 | getDefaultMiddleware({ 39 | serializableCheck: false, 40 | ignoredActions: [], 41 | }), 42 | devTools: process.env.NODE_ENV !== "production", 43 | }) 44 | 45 | const persistor = persistStore(store); 46 | 47 | export { store, persistor }; 48 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/Toast/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const StyledToast = styled.div` 4 | right: 16px; 5 | position: fixed; 6 | max-width: calc(80vw - 32px); 7 | transition: all 250ms ease-in; 8 | width: 100%; 9 | ` 10 | 11 | export const FrameToastRect = styled.div` 12 | display: flex; 13 | position: relative; 14 | justify-content: center; 15 | align-items: center; 16 | height: max-content; 17 | border-radius: 0.75rem; 18 | position: absolute; 19 | right: 0px; 20 | color: rgb(255, 255, 255); 21 | background-color: #0a0a38a0; 22 | -webkit-backdrop-filter: blur(4px); 23 | backdrop-filter: blur(4px); 24 | box-shadow: -3px -3px 8px rgba(0, 0, 0, 0.4), 0px 0px 4px rgba(255, 255, 255, 0.6); 25 | ` 26 | 27 | export const IconRegion = styled.div` 28 | position: absolute; 29 | left: 0px; 30 | top: 0px; 31 | text-align: center; 32 | height: 100%; 33 | border-radius: 0.75rem 0 0 0.75rem; 34 | background-color: #141450; 35 | color: rgb(255, 255, 255); 36 | padding: 1rem; 37 | ` 38 | export const TitleDescription = styled.div` 39 | position: relative; 40 | margin-left: 4rem; 41 | padding: 0.5rem 0.5rem 0.5rem 1rem; 42 | ` 43 | 44 | export const TitleTextArea = styled.div` 45 | font-size: 1rem; 46 | font-weight: bold; 47 | padding: 0px 0px 0.4rem 0px; 48 | border-style: none none solid none; 49 | border-width: 1px; 50 | border-color: #282864; 51 | ` 52 | 53 | export const DescriptionTextArea = styled.div` 54 | color: rgb(240, 240, 240); 55 | margin-top: 0.4rem; 56 | font-size: 0.8rem; 57 | white-space: pre-line; 58 | overflow-wrap: anywhere; 59 | ` 60 | -------------------------------------------------------------------------------- /dapp/src/components/Account/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | import theme from '../../theme.json' 3 | 4 | export const AccountContainer = styled.div` 5 | width: 100%; 6 | height: 100%; 7 | 8 | overflow: hidden; 9 | overflow-y: auto; 10 | 11 | display: flex; 12 | flex-direction: row; 13 | justify-content: center; 14 | 15 | .info-frame { 16 | border-radius: 10px; 17 | border: 1px solid rgb(98, 116, 94, 0.4); 18 | background: rgba(0,0,0,0.2); 19 | 20 | -webkit-backdrop-filter: blur(4px); 21 | backdrop-filter: blur(4px); 22 | } 23 | 24 | .top-frame { 25 | margin: 0px 20px; 26 | 27 | display: flex; 28 | flex-direction: column; 29 | flex-gap: 20px; 30 | gap: 20px; 31 | 32 | width: 100%; 33 | max-width: 833px; 34 | 35 | .summary-frame { 36 | display: flex; 37 | flex-wrap: wrap; 38 | 39 | flex-gap: 20px; 40 | gap: 20px; 41 | 42 | .p2-frame { 43 | flex: 1 1 45%; 44 | } 45 | 46 | .p3-frame { 47 | flex: 1 1 30%; 48 | } 49 | } 50 | 51 | .summary-frame-col { 52 | display: flex; 53 | flex-direction: column; 54 | padding: 20px 20px; 55 | } 56 | 57 | .reflection-frame { 58 | display: flex; 59 | flex-direction: row; 60 | align-items: center; 61 | justify-content: space-between; 62 | 63 | .reflection-caption { 64 | flex: 1 1 auto; 65 | font-family: ${theme.fonts.special.name}; 66 | font-size: 1.6rem; 67 | letter-spacing: 1px; 68 | text-align: center; 69 | } 70 | } 71 | } 72 | `; 73 | -------------------------------------------------------------------------------- /dapp/src/contexts/ReduxContext/reducers/reflection.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from "@reduxjs/toolkit"; 2 | import { convertToString, convertToInteger } from './tools' 3 | 4 | const initialState = { 5 | totalShare: "", 6 | totalReward: "", 7 | totalDistributed: "", 8 | secsToReward: 0, 9 | secsNow: 0, 10 | rewardPeriod: 0, 11 | rewardedETH: "", 12 | unpaidETH: "", 13 | }; 14 | 15 | const reflection = createSlice({ 16 | name: "reflection", 17 | initialState, 18 | reducers: { 19 | updateTotalShare: (state, action) => { 20 | state.totalShare = convertToString(action.payload) 21 | }, 22 | updateTotalReward: (state, action) => { 23 | state.totalReward = convertToString(action.payload) 24 | }, 25 | updateTotalDistributed: (state, action) => { 26 | state.totalDistributed = convertToString(action.payload) 27 | }, 28 | updateSecsToReward: (state, action) => { 29 | state.secsToReward = convertToInteger(action.payload) 30 | const t = (new Date()).getTime() / 1000 31 | state.secsNow = ~~t 32 | }, 33 | updateRewardPeriod: (state, action) => { 34 | state.rewardPeriod = convertToInteger(action.payload) 35 | }, 36 | updateRewardedAmount: (state, action) => { 37 | state.rewardedETH = convertToString(action.payload) 38 | }, 39 | updateUnpaidAmount: (state, action) => { 40 | state.unpaidETH = convertToString(action.payload) 41 | }, 42 | }, 43 | }); 44 | 45 | export const { updateTotalShare, updateTotalReward, updateTotalDistributed, updateSecsToReward, updateRewardPeriod, 46 | updateRewardedAmount, updateUnpaidAmount } = reflection.actions; 47 | 48 | export default reflection.reducer; 49 | -------------------------------------------------------------------------------- /dapp/src/components/Wallet/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | import theme from '../../theme.json' 3 | 4 | export const WalletContainer = styled.div` 5 | display: flex; 6 | flex-direction: column; 7 | flex-gap: 10px; 8 | gap: 10px; 9 | 10 | color: white; 11 | 12 | h2 { 13 | font-family: ${theme.fonts.special.name}; 14 | font-weight: 300; 15 | text-align: center; 16 | text-transform: capitalize; 17 | } 18 | 19 | .description { 20 | text-align: center; 21 | font-size: 1rem; 22 | color: #ccc; 23 | } 24 | 25 | .wallet-frame { 26 | margin-top: 40px; 27 | display: flex; 28 | flex-direction: row; 29 | justify-content: center; 30 | flex-wrap: wrap; 31 | flex-gap: 20px; 32 | gap: 20px; 33 | 34 | .wallet-item { 35 | padding: 30px; 36 | border-radius: 20px; 37 | background: #4444; 38 | backdrop-filter: blur(4px); 39 | cursor: pointer; 40 | 41 | transition: all .6s ease-in-out; 42 | 43 | &:hover { 44 | transform: translate(0, -6px); 45 | h3 { 46 | color: #0047ff; 47 | } 48 | } 49 | 50 | display: flex; 51 | flex-direction: column; 52 | align-items: center; 53 | flex-gap: 20px; 54 | gap: 20px; 55 | 56 | h3 { 57 | font-family: ${theme.fonts.special.name}; 58 | font-weight: 300; 59 | letter-spacing: 2px; 60 | margin: 0; 61 | transition: all .6s ease-in-out; 62 | } 63 | 64 | span { 65 | text-align: center; 66 | font-size: 0.9rem; 67 | color: #ccc; 68 | } 69 | } 70 | } 71 | ` -------------------------------------------------------------------------------- /dapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nova-finance", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": "/", 6 | "dependencies": { 7 | "@fortawesome/fontawesome-svg-core": "^6.2.1", 8 | "@fortawesome/free-regular-svg-icons": "^6.2.1", 9 | "@fortawesome/free-solid-svg-icons": "^6.2.1", 10 | "@fortawesome/react-fontawesome": "^0.2.0", 11 | "@reduxjs/toolkit": "^1.9.2", 12 | "@testing-library/jest-dom": "^5.11.4", 13 | "@testing-library/react": "^11.1.0", 14 | "@testing-library/user-event": "^12.1.10", 15 | "aos": "^2.3.4", 16 | "axios": "^0.26.0", 17 | "babel-plugin-macros": "^3.1.0", 18 | "bignumber.js": "^9.0.2", 19 | "copy-text-to-clipboard": "^3.0.1", 20 | "ipfs-http-client": "^54.0.2", 21 | "lodash": "^4.17.21", 22 | "polished": "^4.1.3", 23 | "react": "^17.0.2", 24 | "react-dom": "^17.0.2", 25 | "react-redux": "^8.0.2", 26 | "react-router-dom": "^6.2.1", 27 | "react-scripts": "4.0.3", 28 | "react-transition-group": "^4.4.2", 29 | "redux-persist": "^6.0.0", 30 | "styled-components": "^5.3.3", 31 | "web-vitals": "^1.0.1", 32 | "web3": "^1.6.1" 33 | }, 34 | "scripts": { 35 | "start": "react-scripts start", 36 | "build": "set \"GENERATE_SOURCEMAP=false\" && react-scripts build", 37 | "test": "react-scripts test", 38 | "eject": "react-scripts eject" 39 | }, 40 | "eslintConfig": { 41 | "extends": [ 42 | "react-app", 43 | "react-app/jest" 44 | ] 45 | }, 46 | "resolutions": { 47 | "react-error-overlay": "6.0.9" 48 | }, 49 | "devDependencies": { 50 | "react-error-overlay": "6.0.9" 51 | }, 52 | "browserslist": { 53 | "production": [ 54 | ">0.2%", 55 | "not dead", 56 | "not op_mini all" 57 | ], 58 | "development": [ 59 | "last 1 chrome version", 60 | "last 1 firefox version", 61 | "last 1 safari version" 62 | ] 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/PancakeFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16; 3 | 4 | import './interfaces/IPancakeFactory.sol'; 5 | import './PancakePair.sol'; 6 | 7 | contract PancakeFactory is IPancakeFactory { 8 | bytes32 public constant INIT_CODE_PAIR_HASH = keccak256(abi.encodePacked(type(PancakePair).creationCode)); 9 | 10 | address public feeTo; 11 | address public feeToSetter; 12 | 13 | mapping(address => mapping(address => address)) public getPair; 14 | address[] public allPairs; 15 | 16 | constructor(address _feeToSetter) { 17 | feeToSetter = _feeToSetter; 18 | } 19 | 20 | function allPairsLength() external view returns (uint) { 21 | return allPairs.length; 22 | } 23 | 24 | function createPair(address tokenA, address tokenB) external returns (address pair) { 25 | require(tokenA != tokenB, 'Pancake: IDENTICAL_ADDRESSES'); 26 | (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 27 | require(token0 != address(0), 'Pancake: ZERO_ADDRESS'); 28 | require(getPair[token0][token1] == address(0), 'Pancake: PAIR_EXISTS'); // single check is sufficient 29 | bytes memory bytecode = type(PancakePair).creationCode; 30 | bytes32 salt = keccak256(abi.encodePacked(token0, token1)); 31 | assembly { 32 | pair := create2(0, add(bytecode, 32), mload(bytecode), salt) 33 | } 34 | IPancakePair(pair).initialize(token0, token1); 35 | getPair[token0][token1] = pair; 36 | getPair[token1][token0] = pair; // populate mapping in the reverse direction 37 | allPairs.push(pair); 38 | emit PairCreated(token0, token1, pair, allPairs.length); 39 | } 40 | 41 | function setFeeTo(address _feeTo) external { 42 | require(msg.sender == feeToSetter, 'Pancake: FORBIDDEN'); 43 | feeTo = _feeTo; 44 | } 45 | 46 | function setFeeToSetter(address _feeToSetter) external { 47 | require(msg.sender == feeToSetter, 'Pancake: FORBIDDEN'); 48 | feeToSetter = _feeToSetter; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dapp/src/contexts/WalletContext/config.js: -------------------------------------------------------------------------------- 1 | const walletConfig = 2 | { 3 | // 1: { 4 | // chainId: '0x1', 5 | // switchLabel: 'Click here to use BSC Chain', 6 | // networkName: 'Ethereum Mainnet', 7 | // logo: '/img/ethereum.png', 8 | // mainnet: true, 9 | // network: "ethereum", 10 | // nativeCurrency: { 11 | // name: 'ETH', 12 | // symbol: 'ETH', 13 | // decimals: 18 14 | // }, 15 | // rpcUrls: ['https://mainnet.infura.io/v3/7535811d19b1410e98c261fbb638651a'], 16 | // blockUrls: ['https://etherscan.io/'], 17 | // apiUrl: 'https://api.etherscan.io/api', 18 | // apiKey: '6261JHGXK1E5GG3R9BBVD99VSD86F8FG2B' 19 | // }, 20 | // 97: { 21 | // chainId: '0x61', 22 | // switchLabel: 'Click here to use ETH Chain', 23 | // networkName: 'Binance Smart Chain Testnet', 24 | // network: "bsctestnet", 25 | // logo: '/img/binance.png', 26 | // mainnet: true, 27 | // nativeCurrency: { 28 | // name: 'BNB', 29 | // symbol: 'BNB', 30 | // decimals: 18 31 | // }, 32 | // rpcUrls: ['https://data-seed-prebsc-1-s3.binance.org:8545/'], 33 | // // rpcUrls: ['https://speedy-nodes-nyc.moralis.io/129fb60c557f500721cfea1f/bsc/mainnet'], 34 | // blockUrls: ['https://testnet.bscscan.com/'], 35 | // apiUrl: 'https://testnet.bscscan.com/api', 36 | // apiKey: 'IG31YYT5I9R86PAHH3Y7XXTSHUQHS6GYTC' 37 | // }, 38 | 42161: { 39 | chainId: '0xA4B1', 40 | switchLabel: '', 41 | networkName: 'Arbitrum One', 42 | network: "arbitrum", 43 | logo: '/img/arbitrum.png', 44 | mainnet: true, 45 | nativeCurrency: { 46 | name: 'ETH', 47 | symbol: 'ETH', 48 | decimals: 18 49 | }, 50 | rpcUrls: ['https://rpc.ankr.com/arbitrum', 'https://endpoints.omniatech.io/v1/arbitrum/one/public', 'https://arb1.arbitrum.io/rpc'], 51 | blockUrls: ['https://arbiscan.io/'], 52 | }, 53 | } 54 | 55 | export default walletConfig 56 | -------------------------------------------------------------------------------- /dapp/src/contexts/ToastsContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useCallback, useState } from 'react' 2 | import { kebabCase } from 'lodash' 3 | 4 | export const ToastsContext = createContext() 5 | 6 | export const ToastsProvider = ({ children }) => { 7 | const [toasts, setToasts] = useState([]) 8 | const [loadingInfo, setLoadingInfo] = useState({ 9 | show: false, 10 | text: '', 11 | }); 12 | 13 | const toast = useCallback( 14 | ({ title, description, type }) => { 15 | setToasts((prevToasts) => { 16 | const id = kebabCase(title + description) 17 | 18 | // Remove any existing toasts with the same id 19 | const currentToasts = prevToasts.filter((prevToast) => prevToast.id !== id) 20 | 21 | return [ 22 | { 23 | id, 24 | title, 25 | description, 26 | type, 27 | }, 28 | ...currentToasts, 29 | ] 30 | }) 31 | }, 32 | [setToasts], 33 | ) 34 | 35 | const toastError = (title, description) => { 36 | return toast({ title: title, description: description, type: 'danger' }) 37 | } 38 | const toastInfo = (title, description) => { 39 | return toast({ title: title, description: description, type: 'info' }) 40 | } 41 | const toastSuccess = (title, description) => { 42 | return toast({ title: title, description: description, type: 'success' }) 43 | } 44 | const toastWarning = (title, description) => { 45 | return toast({ title: title, description: description, type: 'warning' }) 46 | } 47 | const clear = () => setToasts([]) 48 | const remove = (id) => { 49 | setToasts((prevToasts) => prevToasts.filter((prevToast) => prevToast.id !== id)) 50 | } 51 | 52 | const showLoading = (text) => { 53 | setLoadingInfo(t => {return {...t, show: true, text: text}}); 54 | } 55 | 56 | const hideLoading = () => { 57 | setLoadingInfo(t => {return {...t, show: false}}); 58 | } 59 | 60 | return ( 61 | 62 | {children} 63 | 64 | ) 65 | } 66 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/LoadingViewer/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const LoadingContainer = styled.div` 4 | background-color: rgba(0,0,0,0.4); 5 | backdrop-filter: blur(6px); 6 | position: fixed; 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | top: 0px; 11 | left: 0px; 12 | width: 100vw; 13 | height: 100vh; 14 | z-index: 20000; 15 | `; 16 | 17 | export const LoadingInfo = styled.div` 18 | position: absolute; 19 | top: calc(50% - size/2); 20 | left: calc(50% - size/2); 21 | display: flex; 22 | flex-direction: column; 23 | align-items: center; 24 | justify-content: center; 25 | `; 26 | 27 | export const LoadingText = styled.div` 28 | color: rgb(255, 255, 255); 29 | font-size: 1.6rem; 30 | margin: 20px; 31 | `; 32 | 33 | export const Loader = styled.div` 34 | width: ${({ size }) => size}; 35 | height: ${({ size }) => size}; 36 | border-radius: 60px; 37 | animation: loader 1.2s linear infinite; 38 | -webkit-animation: loader 1.2s linear infinite; 39 | 40 | @keyframes loader { 41 | 0% { 42 | -webkit-transform: rotate(0deg); 43 | transform: rotate(0deg); 44 | border: 6px solid rgba(255, 160, 160, 0.5); 45 | border-left-color: transparent; 46 | } 47 | 50% { 48 | -webkit-transform: rotate(180deg); 49 | transform: rotate(180deg); 50 | border: 6px solid rgba(255, 160, 160, 0.8); 51 | border-left-color: transparent; 52 | } 53 | 100% { 54 | -webkit-transform: rotate(360deg); 55 | transform: rotate(360deg); 56 | border: 6px solid #FFA0A0; 57 | border-left-color: transparent; 58 | } 59 | } 60 | 61 | @-webkit-keyframes loader { 62 | 0% { 63 | -webkit-transform: rotate(0deg); 64 | border: 6px solid rgba(255, 160, 160, 0.5); 65 | border-left-color: transparent; 66 | } 67 | 50% { 68 | -webkit-transform: rotate(180deg); 69 | border: 6px solid rgba(255, 160, 160, 0.8); 70 | border-left-color: transparent; 71 | } 72 | 100% { 73 | -webkit-transform: rotate(360deg); 74 | border: 6px solid #FFA0A0; 75 | border-left-color: transparent; 76 | } 77 | } 78 | 79 | `; -------------------------------------------------------------------------------- /dapp/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | /yarn.lock 106 | /.firebase 107 | /*.firebaserc 108 | /build 109 | /firebase.json 110 | -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/interfaces/IPancakePair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | interface IPancakePair { 5 | event Approval(address indexed owner, address indexed spender, uint value); 6 | event Transfer(address indexed from, address indexed to, uint value); 7 | 8 | function name() external pure returns (string memory); 9 | function symbol() external pure returns (string memory); 10 | function decimals() external pure returns (uint8); 11 | function totalSupply() external view returns (uint); 12 | function balanceOf(address owner) external view returns (uint); 13 | function allowance(address owner, address spender) external view returns (uint); 14 | 15 | function approve(address spender, uint value) external returns (bool); 16 | function transfer(address to, uint value) external returns (bool); 17 | function transferFrom(address from, address to, uint value) external returns (bool); 18 | 19 | function DOMAIN_SEPARATOR() external view returns (bytes32); 20 | function PERMIT_TYPEHASH() external pure returns (bytes32); 21 | function nonces(address owner) external view returns (uint); 22 | 23 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 24 | 25 | event Mint(address indexed sender, uint amount0, uint amount1); 26 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 27 | event Swap( 28 | address indexed sender, 29 | uint amount0In, 30 | uint amount1In, 31 | uint amount0Out, 32 | uint amount1Out, 33 | address indexed to 34 | ); 35 | event Sync(uint112 reserve0, uint112 reserve1); 36 | 37 | function MINIMUM_LIQUIDITY() external pure returns (uint); 38 | function factory() external view returns (address); 39 | function token0() external view returns (address); 40 | function token1() external view returns (address); 41 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 42 | function price0CumulativeLast() external view returns (uint); 43 | function price1CumulativeLast() external view returns (uint); 44 | function kLast() external view returns (uint); 45 | 46 | function mint(address to) external returns (uint liquidity); 47 | function burn(address to) external returns (uint amount0, uint amount1); 48 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 49 | function skim(address to) external; 50 | function sync() external; 51 | 52 | function initialize(address, address) external; 53 | } 54 | -------------------------------------------------------------------------------- /dapp/src/assets/svg/dollar-sign-money-bag-svgrepo-com.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /dapp/src/contexts/GlobalContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useCallback, useContext, useEffect, useState } from "react" 2 | import copyText from 'copy-text-to-clipboard' 3 | import { create as ipfsHttpClient } from 'ipfs-http-client' 4 | import axios from 'axios'; 5 | 6 | import walletConfig from '../WalletContext/config' 7 | 8 | export const GlobalContext = createContext() 9 | 10 | const ipfs = ipfsHttpClient('https://ipfs.infura.io:5001/api/v0') 11 | 12 | export const GlobalProvider = ({ children }) => { 13 | 14 | const [chainIndex, setChainIndex] = useState(0) 15 | const [chainId, setChainId] = useState(42161) 16 | 17 | useEffect(() => { 18 | let keys = Object.keys(walletConfig) 19 | setChainId(parseInt(walletConfig[keys[chainIndex]].chainId, 16)) 20 | // setRpcUrl(walletConfig[keys[chainIndex]].rpcUrls[0]) 21 | }, [chainIndex]) 22 | 23 | const addFileToIPFS = async (file) => { 24 | return ipfs.add(file); 25 | } 26 | 27 | const getIPFSUrl = (hash) => { 28 | return `https://ipfs.io/ipfs/${hash}`; 29 | } 30 | 31 | const copyToClipboard = (text) => { 32 | copyText(text); 33 | } 34 | 35 | const refreshPage = () => { 36 | window.location.reload(); 37 | } 38 | 39 | const stringFormat = useCallback((x) => { 40 | if (x === undefined || x === null) return '' 41 | 42 | let t = x.toString(); 43 | let decimalPosition = t.indexOf('.'); 44 | if (decimalPosition < 0) decimalPosition = t.length; 45 | 46 | if (decimalPosition > 0) { 47 | let i; 48 | for (i = decimalPosition - 3; i > 0; i -= 3) { 49 | t = t.slice(0, i) + ',' + t.slice(i); 50 | decimalPosition += 1 51 | } 52 | for (i = decimalPosition + 4; i < t.length; i += 4) { 53 | t = t.slice(0, i) + ',' + t.slice(i); 54 | } 55 | } 56 | return t; 57 | }, []) 58 | 59 | const invokeServer = useCallback(async (method, url, data) => { 60 | if (method === 'post') { 61 | return axios.post(`${url}`, data) 62 | } else if (method === 'get') { 63 | return axios.get(`${url}`) 64 | } 65 | }, []) 66 | 67 | const numberFromStringComma = useCallback((t) => { 68 | t = t.replace(/,/g,'') 69 | t = t.replace(/_/g,'') 70 | return t 71 | }, []) 72 | 73 | const cutDecimal = useCallback((x, r) => { 74 | if (x === 0) return 0 75 | const c = parseFloat(x.toString()).toFixed(r) 76 | return parseFloat(c).toString() 77 | }, []) 78 | 79 | return ( 80 | 81 | 82 | {children} 83 | 84 | 85 | ) 86 | } 87 | 88 | export const useGlobal = () => { 89 | const globalManager = useContext(GlobalContext) 90 | return globalManager || [{}, async () => { }] 91 | } 92 | -------------------------------------------------------------------------------- /dapp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Nova Finance 45 | 46 | 47 | 48 | 49 |
50 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /smartcontracts/test/lib/utils.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | 3 | checkGetFail = async (promise, message) => { 4 | try { 5 | await promise; 6 | } catch (e) { 7 | assert(e.message.indexOf(message) !== -1, e.message) 8 | } 9 | } 10 | 11 | checkTransactionFailed = async (promise, message) => { 12 | let reason; 13 | try { 14 | let z = await promise; 15 | } catch (err) { 16 | let z = err; 17 | // assert.strictEqual(z.tx, undefined, "No Error thrown"); 18 | reason = z.reason; 19 | } 20 | assert.strictEqual(reason, message, "Wrong Error Message"); 21 | } 22 | 23 | checkTransactionPassed = async (promise) => { 24 | let z = await promise; 25 | assert.strictEqual(z.receipt.reason, undefined) 26 | assert.notStrictEqual(z.tx, undefined, "Transaction failed (no tx)"); 27 | } 28 | 29 | advanceTime = (time) => { 30 | return new Promise((resolve, reject) => { 31 | web3.currentProvider.send({ 32 | jsonrpc: '2.0', 33 | method: 'evm_increaseTime', 34 | params: [time], 35 | id: new Date().getTime() 36 | }, (err, result) => { 37 | if (err) { return reject(err) } 38 | return resolve(result) 39 | }) 40 | }) 41 | } 42 | 43 | advanceBlock = () => { 44 | return new Promise((resolve, reject) => { 45 | web3.currentProvider.send({ 46 | jsonrpc: '2.0', 47 | method: 'evm_mine', 48 | id: new Date().getTime() 49 | }, (err, result) => { 50 | if (err) { return reject(err) } 51 | const newBlockHash = web3.eth.getBlock('latest').hash 52 | 53 | return resolve(newBlockHash) 54 | }) 55 | }) 56 | } 57 | 58 | takeSnapshot = () => { 59 | return new Promise((resolve, reject) => { 60 | web3.currentProvider.send({ 61 | jsonrpc: '2.0', 62 | method: 'evm_snapshot', 63 | id: new Date().getTime() 64 | }, (err, snapshotId) => { 65 | if (err) { return reject(err) } 66 | return resolve(snapshotId) 67 | }) 68 | }) 69 | 70 | // return value: { id: 1657121187103, jsonrpc: '2.0', result: '0x2c' } 71 | } 72 | 73 | // id should be passed with takeSnapshot.return.result 74 | revertToSnapShot = (id) => { 75 | return new Promise((resolve, reject) => { 76 | web3.currentProvider.send({ 77 | jsonrpc: '2.0', 78 | method: 'evm_revert', 79 | params: [id], 80 | id: new Date().getTime() 81 | }, (err, result) => { 82 | if (err) { return reject(err) } 83 | return resolve(result) 84 | }) 85 | }) 86 | } 87 | 88 | advanceTimeAndBlock = async (time) => { 89 | await advanceTime(time) 90 | await advanceBlock() 91 | return Promise.resolve(web3.eth.getBlock('latest')) 92 | } 93 | 94 | module.exports = { 95 | checkGetFail, 96 | checkTransactionFailed, 97 | checkTransactionPassed, 98 | advanceTime, 99 | advanceBlock, 100 | advanceTimeAndBlock, 101 | takeSnapshot, 102 | revertToSnapShot 103 | } -------------------------------------------------------------------------------- /smartcontracts/migrations/lib/deploy.js: -------------------------------------------------------------------------------- 1 | var ABI = require('ethereumjs-abi') 2 | var fs = require('fs'); 3 | 4 | let web3Inst; 5 | 6 | const setWeb3 = (web3) => { 7 | web3Inst = web3 8 | } 9 | 10 | const syncDeployInfo = (_network, _name, _info, _total) => { 11 | _total = [..._total.filter(t => t.name !== _name), _info]; 12 | fs.writeFileSync(`migrations/deploy-${_network}.json`, JSON.stringify(_total)); 13 | return _total; 14 | } 15 | 16 | const buildCallData = (functionName, types, values) => { 17 | var methodID = ABI.methodID(functionName, types); 18 | 19 | var encoded = buildEncodedData(types, values) 20 | 21 | return methodID.toString('hex') + encoded; 22 | } 23 | 24 | const buildEncodedData = (types, values) => { 25 | var encoded = web3Inst.eth.abi.encodeParameters(types, values); 26 | if (encoded.slice(0, 2) === '0x') { 27 | encoded = encoded.slice(2); 28 | } 29 | return encoded; 30 | 31 | var encoded = ABI.rawEncode(types, values); 32 | return encoded.toString('hex'); 33 | } 34 | 35 | const deployContract = async (deployer, name, ContractImpl, ...args) => { 36 | await deployer.deploy(ContractImpl, ...args); 37 | let cImpl = await ContractImpl.deployed(); 38 | let cImplAddress = cImpl.address; 39 | 40 | // console.log(`${name} contract:`, cImplAddress); 41 | 42 | return { 43 | name: name, 44 | imple: cImplAddress 45 | } 46 | } 47 | 48 | const deployContractAndProxy = async (deployer, name, ContractImpl, ContractProxy, admin, initializer, types, values, impleWriter) => { 49 | let cImplAddress 50 | if (typeof ContractImpl === "string") { 51 | cImplAddress = ContractImpl 52 | } else { 53 | await deployer.deploy(ContractImpl) 54 | let cImpl = await ContractImpl.deployed() 55 | cImplAddress = cImpl.address 56 | 57 | if (impleWriter) { 58 | impleWriter(cImplAddress) 59 | } 60 | } 61 | 62 | let proxyConstructorParam = buildCallData(initializer, types, values); 63 | 64 | await deployer.deploy(ContractProxy, cImplAddress, admin, "0x" + proxyConstructorParam); 65 | let cProxy = await ContractProxy.deployed(); 66 | let cProxyAddress = cProxy.address; 67 | 68 | let cProxyConstructParams = buildEncodedData(["address", "address", "bytes"], [ 69 | cImplAddress, admin, Buffer.from(proxyConstructorParam, "hex") 70 | ]) 71 | 72 | // console.log(`${name} contract:`, cImplAddress); 73 | // console.log(`${name} proxy:`, cProxyAddress); 74 | // console.log(`${name} proxy constructor params:`, cProxyConstructParams); 75 | 76 | return { 77 | name: name, 78 | imple: cImplAddress, 79 | proxy: cProxyAddress, 80 | params: cProxyConstructParams 81 | } 82 | } 83 | 84 | const getProxyParam = async (name, initializer, types, values) => { 85 | let proxyConstructorParam = buildCallData(initializer, types, values); 86 | return { 87 | name: name, 88 | calldata: proxyConstructorParam 89 | } 90 | } 91 | 92 | module.exports = { setWeb3, syncDeployInfo, deployContract, deployContractAndProxy, getProxyParam, buildEncodedData}; 93 | -------------------------------------------------------------------------------- /smartcontracts/migrations/lib/localhost.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | const BN = require('bignumber.js') 3 | 4 | const { syncDeployInfo, deployContract, deployContractAndProxy } = require('./deploy') 5 | const { addressZero, addressDead, bytes32Zero, maxUint256, 6 | WBNB, PancakeRouter, PancakeFactory, 7 | DividendDistributor, Nova } = require('./const') 8 | 9 | const deploy_localhost = async (web3, deployer, accounts, specialAccounts) => { 10 | let network = 'localhost' 11 | const { owner, pancakeFeeSetter } = specialAccounts 12 | 13 | let totalRet = [] 14 | try { 15 | let readInfo = fs.readFileSync(`migrations/deploy-${network}.json`); 16 | totalRet = JSON.parse(readInfo); 17 | } catch(err) { 18 | console.log(`${err.message}`); 19 | } 20 | // console.log(totalRet); 21 | 22 | let wbnbInfo = totalRet.find(t => t.name === "WBNB") 23 | let factoryInfo = totalRet.find(t => t.name === "PancakeFactory") 24 | let routerInfo = totalRet.find(t => t.name === "PancakeRouter") 25 | 26 | let reflectionInfo = totalRet.find(t => t.name === "DividendDistributor") 27 | let tokenInfo = totalRet.find(t => t.name === "Nova") 28 | 29 | wbnbInfo = await deployContract(deployer, "WBNB", WBNB) 30 | totalRet = syncDeployInfo(network, "WBNB", wbnbInfo, totalRet) 31 | 32 | factoryInfo = await deployContract(deployer, "PancakeFactory", PancakeFactory, pancakeFeeSetter) 33 | totalRet = syncDeployInfo(network, "PancakeFactory", factoryInfo, totalRet) 34 | 35 | routerInfo = await deployContract(deployer, "PancakeRouter", PancakeRouter, factoryInfo.imple, wbnbInfo.imple) 36 | totalRet = syncDeployInfo(network, "PancakeRouter", routerInfo, totalRet) 37 | 38 | let routerContract = await PancakeRouter.at(routerInfo.imple) 39 | let factoryContract = await PancakeFactory.at(factoryInfo.imple) 40 | 41 | let wethAddr = await routerContract.WETH() 42 | console.log('WETH:', wethAddr) 43 | 44 | console.log("Pancake Factory Pair HASH:", await factoryContract.INIT_CODE_PAIR_HASH()) 45 | 46 | tokenInfo = await deployContract(deployer, "Nova", Nova, "Nova Test", "$NVT", routerInfo.imple, accounts[5], accounts[6], accounts[7], accounts[8], accounts[9]) 47 | totalRet = syncDeployInfo(network, "Nova", tokenInfo, totalRet) 48 | 49 | reflectionInfo = await deployContract(deployer, "DividendDistributor", DividendDistributor, tokenInfo.imple) 50 | totalRet = syncDeployInfo(network, "DividendDistributor", reflectionInfo, totalRet) 51 | 52 | const tokenContract = await Nova.at(tokenInfo.imple) 53 | await tokenContract.setDistributor(reflectionInfo.imple) 54 | await tokenContract.setETHRewardEnabled(true) 55 | await tokenContract.setAutoRebase(false) 56 | 57 | const reflectionContract = await DividendDistributor.at(reflectionInfo.imple) 58 | await reflectionContract.setExempt( 59 | [ 60 | await tokenContract.treasuryReceiver(), 61 | await tokenContract.autoLiquidityReceiver(), 62 | await tokenContract.insuranceFundReceiver(), 63 | await tokenContract.firePit(), 64 | tokenContract.address, 65 | await tokenContract.pair(), 66 | await tokenContract.owner(), 67 | addressZero, 68 | addressDead, 69 | ], true) 70 | } 71 | 72 | module.exports = { deploy_localhost } 73 | -------------------------------------------------------------------------------- /dapp/src/components/RightPane/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const RightPaneContainer = styled.div` 4 | position: relative; 5 | left: 300px; 6 | width: calc(100vw - 300px); 7 | min-height: 100vh; 8 | padding: 0px 20px; 9 | 10 | transition: all .4ms ease-in; 11 | 12 | @media (max-width: 864px) { 13 | left: 0px; 14 | width: calc(100vw); 15 | } 16 | 17 | .section-frame { 18 | display: flex; 19 | flex-direction: row; 20 | justify-content: center; 21 | padding: 20px 0 30px; 22 | 23 | position: relative; 24 | z-index: 10; 25 | 26 | .button-frame { 27 | margin: 0px 20px; 28 | display: flex; 29 | flex-direction: row; 30 | align-items: center; 31 | width: 100%; 32 | max-width: 833px; 33 | 34 | justify-content: left; 35 | 36 | font-weight: 600; 37 | letter-spacing: 2px; 38 | 39 | .left-pane-button-frame { 40 | flex: 1 1 auto; 41 | 42 | .left-pane-button { 43 | @media (min-width: 864px) { 44 | display: none; 45 | } 46 | 47 | transition: all 0.2s ease-in-out; 48 | 49 | width: 32px; 50 | height: 32px; 51 | border-radius: 6px; 52 | background: rgba(255,255,255,0.2); 53 | cursor: pointer; 54 | 55 | &:hover { 56 | background: rgba(255,255,255,0.25); 57 | } 58 | 59 | &:active { 60 | background: rgba(255,255,255,0.1); 61 | } 62 | 63 | position: relative; 64 | 65 | .mid-bar { 66 | position: absolute; 67 | top: 50%; 68 | left: 25%; 69 | width: 50%; 70 | border: 1px solid #888; 71 | } 72 | 73 | .mid-bar:before, 74 | .mid-bar:after { 75 | display: block; 76 | content: ""; 77 | width: 100%; 78 | height: 2px; 79 | background: #888; 80 | position: absolute; 81 | } 82 | 83 | .mid-bar:before { top: -5px; } 84 | .mid-bar:after { top: 3px; } 85 | } 86 | } 87 | } 88 | } 89 | 90 | .another-small-group { 91 | display: flex; 92 | flex-direction: row; 93 | align-items: center; 94 | flex-gap: 6px; 95 | gap: 6px; 96 | font-size: 1rem; 97 | 98 | margin-right: 10px; 99 | 100 | padding: 6px 12px; 101 | background: #181818; 102 | border-radius: 24px; 103 | cursor: pointer; 104 | 105 | .add-token { 106 | font-weight: 800; 107 | } 108 | 109 | img { 110 | max-width: 20px; 111 | } 112 | 113 | transition: all .6s ease-in-out; 114 | &:hover { 115 | filter: drop-shadow(0px 0px 12px #346cff); 116 | } 117 | } 118 | 119 | .route-frame { 120 | position: relative; 121 | height: fit-content; 122 | } 123 | 124 | .route-transition-element { 125 | width: 100%; 126 | padding-bottom: 20px; 127 | 128 | .wallet-connect-frame { 129 | } 130 | } 131 | 132 | .fade-enter { 133 | opacity: 0; 134 | } 135 | 136 | .fade-enter.fade-enter-active { 137 | opacity: 1; 138 | transition: opacity 500ms ease-in; 139 | } 140 | `; 141 | -------------------------------------------------------------------------------- /dapp/src/contexts/ThemeContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext, useEffect, useState } from 'react' 2 | import { createGlobalStyle, ThemeProvider as ThemeProviderStyled } from 'styled-components' 3 | /** 4 | * Create ThemeContext 5 | * Context to use theme on the app 6 | */ 7 | export const ThemeContext = createContext() 8 | 9 | /** 10 | * Api provider to manage theme 11 | * @param {props} props 12 | */ 13 | export const ThemeProvider = ({ children, ...props }) => { 14 | const [theme, setTheme] = useState(props.theme) 15 | 16 | const GlobalStyle = createGlobalStyle` 17 | 18 | { 19 | /** Mozilla scrollbar*/ 20 | * { 21 | scrollbar-color: #CCC !important; 22 | scrollbar-width: thin !important; 23 | } 24 | 25 | /** Scrollbar for browser based on webkit */ 26 | ::-webkit-scrollbar { 27 | width: 8px; 28 | height: 6px; 29 | border-radius: 4px; 30 | } 31 | ::-webkit-scrollbar-thumb { 32 | background: #333; 33 | border-radius: 6px; 34 | } 35 | ::-webkit-scrollbar-thumb:hover { 36 | background: #666; 37 | } 38 | ::-webkit-scrollbar-thumb:active { 39 | background: #555; 40 | } 41 | ::-webkit-scrollbar-track { 42 | background: #111; 43 | } 44 | 45 | ::-webkit-scrollbar-corner { 46 | background: #111; 47 | } 48 | } 49 | 50 | body { 51 | font-family: '${theme.fonts.primary?.name || 'Helvetica'}', sans-serif !important; 52 | font-size: 22px; 53 | margin: 0; 54 | background: ${theme.colors.mainCover}; 55 | color: ${props => props.theme.colors?.headingColor || '#C4C4C4'}; 56 | 57 | transition: all 0.8s ease-in-out; 58 | } 59 | 60 | input, textarea, button { 61 | font-family: inherit; 62 | } 63 | 64 | .apexcharts-tooltip { 65 | color: #222430; 66 | } 67 | 68 | .css-1vmnjpn-skeletonStyles-Skeleton { 69 | background-color: rgb(204 204 204 / 90%) !important; 70 | background-image: linear-gradient(90deg,#cccccc,rgb(238 238 238 / 90%),rgb(204 204 204 / 90%) ) !important; 71 | animation: animation-16jpnkj 1.8s ease-in-out infinite !important; 72 | } 73 | 74 | * { 75 | box-sizing: border-box; 76 | scroll-behavior: smooth; 77 | } 78 | ` 79 | 80 | useEffect(() => { 81 | const fonts = Object.entries(theme.fonts || {}) 82 | fonts.forEach(([name, fontFamily]) => { 83 | if (!window.document.getElementById(`${name}-font-styles`)) { 84 | const font = window.document.createElement('link') 85 | font.id = `${name}-font-styles` 86 | font.rel = 'stylesheet' 87 | font.async = true 88 | font.defer = true 89 | font.href = `https://fonts.googleapis.com/css?family=${fontFamily.name}` 90 | 91 | window.document.body.appendChild(font) 92 | } 93 | }) 94 | }, [theme]) 95 | 96 | const update = (theme) => { 97 | setTheme(theme) 98 | } 99 | 100 | const merge = (partTheme) => { 101 | setTheme({ 102 | ...theme, 103 | ...partTheme 104 | }) 105 | } 106 | 107 | return ( 108 | 109 | 110 | 111 | {children} 112 | 113 | 114 | ) 115 | } 116 | 117 | /** 118 | * Hook to get theme state 119 | */ 120 | export const useTheme = () => { 121 | const themeManager = useContext(ThemeContext) 122 | return themeManager || [{}] 123 | } 124 | -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/PancakeERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16; 3 | 4 | import '@openzeppelin/contracts/utils/math/SafeMath.sol'; 5 | import './interfaces/IPancakeERC20.sol'; 6 | 7 | contract PancakeERC20 is IPancakeERC20 { 8 | using SafeMath for uint; 9 | 10 | string public constant name = 'Pancake LPs'; 11 | string public constant symbol = 'Cake-LP'; 12 | uint8 public constant decimals = 18; 13 | uint public totalSupply; 14 | mapping(address => uint) public balanceOf; 15 | mapping(address => mapping(address => uint)) public allowance; 16 | 17 | bytes32 public DOMAIN_SEPARATOR; 18 | // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 19 | bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; 20 | mapping(address => uint) public nonces; 21 | 22 | constructor() { 23 | uint chainId; 24 | assembly { 25 | chainId := chainid() 26 | } 27 | DOMAIN_SEPARATOR = keccak256( 28 | abi.encode( 29 | keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), 30 | keccak256(bytes(name)), 31 | keccak256(bytes('1')), 32 | chainId, 33 | address(this) 34 | ) 35 | ); 36 | } 37 | 38 | function _mint(address to, uint value) internal { 39 | totalSupply = totalSupply.add(value); 40 | balanceOf[to] = balanceOf[to].add(value); 41 | emit Transfer(address(0), to, value); 42 | } 43 | 44 | function _burn(address from, uint value) internal { 45 | balanceOf[from] = balanceOf[from].sub(value); 46 | totalSupply = totalSupply.sub(value); 47 | emit Transfer(from, address(0), value); 48 | } 49 | 50 | function _approve(address owner, address spender, uint value) private { 51 | allowance[owner][spender] = value; 52 | emit Approval(owner, spender, value); 53 | } 54 | 55 | function _transfer(address from, address to, uint value) private { 56 | balanceOf[from] = balanceOf[from].sub(value); 57 | balanceOf[to] = balanceOf[to].add(value); 58 | emit Transfer(from, to, value); 59 | } 60 | 61 | function approve(address spender, uint value) external returns (bool) { 62 | _approve(msg.sender, spender, value); 63 | return true; 64 | } 65 | 66 | function transfer(address to, uint value) external returns (bool) { 67 | _transfer(msg.sender, to, value); 68 | return true; 69 | } 70 | 71 | function transferFrom(address from, address to, uint value) external override returns (bool) { 72 | if (allowance[from][msg.sender] != ~uint(0)) { 73 | allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); 74 | } 75 | _transfer(from, to, value); 76 | return true; 77 | } 78 | 79 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { 80 | require(deadline >= block.timestamp, 'Pancake: EXPIRED'); 81 | bytes32 digest = keccak256( 82 | abi.encodePacked( 83 | '\x19\x01', 84 | DOMAIN_SEPARATOR, 85 | keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) 86 | ) 87 | ); 88 | address recoveredAddress = ecrecover(digest, v, r, s); 89 | require(recoveredAddress != address(0) && recoveredAddress == owner, 'Pancake: INVALID_SIGNATURE'); 90 | _approve(owner, spender, value); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /dapp/src/components/SideBar/index.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useEffect, useRef, useState } from 'react' 2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' 3 | import { solid, regular, brands, icon } from '@fortawesome/fontawesome-svg-core/import.macro' 4 | 5 | import { 6 | SideBarContainer 7 | } from './styles' 8 | 9 | import LogoPNG from '../../assets/images/mark.png' 10 | 11 | import { 12 | DashboardSVG, 13 | AccountSVG, 14 | SwapSVG, 15 | DocsSVG, 16 | TwitterSVG, 17 | TelegramSVG, 18 | } from '../SvgIcons' 19 | 20 | import { MenuItem } from './MenuItem' 21 | import { useCustomWallet } from '../../contexts/WalletContext' 22 | import { useWindowSize } from '../../hooks/useWindowSize' 23 | import { useSelector } from 'react-redux' 24 | 25 | export const SideBar = (props) => { 26 | const selectedChainId = useSelector(state => state.chain.chainId) 27 | const currentTokenAddress = useSelector(state => state.token.address) 28 | const explorerURL = useSelector(state => state.chain.explorer) 29 | 30 | const w = useWindowSize(); 31 | const { visible, close } = props; 32 | 33 | const thisInst = useRef(); 34 | 35 | const { isLoggedIn } = useCustomWallet(); 36 | const [selectMenu, setSelectMenu] = useState(0); 37 | 38 | const handleClick = (t) => { 39 | setSelectMenu(t); 40 | 41 | if (w.width < 864) { 42 | close && close(); 43 | } 44 | } 45 | 46 | const handleClickOutside = useCallback((e) => { 47 | const outSideMenu = !thisInst.current?.contains(e.target) 48 | 49 | if (outSideMenu && w.width < 864 && thisInst.current?.offsetLeft === 0) { 50 | close && close(); 51 | } 52 | }, [close, w.width]) 53 | 54 | useEffect(() => { 55 | window.addEventListener('click', handleClickOutside) 56 | return () => window.removeEventListener('click', handleClickOutside) 57 | }, [handleClickOutside]) 58 | 59 | return ( 60 | 61 |
62 | 63 |
64 | { 65 | {currentTokenAddress.slice(0, 6) + '...' + currentTokenAddress.slice(-5)} 66 | } 67 | 68 | } text='Dashboard' link='/dashboard' handleClick={() => handleClick(1)} selected={selectMenu === 1}/> 69 | } text='Account' link='/account' handleClick={() => handleClick(2)} selected={selectMenu === 2}/> 70 | {/* } text='NovaSwap' link='/novaswap' handleClick={() => handleClick(3)} selected={selectMenu === 3}/> */} 71 | } text='SushiSwap' link={`https://app.sushi.com/swap?inputCurrency=${currentTokenAddress}&outputCurrency=ETH&chainId=${selectedChainId}`} external handleClick={() => handleClick(4)} selected={selectMenu === 4}/> 72 | } text='Docs' link='https://nova-finance-arbitrum.gitbook.io/nova-finance/' external handleClick={() => handleClick(5)} selected={selectMenu === 5}/> 73 | 74 |
75 | } link='https://twitter.com/Nova_Finance_' external small handleClick={() => handleClick(0)}/> 76 | } link='https://t.me/Nova_Fi' external small handleClick={() => handleClick(0)}/> 77 |
78 |
79 | ) 80 | } 81 | -------------------------------------------------------------------------------- /dapp/src/components/Toast/Toast/index.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useEffect, useRef } from 'react' 2 | import { StyledToast, FrameToastRect, IconRegion, TitleDescription, TitleTextArea, DescriptionTextArea } from './styles' 3 | import { CSSTransition } from 'react-transition-group' 4 | 5 | const Toast = ({ toast, onRemove, style, ttl, ...props }) => { 6 | const timer = useRef() 7 | const ref = useRef(null) 8 | const removeHandler = useRef(onRemove) 9 | const { id, title, description, type } = toast 10 | 11 | const handleRemove = useCallback(() => { 12 | removeHandler.current(id); 13 | }, [id, removeHandler]) 14 | 15 | const handleMouseEnter = () => { 16 | clearTimeout(timer.current) 17 | } 18 | 19 | const handleMouseDown = () => { 20 | handleRemove(); 21 | } 22 | 23 | const handleMouseLeave = () => { 24 | if (timer.current) { 25 | clearTimeout(timer.current) 26 | } 27 | 28 | timer.current = window.setTimeout(() => { 29 | handleRemove() 30 | }, ttl) 31 | } 32 | 33 | useEffect(() => { 34 | if (timer.current) { 35 | clearTimeout(timer.current) 36 | } 37 | 38 | timer.current = window.setTimeout(() => { 39 | handleRemove() 40 | }, ttl) 41 | 42 | return () => { 43 | clearTimeout(timer.current) 44 | } 45 | }, [timer, ttl, handleRemove]) 46 | 47 | return ( 48 | 49 | 50 | {/* */} 51 | 52 | 53 | {type === 'success' && 54 | 55 | 56 | 57 | } 58 | {type === 'info' && 59 | 60 | 61 | 62 | } 63 | { 64 | type === 'danger' && 65 | 76 | 77 | } 78 | 79 | 80 | 81 | {title} 82 | 83 | 84 | {description} 85 | 86 | 87 | 88 | {/* */} 89 | 90 | 91 | ) 92 | } 93 | 94 | export default Toast 95 | -------------------------------------------------------------------------------- /dapp/src/contexts/ContractContext/abi/IPancakeFactory.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "IPancakeFactory", 3 | "abi": [ 4 | { 5 | "anonymous": false, 6 | "inputs": [ 7 | { 8 | "indexed": true, 9 | "internalType": "address", 10 | "name": "token0", 11 | "type": "address" 12 | }, 13 | { 14 | "indexed": true, 15 | "internalType": "address", 16 | "name": "token1", 17 | "type": "address" 18 | }, 19 | { 20 | "indexed": false, 21 | "internalType": "address", 22 | "name": "pair", 23 | "type": "address" 24 | }, 25 | { 26 | "indexed": false, 27 | "internalType": "uint256", 28 | "name": "", 29 | "type": "uint256" 30 | } 31 | ], 32 | "name": "PairCreated", 33 | "type": "event" 34 | }, 35 | { 36 | "inputs": [], 37 | "name": "feeTo", 38 | "outputs": [ 39 | { 40 | "internalType": "address", 41 | "name": "", 42 | "type": "address" 43 | } 44 | ], 45 | "stateMutability": "view", 46 | "type": "function" 47 | }, 48 | { 49 | "inputs": [], 50 | "name": "feeToSetter", 51 | "outputs": [ 52 | { 53 | "internalType": "address", 54 | "name": "", 55 | "type": "address" 56 | } 57 | ], 58 | "stateMutability": "view", 59 | "type": "function" 60 | }, 61 | { 62 | "inputs": [ 63 | { 64 | "internalType": "address", 65 | "name": "tokenA", 66 | "type": "address" 67 | }, 68 | { 69 | "internalType": "address", 70 | "name": "tokenB", 71 | "type": "address" 72 | } 73 | ], 74 | "name": "getPair", 75 | "outputs": [ 76 | { 77 | "internalType": "address", 78 | "name": "pair", 79 | "type": "address" 80 | } 81 | ], 82 | "stateMutability": "view", 83 | "type": "function" 84 | }, 85 | { 86 | "inputs": [ 87 | { 88 | "internalType": "uint256", 89 | "name": "", 90 | "type": "uint256" 91 | } 92 | ], 93 | "name": "allPairs", 94 | "outputs": [ 95 | { 96 | "internalType": "address", 97 | "name": "pair", 98 | "type": "address" 99 | } 100 | ], 101 | "stateMutability": "view", 102 | "type": "function" 103 | }, 104 | { 105 | "inputs": [], 106 | "name": "allPairsLength", 107 | "outputs": [ 108 | { 109 | "internalType": "uint256", 110 | "name": "", 111 | "type": "uint256" 112 | } 113 | ], 114 | "stateMutability": "view", 115 | "type": "function" 116 | }, 117 | { 118 | "inputs": [ 119 | { 120 | "internalType": "address", 121 | "name": "tokenA", 122 | "type": "address" 123 | }, 124 | { 125 | "internalType": "address", 126 | "name": "tokenB", 127 | "type": "address" 128 | } 129 | ], 130 | "name": "createPair", 131 | "outputs": [ 132 | { 133 | "internalType": "address", 134 | "name": "pair", 135 | "type": "address" 136 | } 137 | ], 138 | "stateMutability": "nonpayable", 139 | "type": "function" 140 | }, 141 | { 142 | "inputs": [ 143 | { 144 | "internalType": "address", 145 | "name": "", 146 | "type": "address" 147 | } 148 | ], 149 | "name": "setFeeTo", 150 | "outputs": [], 151 | "stateMutability": "nonpayable", 152 | "type": "function" 153 | }, 154 | { 155 | "inputs": [ 156 | { 157 | "internalType": "address", 158 | "name": "", 159 | "type": "address" 160 | } 161 | ], 162 | "name": "setFeeToSetter", 163 | "outputs": [], 164 | "stateMutability": "nonpayable", 165 | "type": "function" 166 | } 167 | ] 168 | } -------------------------------------------------------------------------------- /dapp/src/components/RightPane/index.js: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react' 2 | 3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' 4 | import { solid, regular, brands, icon } from '@fortawesome/fontawesome-svg-core/import.macro' 5 | 6 | import { 7 | Route, 8 | Routes, 9 | useLocation 10 | } from 'react-router-dom' 11 | 12 | import { 13 | RightPaneContainer 14 | } from './styles' 15 | 16 | import { TransitionGroup } from 'react-transition-group' 17 | import { SmallButton } from '../SmallButton' 18 | import { Dashboard } from '../Dashboard' 19 | import { Account } from '../Account' 20 | // import { Swap } from '../Swap' 21 | import Wallet from '../Wallet' 22 | import useToast from '../../hooks/useToast' 23 | import { useCustomWallet } from '../../contexts/WalletContext' 24 | import { CSSTransition } from 'react-transition-group' 25 | import { useSelector } from 'react-redux' 26 | 27 | import { MetamaskSVG } from '../SvgIcons' 28 | 29 | export const RightPane = (props) => { 30 | const { address, symbol, decimals } = useSelector(state => state.token) 31 | 32 | const { handleSideBarShow } = props; 33 | 34 | const location = useLocation(); 35 | 36 | const { connectWallet, disconnectWallet, wallet, isLoggedIn } = useCustomWallet(); 37 | const { toastError } = useToast(); 38 | 39 | const handleAddTokenToWallet = useCallback(async () => { 40 | if (window.ethereum === undefined) { 41 | toastError('Add token', 'Not Installed Metamask') 42 | return; 43 | } 44 | 45 | const tokenAddress = address; 46 | const tokenSymbol = symbol; 47 | const tokenDecimals = decimals; 48 | const tokenImage = ''; 49 | 50 | try { 51 | // wasAdded is a boolean. Like any RPC method, an error may be thrown. 52 | // const wasAdded = 53 | await window.ethereum.request({ 54 | method: 'wallet_watchAsset', 55 | params: { 56 | type: 'ERC20', // Initially only supports ERC20, but eventually more! 57 | options: { 58 | address: tokenAddress, // The address that the token is at. 59 | symbol: tokenSymbol, // A ticker symbol or shorthand, up to 5 chars. 60 | decimals: tokenDecimals, // The number of decimals in the token 61 | image: tokenImage, // A string url of the token logo 62 | }, 63 | }, 64 | }); 65 | 66 | // if (wasAdded) { 67 | // await toastSuccess('Metamask', 'Token added') 68 | // } else { 69 | // await toastError('Metamask', 'Already exists') 70 | // } 71 | } catch (error) { 72 | await toastError('Metamask', `${error.message}`) 73 | } 74 | }, [toastError, address, symbol, decimals]) 75 | 76 | return ( 77 | 78 |
79 |
80 |
81 |
{setTimeout(() => handleSideBarShow(), 300)}}> 82 |
83 |
84 |
85 |
86 | 87 | metamask 88 |
89 | 92 | : 93 | 94 | } 95 | caption={ 96 | isLoggedIn() === true? 97 | `Logout ${wallet.address.slice(0, 6) + '...' + wallet.address.slice(-5)}` 98 | : 99 | 'Connect Wallet' 100 | } 101 | handleClick={() => isLoggedIn() === true ? disconnectWallet() : connectWallet()} /> 102 |
103 |
104 |
105 | 106 | 111 |
112 | { 113 | isLoggedIn() === true ? 114 | 115 | }> 116 | }> 117 | }> 118 | {/* }> */} 119 | 120 | : 121 |
122 | 123 |
124 | } 125 |
126 |
127 |
128 |
129 |
130 | ) 131 | } 132 | -------------------------------------------------------------------------------- /dapp/src/components/Dashboard/index.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import BN from 'bignumber.js' 3 | 4 | import { 5 | DashboardContainer 6 | } from './styles' 7 | 8 | import { DashboardItemInfo } from './DashboardItemInfo' 9 | import { useGlobal } from '../../contexts/GlobalContext' 10 | import { useSelector } from 'react-redux' 11 | 12 | export const Dashboard = (props) => { 13 | 14 | const { symbol, price: tokenPrice, circulatingSupply, supply: total, lastRebasedTime: lastRebased, 15 | poolBalance, firePitBalance, rebasePeriod, 16 | treasuryUSDC: treasuryUSD, treasuryBalance, insuranceReceiverUSDC: insuranceBalanceUSD} = useSelector(state => state.token) 17 | 18 | const { stringFormat, cutDecimal } = useGlobal() 19 | 20 | const [marketCap, setMarketCap] = useState(0) 21 | const [remainingTime, setRemainingTime] = useState('') 22 | const [poolBalanceUSD, setPoolBalanceUSD] = useState(0) 23 | 24 | const [firePitBalanceUSD, setFirePitBalanceUSD] = useState(0) 25 | const [firePitPercentage, setFirePitPercentage] = useState(0) 26 | 27 | useEffect(() => { 28 | let ac = new AbortController(); 29 | 30 | const recursive_run = (ac) => { 31 | if (ac.signal.aborted === false) { 32 | let now1 = (new Date()).getTime() / 1000; 33 | let now = ~~now1; 34 | 35 | let torg = now - lastRebased 36 | let period = rebasePeriod; 37 | let tt = (torg + period - 1) / period; 38 | let t1 = ~~tt; 39 | tt = t1 * period - torg; 40 | 41 | t1 = tt / 60; 42 | let minutes = ~~t1; 43 | let seconds = tt - minutes * 60; 44 | 45 | setRemainingTime(`00:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`) 46 | 47 | setTimeout(() => recursive_run(ac), 1000); 48 | } 49 | } 50 | 51 | recursive_run(ac); 52 | 53 | return () => ac.abort(); 54 | }, [lastRebased, rebasePeriod]) 55 | 56 | useEffect(() => { 57 | setMarketCap(BN(tokenPrice).times(BN(circulatingSupply)).toString()) 58 | }, [tokenPrice, circulatingSupply]) 59 | 60 | // useEffect(() => { 61 | // setTreasuryUSD(tokenPrice * treasuryBalance); 62 | // }, [tokenPrice, treasuryBalance]) 63 | 64 | useEffect(() => { 65 | setFirePitBalanceUSD(BN(tokenPrice).times(BN(firePitBalance)).toString()) 66 | }, [tokenPrice, firePitBalance]) 67 | 68 | useEffect(() => { 69 | setPoolBalanceUSD(tokenPrice * poolBalance); 70 | }, [tokenPrice, poolBalance]) 71 | 72 | useEffect(() => { 73 | if (BN(total).gt(0)) { 74 | setFirePitPercentage(BN(firePitBalance).times(100).div(BN(total)).toString()) 75 | } else { 76 | setFirePitPercentage("0"); 77 | } 78 | }, [firePitBalance, total]) 79 | 80 | return ( 81 | 82 |
83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 |
91 | 92 |
93 |
94 | 95 |
96 |
97 | 98 |
99 |
100 | 101 |
102 |
103 | 104 |
105 | 106 |
107 | 108 |
109 |
110 | 111 |
112 |
113 | 114 |
115 |
116 | 117 |
118 |
119 | ) 120 | } 121 | -------------------------------------------------------------------------------- /dapp/src/contexts/ReduxContext/reducers/token.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit' 2 | import { convertToString, convertToInteger } from './tools' 3 | 4 | const initialState = { 5 | address: "", 6 | name: "", 7 | symbol: "", 8 | decimals: 0, 9 | 10 | owner: "", 11 | supply: "", 12 | price: "", 13 | circulatingSupply: "", 14 | lastRebasedTime: 0, 15 | tickNow: 0, 16 | initRebaseTime: 0, 17 | rebaseRate: "", 18 | rebasePeriod: 0, 19 | balance: "", 20 | balanceETH: "", 21 | treasuryAddress: "", 22 | treasuryBalance: "", 23 | treasuryUSDC: "", 24 | firePitAddress: "", 25 | firePitBalance: "", 26 | insuranceReceiverAddress: "", 27 | insuranceReceiverUSDC: "", 28 | poolBalance: "", 29 | maxWallet: "", 30 | remToBuy: "", 31 | remToSell: "", 32 | isFeeExempt: false, 33 | ethPrice: "", 34 | } 35 | 36 | const token = createSlice({ 37 | name: 'token', 38 | initialState, 39 | reducers: { 40 | updateAddress: (state, action) => { 41 | state.address = convertToString(action.payload) 42 | }, 43 | updateName: (state, action) => { 44 | state.name = convertToString(action.payload) 45 | }, 46 | updateSymbol: (state, action) => { 47 | state.symbol = convertToString(action.payload) 48 | }, 49 | updateDecimals: (state, action) => { 50 | state.decimals = convertToInteger(action.payload) 51 | }, 52 | updateOwner: (state, action) => { 53 | state.owner = convertToString(action.payload) 54 | }, 55 | updateSupply: (state, action) => { 56 | state.supply = convertToString(action.payload) 57 | }, 58 | updatePrice: (state, action) => { 59 | state.price = convertToString(action.payload) 60 | }, 61 | updateCirculatingSupply: (state, action) => { 62 | state.circulatingSupply = convertToString(action.payload) 63 | }, 64 | updateLastRebasedTime: (state, action) => { 65 | state.lastRebasedTime = convertToInteger(action.payload) 66 | state.tickNow = Math.floor((new Date()).getTime() / 1000) 67 | }, 68 | updateInitRebaseTime: (state, action) => { 69 | state.initRebaseTime = convertToInteger(action.payload) 70 | }, 71 | updateRebaseRate: (state, action) => { 72 | state.rebaseRate = convertToString(action.payload) 73 | }, 74 | updateRebasePeriod: (state, action) => { 75 | state.rebasePeriod = convertToInteger(action.payload) 76 | }, 77 | updateBalance: (state, action) => { 78 | state.balance = convertToString(action.payload) 79 | }, 80 | updateBalanceETH: (state, action) => { 81 | state.balanceETH = convertToString(action.payload) 82 | }, 83 | updateTreasuryAddress: (state, action) => { 84 | state.treasuryAddress = convertToString(action.payload) 85 | }, 86 | updateTreasuryBalance: (state, action) => { 87 | state.treasuryBalance = convertToString(action.payload) 88 | }, 89 | updateTreasuryUSDC: (state, action) => { 90 | state.treasuryUSDC = convertToString(action.payload) 91 | }, 92 | updateFirePitAddress: (state, action) => { 93 | state.firePitAddress = convertToString(action.payload) 94 | }, 95 | updateFirePitBalance: (state, action) => { 96 | state.firePitBalance = convertToString(action.payload) 97 | }, 98 | updateInsuranceReceiverAddress: (state, action) => { 99 | state.insuranceReceiverAddress = convertToString(action.payload) 100 | }, 101 | updateInsuranceReceiverUSDC: (state, action) => { 102 | state.insuranceReceiverUSDC = convertToString(action.payload) 103 | }, 104 | updatePoolBalance: (state, action) => { 105 | state.poolBalance = convertToString(action.payload) 106 | }, 107 | updateMaxWallet: (state, action) => { 108 | state.maxWallet = convertToString(action.payload) 109 | }, 110 | updateRemainingToBuy: (state, action) => { 111 | state.remToBuy = convertToString(action.payload) 112 | }, 113 | updateRemainingToSell: (state, action) => { 114 | state.remToSell = convertToString(action.payload) 115 | }, 116 | updateFeeExempted: (state, action) => { 117 | state.isFeeExempt = action.payload 118 | }, 119 | updateETHPrice: (state, action) => { 120 | state.ethPrice = convertToString(action.payload) 121 | }, 122 | } 123 | }) 124 | 125 | export const { updateAddress, updateName, updateSymbol, updateDecimals, 126 | updateOwner, updateSupply, updatePrice, updateCirculatingSupply, 127 | updateLastRebasedTime, updateInitRebaseTime, updateRebaseRate, updateRebasePeriod, updateBalance, 128 | updateBalanceETH, updateTreasuryAddress, updateTreasuryUSDC, updateTreasuryBalance, 129 | updateFirePitAddress, updateFirePitBalance, updateInsuranceReceiverAddress, 130 | updateInsuranceReceiverUSDC, updatePoolBalance, updateMaxWallet, 131 | updateRemainingToBuy, updateRemainingToSell, updateFeeExempted, 132 | updateETHPrice } = token.actions 133 | 134 | export default token.reducer 135 | -------------------------------------------------------------------------------- /dapp/src/components/Swap/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const SwapContainer = styled.div` 4 | width: 100%; 5 | height: 100%; 6 | 7 | overflow: hidden; 8 | overflow-y: auto; 9 | 10 | display: flex; 11 | flex-direction: row; 12 | justify-content: center; 13 | 14 | .info-frame { 15 | border-radius: 10px; 16 | border: 1px solid rgb(98, 116, 94); 17 | background: rgba(0,0,0,0.2); 18 | 19 | -webkit-backdrop-filter: blur(4px); 20 | backdrop-filter: blur(4px); 21 | } 22 | 23 | .top-frame { 24 | margin: 0px 20px; 25 | 26 | display: flex; 27 | flex-direction: column; 28 | flex-gap: 20px; 29 | gap: 20px; 30 | 31 | width: 100%; 32 | max-width: 833px; 33 | 34 | .reflection-frame { 35 | display: flex; 36 | flex-direction: row; 37 | align-items: center; 38 | justify-content: space-between; 39 | 40 | .reflection-caption { 41 | flex: 1 1 auto; 42 | font-size: 1.3rem; 43 | letter-spacing: 1px; 44 | text-align: center; 45 | } 46 | } 47 | 48 | .summary-frame-col { 49 | display: flex; 50 | flex-direction: column; 51 | padding: 20px 20px; 52 | 53 | .my-balance-amount { 54 | position: absolute; 55 | top: -10px; 56 | right: -10px; 57 | 58 | font-size: 12px; 59 | 60 | cursor: pointer; 61 | filter: drop-shadow(0px 0px 0px white); 62 | 63 | transition: all 0.2s ease-in-out; 64 | 65 | &:hover { 66 | font-size: 13px; 67 | filter: drop-shadow(0px 0px 4px white); 68 | } 69 | 70 | &:active { 71 | font-size: 13px; 72 | filter: drop-shadow(0px 0px 4px black); 73 | } 74 | } 75 | 76 | .item-input-frame { 77 | display: flex; 78 | flex-direction: row; 79 | align-items: center; 80 | justify-content: space-between; 81 | 82 | .button-frame { 83 | width: 100%; 84 | display: flex; 85 | justify-content: center; 86 | cursor: pointer; 87 | 88 | filter: drop-shadow(0px 0px 0px white); 89 | opacity: 1; 90 | 91 | transition: all 0.2s ease-in-out; 92 | 93 | &:hover { 94 | filter: drop-shadow(0px 0px 8px white); 95 | } 96 | 97 | &:active { 98 | opacity: 0.6; 99 | } 100 | } 101 | 102 | .item-label { 103 | flex: 1 1 0; 104 | 105 | display: flex; 106 | flex-direction: row; 107 | align-items: center; 108 | justify-content: center; 109 | 110 | padding: 0px 20px; 111 | 112 | p { 113 | font-size: 1.1rem; 114 | padding: 0px 10px; 115 | } 116 | } 117 | 118 | .item-decor-1 { 119 | position: relative; 120 | 121 | ::before { 122 | position: absolute; 123 | top: 0; 124 | left: -1px; 125 | right: -1px; 126 | bottom: -2px; 127 | content: ""; 128 | 129 | border-radius: 10px; 130 | 131 | background: linear-gradient(to right, #00ff00, #ffff00 50%, #ff0000); 132 | z-index: -1; 133 | } 134 | } 135 | 136 | .item-decor-2 { 137 | position: relative; 138 | 139 | ::before { 140 | position: absolute; 141 | top: 0; 142 | left: -1px; 143 | right: -1px; 144 | bottom: -2px; 145 | content: ""; 146 | 147 | border-radius: 10px; 148 | 149 | background: linear-gradient(to right, #ff0000, #00ff00 50%, #ffff00); 150 | z-index: -1; 151 | } 152 | } 153 | 154 | .item-input { 155 | flex: 1 1 0; 156 | 157 | display: flex; 158 | flex-direction: row; 159 | align-items: center; 160 | justify-content: left; 161 | 162 | input { 163 | width: 100%; 164 | outline: none; 165 | border: none; 166 | 167 | border-radius: 10px; 168 | padding: 6px 10px; 169 | 170 | font-size: 16px; 171 | font-weight: 800; 172 | 173 | filter: drop-shadow(2px 2px 6px green); 174 | 175 | ::placeholder { 176 | color: #eee; 177 | } 178 | } 179 | } 180 | } 181 | 182 | .button-input-frame { 183 | display: flex; 184 | flex-direction: row; 185 | justify-content: center; 186 | 187 | .swap-button-frame { 188 | padding: 0px 10px; 189 | 190 | display: flex; 191 | flex-direction: row; 192 | align-items: center; 193 | justify-content: center; 194 | 195 | .swap-button { 196 | cursor: pointer; 197 | border-radius: 10px; 198 | padding: 4px 10px; 199 | background: #aaa; 200 | margin: 0px 10px; 201 | } 202 | } 203 | } 204 | 205 | .error-frame { 206 | font-size: 16px; 207 | text-align: center; 208 | 209 | a { 210 | color: #ddd; 211 | font-weight: 800; 212 | 213 | &:hover { 214 | color: #eee; 215 | } 216 | 217 | &:active { 218 | color: #ccc; 219 | } 220 | } 221 | } 222 | } 223 | } 224 | `; 225 | -------------------------------------------------------------------------------- /smartcontracts/truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * trufflesuite.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like @truffle/hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | 21 | const HDWalletProvider = require('@truffle/hdwallet-provider'); 22 | const fs = require('fs'); 23 | const pvKey = fs.readFileSync(".secret").toString().trim(); 24 | const mnemonicTest = "dice off awake occur broken hamster play elegant vague obtain below tackle"; 25 | 26 | module.exports = { 27 | /** 28 | * Networks define how you connect to your ethereum client and let you set the 29 | * defaults web3 uses to send transactions. If you don't specify one truffle 30 | * will spin up a development blockchain for you on port 9545 when you 31 | * run `develop` or `test`. You can ask a truffle command to use a specific 32 | * network from the command line, e.g 33 | * 34 | * $ truffle test --network 35 | */ 36 | 37 | 38 | 39 | networks: { 40 | // Useful for testing. The `development` name is special - truffle uses it by default 41 | // if it's defined here and no other network is specified at the command line. 42 | // You should run a client (like ganache-cli, geth or parity) in a separate terminal 43 | // tab if you use this network and you must also set the `host`, `port` and `network_id` 44 | // options below to some value. 45 | // 46 | development: { 47 | provider: () => new HDWalletProvider(mnemonicTest, `http://127.0.0.1:8545`), 48 | host: "127.0.0.1", // Localhost (default: none) 49 | port: 8545, // Standard Ethereum port (default: none) 50 | network_id: "*", // Any network (default: none) 51 | timeoutBlocks: 9999999, 52 | 53 | }, 54 | // Useful for deploying to a public network. 55 | // NB: It's important to wrap the provider as a function. 56 | // ropsten: { 57 | // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), 58 | // network_id: 3, // Ropsten's id 59 | // gas: 5500000, // Ropsten has a lower block limit than mainnet 60 | // confirmations: 2, // # of confs to wait between deployments. (default: 0) 61 | // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 62 | // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) 63 | // }, 64 | // Useful for private networks 65 | // private: { 66 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 67 | // network_id: 2111, // This network is yours, in the cloud. 68 | // production: true // Treats this network as if it was a public net. (default: false) 69 | // } 70 | 71 | bsctestnet: { 72 | provider: () => new HDWalletProvider(pvKey, `https://data-seed-prebsc-1-s3.binance.org:8545/`), //`https://data-seed-prebsc-1-s1.binance.org:8545/` 73 | network_id: 97, // This network is yours, in the cloud. 74 | production: true, // Treats this network as if it was a public net. (default: false) 75 | timeoutBlocks: 9999999, 76 | skipDryRun: true 77 | }, 78 | 79 | bscmainnet: { 80 | provider: () => new HDWalletProvider(pvKey, `https://bsc-dataseed.binance.org/`), 81 | network_id: 56, // This network is yours, in the cloud. 82 | production: true, // Treats this network as if it was a public net. (default: false) 83 | timeoutBlocks: 9999999, 84 | skipDryRun: true 85 | }, 86 | 87 | ethereum: { 88 | provider: () => new HDWalletProvider(pvKey, `https://mainnet.infura.io/v3/7535811d19b1410e98c261fbb638651a`), 89 | network_id: 1, // This network is yours, in the cloud. 90 | production: true, // Treats this network as if it was a public net. (default: false) 91 | timeoutBlocks: 9999999, 92 | skipDryRun: true 93 | }, 94 | 95 | goerli: { 96 | provider: () => new HDWalletProvider(pvKey, `https://eth-goerli.g.alchemy.com/v2/NIZ86SMaasaawNVp7cEDm0LhVAcjv3uo`), 97 | network_id: 5, // This network is yours, in the cloud. 98 | production: true, // Treats this network as if it was a public net. (default: false) 99 | timeoutBlocks: 9999999, 100 | skipDryRun: true 101 | } 102 | }, 103 | 104 | // Set default mocha options here, use special reporters etc. 105 | mocha: { 106 | timeout: 10000000 107 | }, 108 | 109 | // Configure your compilers 110 | compilers: { 111 | solc: { 112 | version: "0.8.16", // Fetch exact version from solc-bin (default: truffle's version) 113 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 114 | settings: { // See the solidity docs for advice about optimization and evmVersion 115 | optimizer: { 116 | enabled: true, 117 | runs: 200 118 | }, 119 | // evmVersion: "byzantium" 120 | } 121 | } 122 | }, 123 | 124 | // Truffle DB is currently disabled by default; to enable it, change enabled: 125 | // false to enabled: true. The default storage location can also be 126 | // overridden by specifying the adapter settings, as shown in the commented code below. 127 | // 128 | // NOTE: It is not possible to migrate your contracts to truffle DB and you should 129 | // make a backup of your artifacts to a safe location before enabling this feature. 130 | // 131 | // After you backed up your artifacts you can utilize db by running migrate as follows: 132 | // $ truffle migrate --reset --compile-all 133 | // 134 | // db: { 135 | // enabled: false, 136 | // host: "127.0.0.1", 137 | // adapter: { 138 | // name: "sqlite", 139 | // settings: { 140 | // directory: ".db" 141 | // } 142 | // } 143 | // } 144 | 145 | dashboard: { 146 | port: 25012, 147 | host: "localhost" 148 | }, 149 | 150 | plugins: [ 151 | 'truffle-plugin-verify' 152 | ], 153 | api_keys : { 154 | bscscan : "JAKBSWZ3IT7ZF7EF3EZPWN7HPKEHXPJMVE" 155 | } 156 | }; 157 | -------------------------------------------------------------------------------- /dapp/src/contexts/ContractContext/abi/ERC20.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "ERC20", 3 | "abi": [ 4 | { 5 | "inputs": [ 6 | { 7 | "internalType": "string", 8 | "name": "name_", 9 | "type": "string" 10 | }, 11 | { 12 | "internalType": "string", 13 | "name": "symbol_", 14 | "type": "string" 15 | } 16 | ], 17 | "stateMutability": "nonpayable", 18 | "type": "constructor" 19 | }, 20 | { 21 | "anonymous": false, 22 | "inputs": [ 23 | { 24 | "indexed": true, 25 | "internalType": "address", 26 | "name": "owner", 27 | "type": "address" 28 | }, 29 | { 30 | "indexed": true, 31 | "internalType": "address", 32 | "name": "spender", 33 | "type": "address" 34 | }, 35 | { 36 | "indexed": false, 37 | "internalType": "uint256", 38 | "name": "value", 39 | "type": "uint256" 40 | } 41 | ], 42 | "name": "Approval", 43 | "type": "event" 44 | }, 45 | { 46 | "anonymous": false, 47 | "inputs": [ 48 | { 49 | "indexed": true, 50 | "internalType": "address", 51 | "name": "from", 52 | "type": "address" 53 | }, 54 | { 55 | "indexed": true, 56 | "internalType": "address", 57 | "name": "to", 58 | "type": "address" 59 | }, 60 | { 61 | "indexed": false, 62 | "internalType": "uint256", 63 | "name": "value", 64 | "type": "uint256" 65 | } 66 | ], 67 | "name": "Transfer", 68 | "type": "event" 69 | }, 70 | { 71 | "inputs": [], 72 | "name": "name", 73 | "outputs": [ 74 | { 75 | "internalType": "string", 76 | "name": "", 77 | "type": "string" 78 | } 79 | ], 80 | "stateMutability": "view", 81 | "type": "function" 82 | }, 83 | { 84 | "inputs": [], 85 | "name": "symbol", 86 | "outputs": [ 87 | { 88 | "internalType": "string", 89 | "name": "", 90 | "type": "string" 91 | } 92 | ], 93 | "stateMutability": "view", 94 | "type": "function" 95 | }, 96 | { 97 | "inputs": [], 98 | "name": "decimals", 99 | "outputs": [ 100 | { 101 | "internalType": "uint8", 102 | "name": "", 103 | "type": "uint8" 104 | } 105 | ], 106 | "stateMutability": "view", 107 | "type": "function" 108 | }, 109 | { 110 | "inputs": [], 111 | "name": "totalSupply", 112 | "outputs": [ 113 | { 114 | "internalType": "uint256", 115 | "name": "", 116 | "type": "uint256" 117 | } 118 | ], 119 | "stateMutability": "view", 120 | "type": "function" 121 | }, 122 | { 123 | "inputs": [ 124 | { 125 | "internalType": "address", 126 | "name": "account", 127 | "type": "address" 128 | } 129 | ], 130 | "name": "balanceOf", 131 | "outputs": [ 132 | { 133 | "internalType": "uint256", 134 | "name": "", 135 | "type": "uint256" 136 | } 137 | ], 138 | "stateMutability": "view", 139 | "type": "function" 140 | }, 141 | { 142 | "inputs": [ 143 | { 144 | "internalType": "address", 145 | "name": "to", 146 | "type": "address" 147 | }, 148 | { 149 | "internalType": "uint256", 150 | "name": "amount", 151 | "type": "uint256" 152 | } 153 | ], 154 | "name": "transfer", 155 | "outputs": [ 156 | { 157 | "internalType": "bool", 158 | "name": "", 159 | "type": "bool" 160 | } 161 | ], 162 | "stateMutability": "nonpayable", 163 | "type": "function" 164 | }, 165 | { 166 | "inputs": [ 167 | { 168 | "internalType": "address", 169 | "name": "owner", 170 | "type": "address" 171 | }, 172 | { 173 | "internalType": "address", 174 | "name": "spender", 175 | "type": "address" 176 | } 177 | ], 178 | "name": "allowance", 179 | "outputs": [ 180 | { 181 | "internalType": "uint256", 182 | "name": "", 183 | "type": "uint256" 184 | } 185 | ], 186 | "stateMutability": "view", 187 | "type": "function" 188 | }, 189 | { 190 | "inputs": [ 191 | { 192 | "internalType": "address", 193 | "name": "spender", 194 | "type": "address" 195 | }, 196 | { 197 | "internalType": "uint256", 198 | "name": "amount", 199 | "type": "uint256" 200 | } 201 | ], 202 | "name": "approve", 203 | "outputs": [ 204 | { 205 | "internalType": "bool", 206 | "name": "", 207 | "type": "bool" 208 | } 209 | ], 210 | "stateMutability": "nonpayable", 211 | "type": "function" 212 | }, 213 | { 214 | "inputs": [ 215 | { 216 | "internalType": "address", 217 | "name": "from", 218 | "type": "address" 219 | }, 220 | { 221 | "internalType": "address", 222 | "name": "to", 223 | "type": "address" 224 | }, 225 | { 226 | "internalType": "uint256", 227 | "name": "amount", 228 | "type": "uint256" 229 | } 230 | ], 231 | "name": "transferFrom", 232 | "outputs": [ 233 | { 234 | "internalType": "bool", 235 | "name": "", 236 | "type": "bool" 237 | } 238 | ], 239 | "stateMutability": "nonpayable", 240 | "type": "function" 241 | }, 242 | { 243 | "inputs": [ 244 | { 245 | "internalType": "address", 246 | "name": "spender", 247 | "type": "address" 248 | }, 249 | { 250 | "internalType": "uint256", 251 | "name": "addedValue", 252 | "type": "uint256" 253 | } 254 | ], 255 | "name": "increaseAllowance", 256 | "outputs": [ 257 | { 258 | "internalType": "bool", 259 | "name": "", 260 | "type": "bool" 261 | } 262 | ], 263 | "stateMutability": "nonpayable", 264 | "type": "function" 265 | }, 266 | { 267 | "inputs": [ 268 | { 269 | "internalType": "address", 270 | "name": "spender", 271 | "type": "address" 272 | }, 273 | { 274 | "internalType": "uint256", 275 | "name": "subtractedValue", 276 | "type": "uint256" 277 | } 278 | ], 279 | "name": "decreaseAllowance", 280 | "outputs": [ 281 | { 282 | "internalType": "bool", 283 | "name": "", 284 | "type": "bool" 285 | } 286 | ], 287 | "stateMutability": "nonpayable", 288 | "type": "function" 289 | } 290 | ] 291 | } -------------------------------------------------------------------------------- /smartcontracts/test/check.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | const BN = require('bignumber.js') 3 | const fs = require('fs') 4 | 5 | const { checkGetFail, checkTransactionFailed, checkTransactionPassed, advanceTime, advanceBlock, takeSnapshot, revertToSnapShot, advanceTimeAndBlock } = require("./lib/utils.js"); 6 | const { maxUint256, PancakeRouter, PancakeFactory, PancakePair, DividendDistributor, Nova } = require('../migrations/lib/const') 7 | 8 | const { setWeb3 } = require('../migrations/lib/deploy') 9 | const deployParams = require('../migrations/deploy-localhost.json'); 10 | 11 | let errorMessages = { 12 | alreadySet: 'Already Set', 13 | insufficientAllowance: 'ERC20: insufficient allowance', 14 | notLocked: 'Not Locked', 15 | notExpired: 'Not Expired' 16 | } 17 | 18 | const BN2Decimal = (t, decimal) => { 19 | if (decimal === undefined) decimal = 18 20 | return BN(t).div(BN(`1e${decimal}`)).toString() 21 | } 22 | 23 | contract("Nova", accounts => { 24 | let tokenContract 25 | let routerContract 26 | let wethAddress 27 | let treasuryAddress 28 | let tokenDecimals 29 | let maxWallet 30 | let maxBuyPerDay 31 | let maxSellPerDay 32 | 33 | let user1 = accounts[1] 34 | let user2 = accounts[2] 35 | let user3 = accounts[3] 36 | 37 | let oneTimeBuy = new BN('12000000') 38 | 39 | before (async () => { 40 | let routerInfo = deployParams.find(t => t.name === "PancakeRouter") 41 | let wbnbInfo = deployParams.find(t => t.name === 'WBNB') 42 | let tokenInfo = deployParams.find(t => t.name === 'Nova') 43 | 44 | wethAddress = wbnbInfo.imple 45 | tokenContract = await Nova.at(tokenInfo.imple) 46 | routerContract = await PancakeRouter.at(routerInfo.imple) 47 | treasuryAddress = await tokenContract.treasuryReceiver() 48 | tokenDecimals = parseInt((await tokenContract.decimals()).toString()) 49 | 50 | maxWallet = await tokenContract.getMaxTokenPerWallet() 51 | maxBuyPerDay = await tokenContract.getTimeframeQuotaIn() 52 | maxSellPerDay = await tokenContract.getTimeframeQuotaOut() 53 | 54 | setWeb3(web3) 55 | }) 56 | 57 | it ("Adding to the liquidity", async () => { 58 | await tokenContract.approve(routerContract.address, maxUint256, {from: treasuryAddress}) 59 | await routerContract.addLiquidityETH(tokenContract.address, '1000000000', 0, 0, treasuryAddress, '0xffffffff', {from: treasuryAddress, value: web3.utils.toWei('1000')}) 60 | 61 | let pair = await tokenContract.pair() 62 | const pairContract = await PancakePair.at(pair) 63 | let res = await pairContract.getReserves() 64 | let token0 = await pairContract.token0() 65 | 66 | let tokenIndex = 1 67 | let ethIndex = 0 68 | if (token0.toLowerCase() === tokenContract.address.toLowerCase()) { 69 | tokenIndex = 0 70 | ethIndex = 1 71 | } 72 | 73 | console.log('Pair', BN2Decimal(res[tokenIndex].toString(), tokenDecimals.toString()), web3.utils.fromWei(res[ethIndex].toString())) 74 | }) 75 | 76 | const tokenBalance = async (w) => { 77 | let bal = await tokenContract.balanceOf(w) 78 | return BN2Decimal(bal.toString(), tokenDecimals) 79 | } 80 | 81 | const ethBalance = async (w) => { 82 | let bal = await web3.eth.getBalance(w) 83 | return web3.utils.fromWei(bal) 84 | } 85 | 86 | it ("Buying tokens", async () => { 87 | console.log('max wallet', BN2Decimal(maxWallet.toString(), tokenDecimals)) 88 | console.log('max buy per day', BN2Decimal(maxBuyPerDay.toString(), tokenDecimals)) 89 | console.log('max sell per day', BN2Decimal(maxSellPerDay.toString(), tokenDecimals)) 90 | 91 | let info = await tokenContract.getOverviewOf(user1) 92 | console.log(">>> user1's overview now") 93 | console.log('now', parseInt(info[5].toString())) 94 | console.log('reset at', parseInt(info[0].toString())) 95 | console.log('buy amount remainning', BN2Decimal(info[3].toString(), tokenDecimals)) 96 | console.log('sell amount remainning', BN2Decimal(info[4].toString(), tokenDecimals)) 97 | console.log('user1 balance', await tokenBalance(user1)) 98 | console.log('firePit balance', await tokenBalance(await tokenContract.firePit())) 99 | console.log('self balance', await tokenBalance(tokenContract.address)) 100 | console.log('autoLiquidityReceiver balance', await tokenBalance(await tokenContract.autoLiquidityReceiver())) 101 | 102 | let ta = await routerContract.getAmountsOut(oneTimeBuy.toString(), [tokenContract.address, wethAddress]) 103 | await routerContract.swapExactETHForTokensSupportingFeeOnTransferTokens(0, [wethAddress, tokenContract.address], user1, '0xffffffff', {from: user1, value: ta[ta.length - 1].toString()}) 104 | 105 | info = await tokenContract.getOverviewOf(user1) 106 | console.log(">>> user1's overview after buying", BN2Decimal(oneTimeBuy.toString(), tokenDecimals)) 107 | console.log('now', parseInt(info[5].toString())) 108 | console.log('reset at', parseInt(info[0].toString())) 109 | console.log('buy amount remainning', BN2Decimal(info[3].toString(), tokenDecimals)) 110 | console.log('sell amount remainning', BN2Decimal(info[4].toString(), tokenDecimals)) 111 | console.log('user1 balance', await tokenBalance(user1)) 112 | console.log('firePit balance', await tokenBalance(await tokenContract.firePit())) 113 | console.log('self balance', await tokenBalance(tokenContract.address)) 114 | console.log('autoLiquidityReceiver balance', await tokenBalance(await tokenContract.autoLiquidityReceiver())) 115 | }) 116 | 117 | it ("user2 and user3 buy", async () => { 118 | console.log('firePit balance', await tokenBalance(await tokenContract.firePit())) 119 | console.log('self balance', await tokenBalance(tokenContract.address)) 120 | console.log('autoLiquidityReceiver balance', await tokenBalance(await tokenContract.autoLiquidityReceiver())) 121 | 122 | let ta = await routerContract.getAmountsOut(oneTimeBuy.toString(), [tokenContract.address, wethAddress]) 123 | await routerContract.swapExactETHForTokensSupportingFeeOnTransferTokens(0, [wethAddress, tokenContract.address], user2, '0xffffffff', {from: user2, value: ta[ta.length - 1].toString()}) 124 | 125 | ta = await routerContract.getAmountsOut(oneTimeBuy.toString(), [tokenContract.address, wethAddress]) 126 | await routerContract.swapExactETHForTokensSupportingFeeOnTransferTokens(0, [wethAddress, tokenContract.address], user3, '0xffffffff', {from: user3, value: ta[ta.length - 1].toString()}) 127 | 128 | console.log('firePit balance', await tokenBalance(await tokenContract.firePit())) 129 | console.log('self balance', await tokenBalance(tokenContract.address)) 130 | console.log('autoLiquidityReceiver balance', await tokenBalance(await tokenContract.autoLiquidityReceiver())) 131 | }) 132 | 133 | it ("distribution of ETH", async () => { 134 | console.log('treasury ETH', await ethBalance(await tokenContract.treasuryReceiver())) 135 | console.log('dev ETH', await ethBalance(await tokenContract.devAddress())) 136 | console.log('insurance ETH', await ethBalance(await tokenContract.insuranceFundReceiver())) 137 | console.log('reflection ETH', await ethBalance(await tokenContract.distributorAddress())) 138 | console.log('user1 ETH', await ethBalance(user1)) 139 | console.log('user2 ETH', await ethBalance(user2)) 140 | console.log('user3 ETH', await ethBalance(user3)) 141 | 142 | await tokenContract.transfer(accounts[9], '1000000', {from: treasuryAddress}) 143 | 144 | console.log('treasury ETH', await ethBalance(await tokenContract.treasuryReceiver())) 145 | console.log('dev ETH', await ethBalance(await tokenContract.devAddress())) 146 | console.log('insurance ETH', await ethBalance(await tokenContract.insuranceFundReceiver())) 147 | console.log('reflection ETH', await ethBalance(await tokenContract.distributorAddress())) 148 | 149 | await advanceTimeAndBlock(3601); 150 | 151 | await tokenContract.transfer(accounts[9], '1000000', {from: treasuryAddress}) 152 | 153 | console.log('user1 ETH', await ethBalance(user1)) 154 | console.log('user2 ETH', await ethBalance(user2)) 155 | console.log('user3 ETH', await ethBalance(user3)) 156 | }) 157 | 158 | it("rebase", async () => { 159 | await tokenContract.setAutoRebase(true) 160 | console.log('user1 balance', await tokenBalance(user1)) 161 | await advanceTimeAndBlock(86400) 162 | await tokenContract.transfer(user3, '100000', {from: user2}) 163 | console.log('user1 balance', await tokenBalance(user1)) 164 | }) 165 | }) 166 | -------------------------------------------------------------------------------- /smartcontracts/contracts/DividendDistributor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.16; 4 | 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | import "@openzeppelin/contracts/utils/math/SafeMath.sol"; 7 | import "./interface.sol"; 8 | 9 | contract DividendDistributor is IDividendDistributor, Ownable 10 | { 11 | using SafeMath for uint256; 12 | 13 | address public tokenAddress; 14 | 15 | struct Share { 16 | uint256 amount; 17 | uint256 totalExcluded;// excluded dividend 18 | uint256 totalRealised; 19 | } 20 | 21 | address[] shareholders; 22 | mapping (address => uint256) shareholderIndexes; 23 | mapping (address => uint256) shareholderClaims; 24 | 25 | mapping (address => Share) public shares; 26 | 27 | uint256 public totalShares; 28 | uint256 public totalDividends; 29 | uint256 public totalDistributed;// to be shown in UI 30 | uint256 public dividendsPerShare; 31 | uint256 public dividendsPerShareAccuracyFactor; 32 | 33 | uint256 public minPeriod = 1 hours; 34 | uint256 public minDistribution; 35 | 36 | address public DEAD = 0x000000000000000000000000000000000000dEaD; 37 | address public ZERO = 0x0000000000000000000000000000000000000000; 38 | 39 | uint256 currentIndex; 40 | 41 | mapping (address => bool) public isDividendExempt; 42 | mapping (address => bool) private isReentrant; 43 | 44 | constructor(address _token) { 45 | dividendsPerShareAccuracyFactor = 10 ** 36; 46 | minPeriod = 1 hours; 47 | minDistribution = 5 * (10 ** 16); 48 | 49 | isDividendExempt[address(this)] = true; 50 | isDividendExempt[DEAD] = true; 51 | isDividendExempt[ZERO] = true; 52 | 53 | tokenAddress = _token; 54 | } 55 | 56 | modifier onlyToken() { 57 | require(msg.sender == tokenAddress, "only token contract can set shares"); 58 | _; 59 | } 60 | 61 | function setTokenAddress(address _tokenAddress) external onlyOwner { 62 | require(_tokenAddress != address(0)); 63 | tokenAddress = _tokenAddress; 64 | } 65 | 66 | function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution) external override onlyOwner { 67 | minPeriod = _minPeriod; 68 | minDistribution = _minDistribution; 69 | } 70 | 71 | function setShare(address shareholder, uint256 amount) external override onlyToken { 72 | if (isDividendExempt[shareholder] == true) return; 73 | 74 | if(shares[shareholder].amount > 0){ 75 | distributeDividend(shareholder); 76 | } 77 | 78 | if(amount > 0 && shares[shareholder].amount == 0){ 79 | addShareholder(shareholder); 80 | }else if(amount == 0 && shares[shareholder].amount > 0){ 81 | removeShareholder(shareholder); 82 | } 83 | 84 | totalShares = totalShares.sub(shares[shareholder].amount).add(amount); 85 | shares[shareholder].amount = amount; 86 | shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount); 87 | } 88 | 89 | function deposit() external payable override onlyToken { 90 | uint256 amount = msg.value; 91 | 92 | totalDividends = totalDividends.add(amount); 93 | dividendsPerShare = dividendsPerShare.add(dividendsPerShareAccuracyFactor.mul(amount).div(totalShares)); 94 | } 95 | 96 | function process(uint256 gas) external override onlyToken { 97 | uint256 shareholderCount = shareholders.length; 98 | 99 | if(shareholderCount == 0) { return; } 100 | 101 | uint256 gasUsed = 0; 102 | uint256 gasLeft = gasleft(); 103 | 104 | uint256 iterations = 0; 105 | 106 | while(gasUsed < gas && iterations < shareholderCount) { 107 | if(currentIndex >= shareholderCount){ 108 | currentIndex = 0; 109 | } 110 | 111 | if(shouldDistribute(shareholders[currentIndex])){ 112 | distributeDividend(shareholders[currentIndex]); 113 | } 114 | 115 | gasUsed = gasUsed.add(gasLeft.sub(gasleft())); 116 | gasLeft = gasleft(); 117 | currentIndex ++; 118 | iterations ++; 119 | } 120 | } 121 | 122 | function shouldDistribute(address shareholder) internal view returns (bool) { 123 | return shareholderClaims[shareholder] + minPeriod < block.timestamp 124 | && getUnpaidEarnings(shareholder) > minDistribution; 125 | } 126 | 127 | function distributeDividend(address shareholder) internal { 128 | if (isReentrant[shareholder] == true) { return; } 129 | 130 | if(shares[shareholder].amount == 0){ return; } 131 | 132 | isReentrant[shareholder] = true; 133 | 134 | uint256 amount = getUnpaidEarnings(shareholder); 135 | if(amount > 0){ 136 | shareholderClaims[shareholder] = block.timestamp; 137 | shares[shareholder].totalRealised = shares[shareholder].totalRealised.add(amount); 138 | shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount); 139 | 140 | totalDistributed = totalDistributed.add(amount); 141 | 142 | (bool success, ) = payable(shareholder).call{ 143 | value: amount, 144 | gas: 30000 145 | }(""); 146 | 147 | require(success == true, "reward to the holder failed"); 148 | } 149 | 150 | isReentrant[shareholder] = false; 151 | } 152 | 153 | function claimDividend() external { 154 | distributeDividend(msg.sender); 155 | } 156 | 157 | function getUnpaidEarnings(address shareholder) public view returns (uint256) { 158 | if(shares[shareholder].amount == 0){ return 0; } 159 | 160 | uint256 shareholderTotalDividends = getCumulativeDividends(shares[shareholder].amount); 161 | uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded; 162 | 163 | if(shareholderTotalDividends <= shareholderTotalExcluded){ return 0; } 164 | 165 | return shareholderTotalDividends.sub(shareholderTotalExcluded); 166 | } 167 | 168 | function getCumulativeDividends(uint256 share) internal view returns (uint256) { 169 | return share.mul(dividendsPerShare).div(dividendsPerShareAccuracyFactor); 170 | } 171 | 172 | function addShareholder(address shareholder) internal { 173 | shareholderIndexes[shareholder] = shareholders.length; 174 | shareholders.push(shareholder); 175 | } 176 | 177 | function removeShareholder(address shareholder) internal { 178 | if (shareholders.length > 0 && shareholders[shareholderIndexes[shareholder]] == shareholder) { 179 | shareholders[shareholderIndexes[shareholder]] = shareholders[shareholders.length-1]; 180 | shareholderIndexes[shareholders[shareholders.length-1]] = shareholderIndexes[shareholder]; 181 | shareholders.pop(); 182 | } 183 | } 184 | 185 | function _setExempt(address _addr, bool _set) internal { 186 | isDividendExempt[_addr] = _set; 187 | 188 | if (_set == true) { 189 | address shareholder = _addr; 190 | uint256 remainingUnpaid = getUnpaidEarnings(shareholder); 191 | 192 | if (remainingUnpaid > 0) { 193 | (bool success, ) = payable(_msgSender()).call{ 194 | value: remainingUnpaid, 195 | gas: 30000 196 | }(""); 197 | require(success == true, "fee exempt pay error"); 198 | } 199 | 200 | removeShareholder(shareholder); 201 | 202 | totalShares = totalShares.sub(shares[shareholder].amount); 203 | shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount); 204 | shares[shareholder].amount = 0; 205 | } 206 | } 207 | 208 | function setExempt(address[] calldata wallets, bool set) external payable onlyOwner { 209 | require(wallets.length > 0, "Invalid Parameters"); 210 | uint256 i; 211 | for (i = 0; i < wallets.length; i ++) { 212 | _setExempt(wallets[i], set); 213 | } 214 | } 215 | 216 | function getRemainingTimeToBeRewarded(address shareHolder) external view returns (int256) { 217 | return int256(block.timestamp) - int256(shareholderClaims[shareHolder]); 218 | } 219 | 220 | function recoverETH(address to, uint256 amount) external payable onlyOwner { 221 | uint256 balance = address(this).balance; 222 | if (amount == 0) amount = balance; 223 | 224 | require(amount > 0, "No ETH to recover"); 225 | 226 | (bool success,) = payable(to).call{value: amount}(""); 227 | require(success, "Not Recovered ETH"); 228 | } 229 | 230 | function recoverToken(address token, address to, uint256 amount) external onlyOwner { 231 | uint256 balance = IERC20(token).balanceOf(address(this)); 232 | if (amount == 0) amount = balance; 233 | require(amount > 0, "No token to recover"); 234 | 235 | IERC20(token).transfer(to, amount); 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /dapp/src/contexts/WalletContext/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | // import { isMobile } from 'react-device-detect' 3 | 4 | import { createContext, useContext, useState, useEffect, useCallback, useMemo } from "react"; 5 | import Web3 from 'web3' 6 | 7 | import walletConfig from './config'; 8 | import { useGlobal } from '../GlobalContext'; 9 | 10 | export const WalletContext = createContext(); 11 | 12 | const Web3Modal = window.Web3Modal?.default; 13 | const WalletConnectProvider = window.WalletConnectProvider?.default; 14 | // const EvmChains = window.EvmChains; 15 | // const Fortmatic = window.Fortmatic; 16 | 17 | export const WalletProvider = (props) => { 18 | const { chainId } = useGlobal() 19 | 20 | const [wallet, setWallet] = useState({ 21 | address: '', 22 | chainId: 0 23 | }); 24 | 25 | const configuredChainId = useMemo(() => parseInt(walletConfig[chainId].chainId, 16), [chainId]) 26 | 27 | const initWeb3 = useCallback(() => { 28 | let web3Modal 29 | 30 | if (Web3Modal) { 31 | const providerOptions = { 32 | walletconnect: { 33 | package: WalletConnectProvider, 34 | options: { 35 | // infuraId: "8043bb2cf99347b1bfadfb233c5325c0", 36 | rpc: { 37 | [configuredChainId]: walletConfig[chainId].rpcUrls[0] 38 | }, 39 | // network: walletConfig.network, 40 | bridge: "https://bridge.walletconnect.org", 41 | pollingInterval: 12000 42 | }, 43 | }, 44 | // fortmatic: { 45 | // package: Fortmatic, 46 | // options: { 47 | // // Mikko's TESTNET api key 48 | // key: "pk_test_391E26A3B43A3350" 49 | // } 50 | // } 51 | }; 52 | 53 | web3Modal = new Web3Modal({ 54 | theme: "light", //"light", "dark" 55 | // network: walletConfig.network, 56 | cacheProvider: true, // optional 57 | providerOptions, // required 58 | disableInjectedProvider: false, // optional. For MetaMask / Brave / Opera. 59 | }); 60 | 61 | window.web3Modal = web3Modal 62 | } 63 | }, [chainId, configuredChainId]) 64 | 65 | const connectWalletChain = useCallback(async (chainId, chainName, nativeCurrency, rpcUrls, blockExplorerUrls) => { 66 | let ethereum = window.ethereum; 67 | if (ethereum === undefined) 68 | return; 69 | 70 | try { 71 | await ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: chainId }] }); 72 | } catch (switchError) { 73 | // This error code indicates that the chain has not been added to MetaMask. 74 | console.log("error switch chain: ", switchError); 75 | if (switchError.code === 4902) { 76 | const data = [{ 77 | // chainId: '0x38', 78 | chainId: chainId, 79 | // chainName: 'Binance Smart Chain', 80 | chainName: chainName, 81 | // nativeCurrency: 82 | // { 83 | // name: 'BNB', 84 | // symbol: 'BNB', 85 | // decimals: 18 86 | // }, 87 | nativeCurrency: nativeCurrency, 88 | // rpcUrls: ['https://bsc-dataseed.binance.org/'], 89 | rpcUrls: rpcUrls, 90 | // blockExplorerUrls: ['https://bscscan.com/'], 91 | blockExplorerUrls: blockExplorerUrls 92 | }] 93 | 94 | await ethereum.request({ method: 'wallet_addEthereumChain', params: data }) 95 | .then(() => { 96 | }) 97 | .catch((error) => { 98 | console.log('Failed to add network ', error) 99 | throw error 100 | }) 101 | } 102 | } 103 | }, []) 104 | 105 | const connectWalletByConfig = useCallback(async () => { 106 | return await connectWalletChain( 107 | walletConfig[chainId].chainId, 108 | walletConfig[chainId].networkName, 109 | walletConfig[chainId].nativeCurrency, 110 | walletConfig[chainId].rpcUrls, 111 | walletConfig[chainId].blockUrls 112 | ) 113 | }, [connectWalletChain, chainId]) 114 | 115 | const disconnectWallet = useCallback( async () => { 116 | if (window.web3Modal) { 117 | if (window.provider) // if connected state then disconnect 118 | { 119 | // show loading... 120 | if (window.provider.close) await window.provider.close(); 121 | await window.web3Modal.clearCachedProvider(); 122 | // hide loading 123 | // disconnected status 124 | console.log('disconnected from wallet'); 125 | } 126 | } 127 | window.web3 = undefined; 128 | window.provider = undefined; 129 | setWallet(t => { 130 | return { 131 | address: '', 132 | chainId: 0, 133 | } 134 | }) 135 | }, []) 136 | 137 | const connectWallet = useCallback(async (w) => { 138 | if (window.web3Modal === undefined) return 139 | 140 | let provider 141 | let account = '' 142 | 143 | try { // connect 144 | if (w === 'injected') { 145 | provider = await window.web3Modal.connectTo(w); 146 | } else if (w === 'walletconnect') { 147 | provider = await window.web3Modal.connectTo(w); 148 | } else { 149 | provider = await window.web3Modal.connect(); 150 | } 151 | // show loading... 152 | const web3 = new Web3(provider); 153 | account = (await web3.eth.getAccounts())[0]; 154 | const chainId = parseInt(await web3.eth.getChainId()); 155 | // hide loading 156 | window.provider = provider 157 | window.web3 = web3 158 | setWallet(t => { 159 | return { 160 | address: account, 161 | chainId: chainId 162 | } 163 | }) 164 | 165 | // Load chain information over an HTTP API 166 | // const chainData = await EvmChains.getChain(chainId); 167 | 168 | if (chainId !== configuredChainId) { 169 | await connectWalletByConfig() 170 | } 171 | 172 | // connected status 173 | console.log('connected to', account, web3); 174 | } catch (e) { 175 | // hide loading 176 | console.log("Could not get a wallet connection", e); 177 | return; 178 | } 179 | 180 | // Subscribe to accounts change 181 | provider.on("accountsChanged", async (accounts) => { 182 | // account changed 183 | if (accounts.length > 0) { 184 | setWallet(t => { 185 | return { 186 | ...t, 187 | address: accounts[0] 188 | } 189 | }) 190 | } else { 191 | await disconnectWallet() 192 | } 193 | console.log("account ->", accounts) 194 | }); 195 | 196 | // Subscribe to chainId change 197 | provider.on("chainChanged", (chainId) => { 198 | console.log("chainChanged -> ", chainId); 199 | }); 200 | 201 | // Subscribe to networkId change 202 | provider.on("networkChanged", (networkId) => { 203 | setWallet(t => { 204 | return { 205 | ...t, 206 | chainId: parseInt(networkId) 207 | } 208 | }) 209 | console.log("networkChanged -> ", networkId); 210 | }); 211 | 212 | return account 213 | }, [disconnectWallet, connectWalletByConfig, configuredChainId]) 214 | 215 | const reconnectWallet = async () => { 216 | if (window.web3Modal?.cachedProvider) { 217 | connectWallet() 218 | } 219 | } 220 | 221 | useEffect(() => { 222 | initWeb3() 223 | reconnectWallet() 224 | }, [initWeb3]) 225 | 226 | const isLoggedIn = useCallback(() => { 227 | return window.web3 !== undefined && wallet.chainId === configuredChainId 228 | }, [wallet.chainId, configuredChainId]) 229 | 230 | const isWrongChain = useCallback(() => { 231 | return wallet.address && wallet.chainId !== configuredChainId 232 | }, [wallet.chainId, wallet.address, configuredChainId]) 233 | 234 | return ( 235 | 236 | {props.children} 237 | 238 | ) 239 | } 240 | 241 | export const useCustomWallet = () => { 242 | const dataManager = useContext(WalletContext) 243 | return dataManager || [{}, async () => { }] 244 | } 245 | -------------------------------------------------------------------------------- /dapp/src/contexts/ContractContext/abi/DividendDistributor.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "DividendDistributor", 3 | "abi": [ 4 | { 5 | "inputs": [ 6 | { 7 | "internalType": "address", 8 | "name": "_token", 9 | "type": "address" 10 | } 11 | ], 12 | "stateMutability": "nonpayable", 13 | "type": "constructor" 14 | }, 15 | { 16 | "anonymous": false, 17 | "inputs": [ 18 | { 19 | "indexed": true, 20 | "internalType": "address", 21 | "name": "previousOwner", 22 | "type": "address" 23 | }, 24 | { 25 | "indexed": true, 26 | "internalType": "address", 27 | "name": "newOwner", 28 | "type": "address" 29 | } 30 | ], 31 | "name": "OwnershipTransferred", 32 | "type": "event" 33 | }, 34 | { 35 | "inputs": [], 36 | "name": "DEAD", 37 | "outputs": [ 38 | { 39 | "internalType": "address", 40 | "name": "", 41 | "type": "address" 42 | } 43 | ], 44 | "stateMutability": "view", 45 | "type": "function" 46 | }, 47 | { 48 | "inputs": [], 49 | "name": "ZERO", 50 | "outputs": [ 51 | { 52 | "internalType": "address", 53 | "name": "", 54 | "type": "address" 55 | } 56 | ], 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "inputs": [], 62 | "name": "dividendsPerShare", 63 | "outputs": [ 64 | { 65 | "internalType": "uint256", 66 | "name": "", 67 | "type": "uint256" 68 | } 69 | ], 70 | "stateMutability": "view", 71 | "type": "function" 72 | }, 73 | { 74 | "inputs": [], 75 | "name": "dividendsPerShareAccuracyFactor", 76 | "outputs": [ 77 | { 78 | "internalType": "uint256", 79 | "name": "", 80 | "type": "uint256" 81 | } 82 | ], 83 | "stateMutability": "view", 84 | "type": "function" 85 | }, 86 | { 87 | "inputs": [ 88 | { 89 | "internalType": "address", 90 | "name": "", 91 | "type": "address" 92 | } 93 | ], 94 | "name": "isDividendExempt", 95 | "outputs": [ 96 | { 97 | "internalType": "bool", 98 | "name": "", 99 | "type": "bool" 100 | } 101 | ], 102 | "stateMutability": "view", 103 | "type": "function" 104 | }, 105 | { 106 | "inputs": [], 107 | "name": "minDistribution", 108 | "outputs": [ 109 | { 110 | "internalType": "uint256", 111 | "name": "", 112 | "type": "uint256" 113 | } 114 | ], 115 | "stateMutability": "view", 116 | "type": "function" 117 | }, 118 | { 119 | "inputs": [], 120 | "name": "minPeriod", 121 | "outputs": [ 122 | { 123 | "internalType": "uint256", 124 | "name": "", 125 | "type": "uint256" 126 | } 127 | ], 128 | "stateMutability": "view", 129 | "type": "function" 130 | }, 131 | { 132 | "inputs": [], 133 | "name": "owner", 134 | "outputs": [ 135 | { 136 | "internalType": "address", 137 | "name": "", 138 | "type": "address" 139 | } 140 | ], 141 | "stateMutability": "view", 142 | "type": "function" 143 | }, 144 | { 145 | "inputs": [], 146 | "name": "renounceOwnership", 147 | "outputs": [], 148 | "stateMutability": "nonpayable", 149 | "type": "function" 150 | }, 151 | { 152 | "inputs": [ 153 | { 154 | "internalType": "address", 155 | "name": "", 156 | "type": "address" 157 | } 158 | ], 159 | "name": "shares", 160 | "outputs": [ 161 | { 162 | "internalType": "uint256", 163 | "name": "amount", 164 | "type": "uint256" 165 | }, 166 | { 167 | "internalType": "uint256", 168 | "name": "totalExcluded", 169 | "type": "uint256" 170 | }, 171 | { 172 | "internalType": "uint256", 173 | "name": "totalRealised", 174 | "type": "uint256" 175 | } 176 | ], 177 | "stateMutability": "view", 178 | "type": "function" 179 | }, 180 | { 181 | "inputs": [], 182 | "name": "tokenAddress", 183 | "outputs": [ 184 | { 185 | "internalType": "address", 186 | "name": "", 187 | "type": "address" 188 | } 189 | ], 190 | "stateMutability": "view", 191 | "type": "function" 192 | }, 193 | { 194 | "inputs": [], 195 | "name": "totalDistributed", 196 | "outputs": [ 197 | { 198 | "internalType": "uint256", 199 | "name": "", 200 | "type": "uint256" 201 | } 202 | ], 203 | "stateMutability": "view", 204 | "type": "function" 205 | }, 206 | { 207 | "inputs": [], 208 | "name": "totalDividends", 209 | "outputs": [ 210 | { 211 | "internalType": "uint256", 212 | "name": "", 213 | "type": "uint256" 214 | } 215 | ], 216 | "stateMutability": "view", 217 | "type": "function" 218 | }, 219 | { 220 | "inputs": [], 221 | "name": "totalShares", 222 | "outputs": [ 223 | { 224 | "internalType": "uint256", 225 | "name": "", 226 | "type": "uint256" 227 | } 228 | ], 229 | "stateMutability": "view", 230 | "type": "function" 231 | }, 232 | { 233 | "inputs": [ 234 | { 235 | "internalType": "address", 236 | "name": "newOwner", 237 | "type": "address" 238 | } 239 | ], 240 | "name": "transferOwnership", 241 | "outputs": [], 242 | "stateMutability": "nonpayable", 243 | "type": "function" 244 | }, 245 | { 246 | "inputs": [ 247 | { 248 | "internalType": "address", 249 | "name": "_tokenAddress", 250 | "type": "address" 251 | } 252 | ], 253 | "name": "setTokenAddress", 254 | "outputs": [], 255 | "stateMutability": "nonpayable", 256 | "type": "function" 257 | }, 258 | { 259 | "inputs": [ 260 | { 261 | "internalType": "uint256", 262 | "name": "_minPeriod", 263 | "type": "uint256" 264 | }, 265 | { 266 | "internalType": "uint256", 267 | "name": "_minDistribution", 268 | "type": "uint256" 269 | } 270 | ], 271 | "name": "setDistributionCriteria", 272 | "outputs": [], 273 | "stateMutability": "nonpayable", 274 | "type": "function" 275 | }, 276 | { 277 | "inputs": [ 278 | { 279 | "internalType": "address", 280 | "name": "shareholder", 281 | "type": "address" 282 | }, 283 | { 284 | "internalType": "uint256", 285 | "name": "amount", 286 | "type": "uint256" 287 | } 288 | ], 289 | "name": "setShare", 290 | "outputs": [], 291 | "stateMutability": "nonpayable", 292 | "type": "function" 293 | }, 294 | { 295 | "inputs": [], 296 | "name": "deposit", 297 | "outputs": [], 298 | "stateMutability": "payable", 299 | "type": "function" 300 | }, 301 | { 302 | "inputs": [ 303 | { 304 | "internalType": "uint256", 305 | "name": "gas", 306 | "type": "uint256" 307 | } 308 | ], 309 | "name": "process", 310 | "outputs": [], 311 | "stateMutability": "nonpayable", 312 | "type": "function" 313 | }, 314 | { 315 | "inputs": [], 316 | "name": "claimDividend", 317 | "outputs": [], 318 | "stateMutability": "nonpayable", 319 | "type": "function" 320 | }, 321 | { 322 | "inputs": [ 323 | { 324 | "internalType": "address", 325 | "name": "shareholder", 326 | "type": "address" 327 | } 328 | ], 329 | "name": "getUnpaidEarnings", 330 | "outputs": [ 331 | { 332 | "internalType": "uint256", 333 | "name": "", 334 | "type": "uint256" 335 | } 336 | ], 337 | "stateMutability": "view", 338 | "type": "function" 339 | }, 340 | { 341 | "inputs": [ 342 | { 343 | "internalType": "address", 344 | "name": "_addr", 345 | "type": "address" 346 | }, 347 | { 348 | "internalType": "bool", 349 | "name": "_set", 350 | "type": "bool" 351 | } 352 | ], 353 | "name": "setExempt", 354 | "outputs": [], 355 | "stateMutability": "payable", 356 | "type": "function" 357 | }, 358 | { 359 | "inputs": [ 360 | { 361 | "internalType": "address", 362 | "name": "shareHolder", 363 | "type": "address" 364 | } 365 | ], 366 | "name": "getRemainingTimeToBeRewarded", 367 | "outputs": [ 368 | { 369 | "internalType": "int256", 370 | "name": "", 371 | "type": "int256" 372 | } 373 | ], 374 | "stateMutability": "view", 375 | "type": "function" 376 | } 377 | ] 378 | } -------------------------------------------------------------------------------- /dapp/src/components/Swap/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useCallback } from 'react' 2 | 3 | import { 4 | SwapContainer 5 | } from './styles' 6 | 7 | import { useContract } from '../../contexts/ContractContext' 8 | import { useCustomWallet } from '../../contexts/WalletContext' 9 | import useToast from '../../hooks/useToast' 10 | import { SmallButton } from '../SmallButton' 11 | 12 | import TokenPNG from '../../assets/images/mark.png' 13 | import ETHPng from '../../assets/images/eth.png' 14 | import SwapPng from '../../assets/images/swap.png' 15 | 16 | export const Swap = (props) => { 17 | 18 | const { wallet } = useCustomWallet() 19 | const { showLoading, hideLoading, toastSuccess, toastError } = useToast(); 20 | 21 | const { reloadCounter, tokenPriceToUSDC, balanceOf, metisPriceToUSDC, wethBalanceOf, 22 | getTokenApprovedAmount, refreshPages, approveToken, sellToken, buyToken } = useContract() 23 | 24 | const [myBalance, setMyBalance] = useState(0) 25 | const [myETHBalance, setMyETHBalance] = useState(0) 26 | 27 | const [metisPrice, setMetisPrice] = useState(0) 28 | const [tokenPrice, setTokenPrice] = useState(0) 29 | 30 | const [tokenApprovedAmount, setTokenApprovedAmount] = useState(0) 31 | const [showApprove, setShowApprove] = useState(0) 32 | 33 | const [info, setInfo] = useState('Please input the amount') 34 | const [txRes, setTxRes] = useState('') 35 | 36 | const [isSelling, setIsSelling] = useState(true) 37 | const [tokenAmount, setTokenAmount] = useState('') 38 | const [metisAmount, setMetisAmount] = useState('') 39 | 40 | useEffect(() => { 41 | let ac = new AbortController(); 42 | 43 | tokenPriceToUSDC(1) 44 | .then(r => { 45 | if (ac.signal.aborted === false) { 46 | setTokenPrice(r) 47 | } 48 | }) 49 | .catch(err => { 50 | console.log(`${err.message}`) 51 | }) 52 | 53 | balanceOf(wallet.address) 54 | .then(r => { 55 | if (ac.signal.aborted === false) { 56 | setMyBalance(r); 57 | } 58 | }) 59 | .catch(err => { 60 | console.log(`${err.message}`) 61 | }) 62 | 63 | wethBalanceOf(wallet.address) 64 | .then(r => { 65 | if (ac.signal.aborted === false) { 66 | setMyETHBalance(r); 67 | } 68 | }) 69 | .catch(err => { 70 | console.log(`${err.message}`) 71 | }) 72 | 73 | metisPriceToUSDC(1) 74 | .then(r => { 75 | if (ac.signal.aborted === false) { 76 | setMetisPrice(r) 77 | } 78 | }) 79 | .catch(err => { 80 | console.log(`${err.message}`) 81 | }) 82 | 83 | getTokenApprovedAmount() 84 | .then(r => { 85 | if (ac.signal.aborted === false) { 86 | setTokenApprovedAmount(r) 87 | } 88 | }) 89 | .catch(err => { 90 | console.log(`${err.message}`) 91 | }) 92 | 93 | return () => ac.abort(); 94 | }, [reloadCounter, tokenPriceToUSDC, balanceOf, wethBalanceOf, metisPriceToUSDC, getTokenApprovedAmount, wallet.address]) 95 | 96 | useEffect(() => { 97 | setShowApprove(isSelling === true && myBalance > tokenApprovedAmount); 98 | }, [isSelling, myBalance, tokenApprovedAmount]) 99 | 100 | const handleTokenInput = useCallback((t) => { 101 | setTokenAmount(t); 102 | if (metisPrice === 0) return; 103 | 104 | let am = parseFloat(t); 105 | let um = am * tokenPrice / metisPrice; 106 | 107 | if (t === '') { 108 | setMetisAmount(''); 109 | } else { 110 | setMetisAmount(um.toString()); 111 | } 112 | 113 | if (isNaN(am)) { 114 | setInfo('Invalid ARES token amount'); 115 | } else if ((isSelling === true && am > myBalance) || (isSelling !== true && um > myETHBalance)) { 116 | setInfo('Insufficient balance'); 117 | } else { 118 | setInfo(''); 119 | } 120 | }, [tokenPrice, metisPrice, isSelling, myBalance, myETHBalance]) 121 | 122 | const handleMetisInput = useCallback((t) => { 123 | setMetisAmount(t); 124 | if (tokenPrice === 0) return; 125 | 126 | let am = parseFloat(t); 127 | let um = am * metisPrice / tokenPrice; 128 | 129 | if (t === '') { 130 | setTokenAmount(''); 131 | } else { 132 | setTokenAmount(um.toString()); 133 | } 134 | 135 | if (isNaN(am)) { 136 | setInfo('Invalid METIS amount'); 137 | } else if ((isSelling !== true && am > myETHBalance) || (isSelling === true && um > myBalance)) { 138 | setInfo('Insufficient balance'); 139 | } else { 140 | setInfo(''); 141 | } 142 | }, [tokenPrice, metisPrice, isSelling, myBalance, myETHBalance]) 143 | 144 | const handleMyBalance = useCallback(() => { 145 | if (isSelling) { 146 | handleTokenInput(myBalance.toString()); 147 | } else { 148 | handleMetisInput(myETHBalance.toString()); 149 | } 150 | }, [myBalance, myETHBalance, isSelling, handleTokenInput, handleMetisInput]) 151 | 152 | const handleApproveToken = useCallback(() => { 153 | showLoading(`Approving ARES for Tethys: Router...`); 154 | 155 | approveToken() 156 | .then(r => { 157 | setTxRes(r.transactionHash); 158 | refreshPages(); 159 | toastSuccess('ARES SWAP', 'Approved Successfully'); 160 | hideLoading(); 161 | }) 162 | .catch(err => { 163 | toastError('ARES SWAP', `${err.message}`); 164 | hideLoading(); 165 | }) 166 | }, [showLoading, approveToken, refreshPages, toastSuccess, hideLoading, toastError]) 167 | 168 | const handleSellToken = useCallback(() => { 169 | if (info !== '') { 170 | toastError('Please fix this error first', info); 171 | return; 172 | } 173 | 174 | showLoading(`Selling ${tokenAmount} ARES token...`); 175 | 176 | sellToken(tokenAmount) 177 | .then(r => { 178 | setTxRes(r.transactionHash); 179 | refreshPages(); 180 | toastSuccess('ARES SWAP', 'Sold successfully'); 181 | hideLoading(); 182 | }) 183 | .catch(err => { 184 | toastError('ARES SWAP', `${err.message}`); 185 | hideLoading(); 186 | }) 187 | }, [toastError, showLoading, tokenAmount, sellToken, refreshPages, toastSuccess, hideLoading, info]) 188 | 189 | const handleBuyToken = useCallback(() => { 190 | if (info !== '') { 191 | toastError('Please fix this error first', info); 192 | return; 193 | } 194 | 195 | showLoading(`Buying ARES token by ${metisAmount} METIS...`); 196 | 197 | buyToken(metisAmount) 198 | .then(r => { 199 | setTxRes(r.transactionHash); 200 | refreshPages(); 201 | toastSuccess('ARES SWAP', 'Bought successfully'); 202 | hideLoading(); 203 | }) 204 | .catch(err => { 205 | toastError('ARES SWAP', `${err.message}`); 206 | hideLoading(); 207 | }) 208 | }, [info, showLoading, metisAmount, buyToken, refreshPages, toastSuccess, hideLoading, toastError]) 209 | 210 | return ( 211 | 212 |
213 |
214 |
Buy / Sell ARES
215 |
216 |
217 |
222 |
{isSelling ? `My ARES balance ${myBalance}` : `My METIS balance ${myETHBalance}`}
223 |
224 |
225 | 226 |

ARES

227 |
228 |
229 | 10000000000000? 'approved: unlimited': `approved ${tokenApprovedAmount} ARES`} value={tokenAmount} onChange={e => handleTokenInput(e.target.value)} /> 230 |
231 |
232 | 233 |
234 |
{ setIsSelling(t => !t) }}> 235 | 236 |
237 |
238 | 239 |
240 |
241 | 242 |

METIS

243 |
244 |
245 | handleMetisInput(e.target.value)} /> 246 |
247 |
248 |
249 | 250 |
251 |
252 | {showApprove === true && } 253 | isSelling === true? handleSellToken() : handleBuyToken()} /> 254 |
255 |
256 |
257 |
258 |
{info}
259 |
260 | {txRes &&
261 |
262 | Your transaction hash: {txRes.slice(0, 8)}...{txRes.slice(-6)} 263 |
264 |
} 265 |
266 |
267 | ) 268 | } 269 | -------------------------------------------------------------------------------- /smartcontracts/scripts/run.js: -------------------------------------------------------------------------------- 1 | const Web3 = require('web3') 2 | const fs = require('fs') 3 | const BN = require('bignumber.js') 4 | const pvkey = fs.readFileSync('.secret').toString().trim(); 5 | 6 | const PBUSD = require('../build/contracts/PBUSD.json') 7 | const PriceStabilizerUpgradeable = require('../build/contracts/PriceStabilizerUpgradeable.json') 8 | const FeeDistributorUpgradeable = require('../build/contracts/FeeDistributorUpgradeable.json') 9 | const StarLinkSatellite = require('../build/contracts/StarLinkSatellite.json') 10 | const StarLinkSatelliteNodeManager = require('../build/contracts/StarLinkSatelliteNodeManager.json') 11 | const vStarLinkSatellite = require('../build/contracts/vStarLinkSatellite.json') 12 | const StarLinkSatellitePresale = require('../build/contracts/StarLinkSatellitePresale.json') 13 | const PancakeRouter = require('../build/contracts/PancakeRouter.json') 14 | const PancakePair = require('../build/contracts/PancakePair.json') 15 | const PancakeFactory = require('../build/contracts/PancakeFactory.json') 16 | 17 | let web3; // = new Web3(chainData.rpcUrls[0]); 18 | let deployParams; 19 | let chainIdNumber; 20 | let jsonPath; 21 | let network = ''; 22 | let runMode = ''; 23 | 24 | const getContract = async (abi, address) => { 25 | return await new web3.eth.Contract(abi, address); 26 | } 27 | 28 | const queryContract = async (tx) => { 29 | return await tx.call() 30 | } 31 | 32 | const executeContract1 = async (contractAddress, tx) => { 33 | // const networkId = await web3.eth.net.getId(); 34 | // { 35 | // address: '0x8f4DF07B38E5203eb81Ab4C523DeEAb0AC1f2749', 36 | // privateKey: '0x76d7....c21d', 37 | // signTransaction: [Function: signTransaction], 38 | // sign: [Function: sign], 39 | // encrypt: [Function: encrypt] 40 | // } 41 | const address = await web3.eth.accounts.privateKeyToAccount(pvkey).address; 42 | const gas = await tx.estimateGas({from: address}); 43 | const gasPrice = await web3.eth.getGasPrice(); 44 | const data = tx.encodeABI(); 45 | const nonce = await web3.eth.getTransactionCount(address); 46 | 47 | const signedTx = await web3.eth.accounts.signTransaction( 48 | { 49 | to: contractAddress, 50 | data, 51 | gas, 52 | gasPrice, 53 | nonce, 54 | chainId: chainIdNumber 55 | }, 56 | pvkey 57 | ); 58 | const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); 59 | // console.log(`Transaction hash: ${receipt.transactionHash}`); 60 | return receipt; 61 | } 62 | 63 | const executeContract2 = async (contractAddress, tx) => { 64 | // const networkId = await web3.eth.net.getId(); 65 | await web3.eth.accounts.wallet.add(pvkey); 66 | 67 | const address = await web3.eth.accounts.privateKeyToAccount(pvkey).address; 68 | const gas = await tx.estimateGas({from: address}); 69 | const gasPrice = await web3.eth.getGasPrice(); 70 | const data = tx.encodeABI(); 71 | const nonce = await web3.eth.getTransactionCount(address); 72 | const txData = { 73 | from: address, 74 | to: contractAddress, 75 | data: data, 76 | gas, 77 | gasPrice, 78 | nonce, 79 | chainId: chainIdNumber 80 | }; 81 | 82 | const receipt = await web3.eth.sendTransaction(txData); 83 | // console.log(`Transaction hash: ${receipt.transactionHash}`); 84 | return receipt; 85 | } 86 | 87 | const executeContract = async (contractAddress, tx) => { 88 | try { 89 | return await executeContract1(contractAddress, tx); 90 | } catch (err) { 91 | console.log(err.message) 92 | } 93 | } 94 | 95 | const parseArguments = async () => { 96 | let i 97 | let args = process.argv 98 | 99 | for (i = 0; i < args.length; i ++) { 100 | if (args[i] === '--network') { 101 | if (i < args.length - 1) { 102 | network = args[i + 1] 103 | i ++ 104 | } 105 | } else if (args[i] === '--run') { 106 | if (i < args.length - 1) { 107 | runMode = args[i + 1] 108 | i ++ 109 | } 110 | } 111 | } 112 | 113 | const networkTable = { 114 | bscmainnet: { 115 | rpc: 'https://bsc-dataseed.binance.org/', 116 | privateKey: pvkey, 117 | chainId: 56, 118 | blockExplorer: 'https://bscscan.com/' 119 | }, 120 | bsctestnet: { 121 | rpc: 'https://data-seed-prebsc-2-s1.binance.org:8545/', 122 | privateKey: pvkey, 123 | chainId: 97, 124 | blockExplorer: 'https://testnet.bscscan.com/' 125 | } 126 | } 127 | 128 | let conf = networkTable[network] 129 | 130 | if (conf?.rpc) { 131 | web3 = new Web3(conf.rpc) 132 | await web3.eth.accounts.wallet.add(conf.privateKey) 133 | chainIdNumber = conf.chainId 134 | 135 | const address = await web3.eth.accounts.privateKeyToAccount(pvkey).address; 136 | console.log(`Loading web3 with ${conf.rpc}, adding address ${address}`) 137 | 138 | jsonPath = `../migrations/deploy-${network}.json` 139 | deployParams = require(jsonPath); 140 | } else { 141 | console.log('undefined network') 142 | console.log('#> node scripts/configure.js --network bsctestnet') 143 | process.exit(1) 144 | } 145 | } 146 | 147 | let syncDeployInfo = (_name, _info, _total) => { 148 | _total = [..._total.filter(t => t.name !== _name), _info]; 149 | fs.writeFileSync(`migrations/deploy-${network}.json`, JSON.stringify(_total)); 150 | return _total; 151 | } 152 | 153 | const configure = async () => { 154 | let pbusdInfo = deployParams.find(t => t.name === "PBUSD") 155 | let pricerInfo = deployParams.find(t => t.name === "PriceStabilizerUpgradeable") 156 | let busdDistInfo = deployParams.find(t => t.name === "FeeDistributorUpgradeable") 157 | let slsTokenInfo = deployParams.find(t => t.name === "StarLinkSatellite") 158 | let slsNodeManagerInfo = deployParams.find(t => t.name === "StarLinkSatelliteNodeManager") 159 | let vSlsTokenInfo = deployParams.find(t => t.name === "vStarLinkSatellite") 160 | let slsPresaleInfo = deployParams.find(t => t.name === "StarLinkSatellitePresale") 161 | let routerInfo = deployParams.find(t => t.name === "PancakeRouter") 162 | 163 | let pbusd = await getContract(PBUSD.abi, pbusdInfo.imple) 164 | let pricer = await getContract(PriceStabilizerUpgradeable.abi, pricerInfo.proxy) 165 | let busdDistributor = await getContract(FeeDistributorUpgradeable.abi, busdDistInfo.proxy) 166 | let slsToken = await getContract(StarLinkSatellite.abi, slsTokenInfo.proxy) 167 | let slsNodeManager = await getContract(StarLinkSatelliteNodeManager.abi, slsNodeManagerInfo.proxy) 168 | let vSlsToken = await getContract(vStarLinkSatellite.abi, vSlsTokenInfo.proxy) 169 | let slsPresale = await getContract(StarLinkSatellitePresale.abi, slsPresaleInfo.proxy) 170 | let router = await getContract(PancakeRouter.abi, routerInfo.imple) 171 | 172 | let factoryAddress = await router.methods.factory().call() 173 | let factory = await getContract(PancakeFactory.abi, factoryAddress) 174 | 175 | let pairAddress = await slsToken.methods.uniswapV2Pair().call() 176 | let pair = await getContract(PancakePair.abi, pairAddress) 177 | 178 | let feeRx1 = '0x4Ce5CD0718948701951eDBEe9ff2B1CA87cbeE7c' 179 | let feeRx2 = '0xd35045c3AFfEea18fd2F6AA0c3060D9108B1963a' 180 | 181 | let busdShare1 = 8000 182 | let busdShare2 = 2000 183 | 184 | let OneToken = BN('1e18') 185 | 186 | const initializeContracts = async () => { 187 | console.log('Initializing Price Stabilizer(Treasury)') 188 | await executeContract(pricer._address, pricer.methods.updateTargetToken(slsToken._address)) 189 | 190 | console.log('Initializing BUSD distributor') 191 | await executeContract(busdDistributor._address, busdDistributor.methods.updateFeeAddresses([feeRx1, feeRx2])) 192 | await executeContract(busdDistributor._address, busdDistributor.methods.updateFeeShares([busdShare1, busdShare2])) 193 | 194 | console.log('Initializing GSLS token') 195 | await executeContract(slsToken._address, slsToken.methods.updateBUSDDistributor(busdDistributor._address)) 196 | await executeContract(slsToken._address, slsToken.methods.setDistributionThreshold(BN("100").times(OneToken))) 197 | await executeContract(slsToken._address, slsToken.methods.setNodeManagerAddr(slsNodeManager._address)) 198 | 199 | console.log('Initializing GSLS Node Manager') 200 | await executeContract(slsNodeManager._address, slsNodeManager.methods.setPromoToken(vSlsToken._address)) 201 | await executeContract(slsNodeManager._address, slsNodeManager.methods.setTokenAddr(slsToken._address)) 202 | await executeContract(slsNodeManager._address, slsNodeManager.methods.setNodePriceOriginal(BN("10").times(OneToken))) 203 | await executeContract(slsNodeManager._address, slsNodeManager.methods.setNodePricePromotional(BN("10").times(OneToken))) 204 | 205 | console.log('Initializing vGSLS token') 206 | await executeContract(vSlsToken._address, vSlsToken.methods.enableMinter(slsPresale._address, true)); 207 | await executeContract(vSlsToken._address, vSlsToken.methods.enableBurner(slsNodeManager._address, true)); 208 | 209 | console.log('Initializing presale') 210 | await executeContract(slsPresale._address, slsPresale.methods.updateVTokenPrice(BN("12500000000"))); 211 | 212 | console.log('You should deposit some BUSD to price stabilizer(treasury) contract') 213 | 214 | let pair = { 215 | name: "PancakePair", 216 | imple: await queryContract(slsToken.methods.uniswapV2Pair()) 217 | } 218 | deployParams = syncDeployInfo("PancakePair", pair, deployParams) 219 | } 220 | 221 | await initializeContracts() 222 | 223 | console.log('Done!') 224 | } 225 | 226 | const stabilize = async () => { 227 | let pricerInfo = deployParams.find(t => t.name === "PriceStabilizerUpgradeable") 228 | let slsTokenInfo = deployParams.find(t => t.name === "StarLinkSatellite") 229 | 230 | let pricer = await getContract(PriceStabilizerUpgradeable.abi, pricerInfo.proxy) 231 | let slsToken = await getContract(StarLinkSatellite.abi, slsTokenInfo.proxy) 232 | 233 | const updateContracts = async () => { 234 | console.log('Setting price range') 235 | await executeContract(pricer._address, pricer.methods.updatePriceRange(26000000000, 24000000000)) 236 | await executeContract(slsToken._address, slsToken.methods.enablePriceStabilizing(true)) 237 | } 238 | 239 | await updateContracts() 240 | 241 | console.log('Done!') 242 | } 243 | 244 | const main = async () => { 245 | await parseArguments() 246 | 247 | if (runMode === 'configure') { 248 | await configure() 249 | } else if (runMode === 'stabilize') { 250 | await stabilize() 251 | } 252 | } 253 | 254 | main() -------------------------------------------------------------------------------- /smartcontracts/contracts/pancake/PancakePair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.16; 3 | 4 | import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; 5 | import './interfaces/IPancakePair.sol'; 6 | import './PancakeERC20.sol'; 7 | import './libraries/Math.sol'; 8 | import './libraries/UQ112x112.sol'; 9 | import './interfaces/IPancakeFactory.sol'; 10 | import './interfaces/IPancakeCallee.sol'; 11 | 12 | contract PancakePair is PancakeERC20 { 13 | using SafeMath for uint; 14 | using UQ112x112 for uint224; 15 | 16 | uint public constant MINIMUM_LIQUIDITY = 10**3; 17 | bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); 18 | 19 | address public factory; 20 | address public token0; 21 | address public token1; 22 | 23 | uint112 private reserve0; // uses single storage slot, accessible via getReserves 24 | uint112 private reserve1; // uses single storage slot, accessible via getReserves 25 | uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves 26 | 27 | uint public price0CumulativeLast; 28 | uint public price1CumulativeLast; 29 | uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event 30 | 31 | event Mint(address indexed sender, uint amount0, uint amount1); 32 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 33 | event Swap( 34 | address indexed sender, 35 | uint amount0In, 36 | uint amount1In, 37 | uint amount0Out, 38 | uint amount1Out, 39 | address indexed to 40 | ); 41 | event Sync(uint112 reserve0, uint112 reserve1); 42 | 43 | uint private unlocked = 1; 44 | modifier lock() { 45 | require(unlocked == 1, 'Pancake: LOCKED'); 46 | unlocked = 0; 47 | _; 48 | unlocked = 1; 49 | } 50 | 51 | function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { 52 | _reserve0 = reserve0; 53 | _reserve1 = reserve1; 54 | _blockTimestampLast = blockTimestampLast; 55 | } 56 | 57 | function _safeTransfer(address token, address to, uint value) private { 58 | // (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); 59 | // require(success && (data.length == 0 || abi.decode(data, (bool))), 'Pancake: TRANSFER_FAILED'); 60 | IERC20(token).transfer(to, value); 61 | } 62 | 63 | constructor() { 64 | factory = msg.sender; 65 | } 66 | 67 | // called once by the factory at time of deployment 68 | function initialize(address _token0, address _token1) external { 69 | require(msg.sender == factory, 'Pancake: FORBIDDEN'); // sufficient check 70 | token0 = _token0; 71 | token1 = _token1; 72 | } 73 | 74 | // update reserves and, on the first call per block, price accumulators 75 | function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { 76 | require(balance0 <= ~uint112(0) && balance1 <= ~uint112(0), 'Pancake: OVERFLOW'); 77 | uint32 blockTimestamp = uint32(block.timestamp % 2**32); 78 | uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired 79 | if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { 80 | // * never overflows, and + overflow is desired 81 | price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; 82 | price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; 83 | } 84 | reserve0 = uint112(balance0); 85 | reserve1 = uint112(balance1); 86 | blockTimestampLast = blockTimestamp; 87 | emit Sync(reserve0, reserve1); 88 | } 89 | 90 | // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) 91 | function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { 92 | address feeTo = IPancakeFactory(factory).feeTo(); 93 | feeOn = feeTo != address(0); 94 | uint _kLast = kLast; // gas savings 95 | if (feeOn) { 96 | if (_kLast != 0) { 97 | uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); 98 | uint rootKLast = Math.sqrt(_kLast); 99 | if (rootK > rootKLast) { 100 | uint numerator = totalSupply.mul(rootK.sub(rootKLast)); 101 | uint denominator = rootK.mul(3).add(rootKLast); 102 | uint liquidity = numerator / denominator; 103 | if (liquidity > 0) _mint(feeTo, liquidity); 104 | } 105 | } 106 | } else if (_kLast != 0) { 107 | kLast = 0; 108 | } 109 | } 110 | 111 | // this low-level function should be called from a contract which performs important safety checks 112 | function mint(address to) external lock returns (uint liquidity) { 113 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 114 | uint balance0 = IERC20(token0).balanceOf(address(this)); 115 | uint balance1 = IERC20(token1).balanceOf(address(this)); 116 | uint amount0 = balance0.sub(_reserve0); 117 | uint amount1 = balance1.sub(_reserve1); 118 | 119 | bool feeOn = _mintFee(_reserve0, _reserve1); 120 | uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee 121 | if (_totalSupply == 0) { 122 | liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); 123 | _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens 124 | } else { 125 | liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1); 126 | } 127 | require(liquidity > 0, 'Pancake: INSUFFICIENT_LIQUIDITY_MINTED'); 128 | _mint(to, liquidity); 129 | 130 | _update(balance0, balance1, _reserve0, _reserve1); 131 | if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date 132 | emit Mint(msg.sender, amount0, amount1); 133 | } 134 | 135 | // this low-level function should be called from a contract which performs important safety checks 136 | function burn(address to) external lock returns (uint amount0, uint amount1) { 137 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 138 | address _token0 = token0; // gas savings 139 | address _token1 = token1; // gas savings 140 | uint balance0 = IERC20(_token0).balanceOf(address(this)); 141 | uint balance1 = IERC20(_token1).balanceOf(address(this)); 142 | uint liquidity = balanceOf[address(this)]; 143 | 144 | bool feeOn = _mintFee(_reserve0, _reserve1); 145 | uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee 146 | amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution 147 | amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution 148 | require(amount0 > 0 && amount1 > 0, 'Pancake: INSUFFICIENT_LIQUIDITY_BURNED'); 149 | _burn(address(this), liquidity); 150 | _safeTransfer(_token0, to, amount0); 151 | _safeTransfer(_token1, to, amount1); 152 | balance0 = IERC20(_token0).balanceOf(address(this)); 153 | balance1 = IERC20(_token1).balanceOf(address(this)); 154 | 155 | _update(balance0, balance1, _reserve0, _reserve1); 156 | if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date 157 | emit Burn(msg.sender, amount0, amount1, to); 158 | } 159 | 160 | // this low-level function should be called from a contract which performs important safety checks 161 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { 162 | require(amount0Out > 0 || amount1Out > 0, 'Pancake: INSUFFICIENT_OUTPUT_AMOUNT'); 163 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 164 | require(amount0Out < _reserve0 && amount1Out < _reserve1, 'Pancake: INSUFFICIENT_LIQUIDITY'); 165 | 166 | uint balance0; 167 | uint balance1; 168 | { // scope for _token{0,1}, avoids stack too deep errors 169 | address _token0 = token0; 170 | address _token1 = token1; 171 | require(to != _token0 && to != _token1, 'Pancake: INVALID_TO'); 172 | if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens 173 | if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens 174 | if (data.length > 0) IPancakeCallee(to).pancakeCall(msg.sender, amount0Out, amount1Out, data); 175 | balance0 = IERC20(_token0).balanceOf(address(this)); 176 | balance1 = IERC20(_token1).balanceOf(address(this)); 177 | } 178 | uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; 179 | uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; 180 | require(amount0In > 0 || amount1In > 0, 'Pancake: INSUFFICIENT_INPUT_AMOUNT'); 181 | { // scope for reserve{0,1}Adjusted, avoids stack too deep errors 182 | uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(2)); 183 | uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(2)); 184 | require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'Pancake: K'); 185 | } 186 | 187 | _update(balance0, balance1, _reserve0, _reserve1); 188 | emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); 189 | } 190 | 191 | // force balances to match reserves 192 | function skim(address to) external lock { 193 | address _token0 = token0; // gas savings 194 | address _token1 = token1; // gas savings 195 | _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0)); 196 | _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1)); 197 | } 198 | 199 | // force reserves to match balances 200 | function sync() external lock { 201 | _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /dapp/src/components/Home/StarryGalaxy.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | function run(container) { 4 | var num = 500; 5 | var w = window.innerWidth; 6 | var h = window.innerHeight; 7 | var max = 100; 8 | var _x = 0; 9 | var _y = 0; 10 | var _z = 40; 11 | var dtr = function (d) { 12 | return d * Math.PI / 180; 13 | }; 14 | 15 | var rnd = function () { 16 | return Math.sin(Math.floor(Math.random() * 360) * Math.PI / 180); 17 | }; 18 | var dist = function (p1, p2, p3) { 19 | return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2)); 20 | }; 21 | 22 | var cam = { 23 | obj: { x: _x, y: _y, z: _z }, 24 | dest: { x: 0, y: 0, z: 1 }, 25 | dist: { x: 0, y: 0, z: 200 }, 26 | ang: { cplane: 0, splane: 0, ctheta: 0, stheta: 0 }, 27 | zoom: 2, 28 | disp: { x: w / 2, y: h / 2, z: 0 }, 29 | upd: function () { 30 | cam.dist.x = cam.dest.x - cam.obj.x; 31 | cam.dist.y = cam.dest.y - cam.obj.y; 32 | cam.dist.z = cam.dest.z - cam.obj.z; 33 | cam.ang.cplane = -cam.dist.z / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.z * cam.dist.z); 34 | cam.ang.splane = cam.dist.x / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.z * cam.dist.z); 35 | cam.ang.ctheta = Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.z * cam.dist.z) / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.y * cam.dist.y + cam.dist.z * cam.dist.z); 36 | cam.ang.stheta = -cam.dist.y / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.y * cam.dist.y + cam.dist.z * cam.dist.z); 37 | } 38 | }; 39 | 40 | var trans = { 41 | parts: { 42 | sz: function (p, sz) { 43 | return { 44 | x: p.x * sz.x, 45 | y: p.y * sz.y, 46 | z: p.z * sz.z 47 | }; 48 | }, 49 | rot: { 50 | x: function (p, rot) { 51 | return { 52 | x: p.x, 53 | y: p.y * Math.cos(dtr(rot.x)) - p.z * Math.sin(dtr(rot.x)), 54 | z: p.y * Math.sin(dtr(rot.x)) + p.z * Math.cos(dtr(rot.x)) 55 | }; 56 | }, 57 | y: function (p, rot) { 58 | return { 59 | x: p.x * Math.cos(dtr(rot.y)) + p.z * Math.sin(dtr(rot.y)), 60 | y: p.y, 61 | z: -p.x * Math.sin(dtr(rot.y)) + p.z * Math.cos(dtr(rot.y)) 62 | }; 63 | }, 64 | z: function (p, rot) { 65 | return { 66 | x: p.x * Math.cos(dtr(rot.z)) - p.y * Math.sin(dtr(rot.z)), 67 | y: p.x * Math.sin(dtr(rot.z)) + p.y * Math.cos(dtr(rot.z)), 68 | z: p.z 69 | }; 70 | } 71 | }, 72 | pos: function (p, pos) { 73 | return { 74 | x: p.x + pos.x, 75 | y: p.y + pos.y, 76 | z: p.z + pos.z 77 | }; 78 | } 79 | }, 80 | pov: { 81 | plane: function (p) { 82 | return { 83 | x: p.x * cam.ang.cplane + p.z * cam.ang.splane, 84 | y: p.y, 85 | z: p.x * -cam.ang.splane + p.z * cam.ang.cplane 86 | }; 87 | }, 88 | theta: function (p) { 89 | return { 90 | x: p.x, 91 | y: p.y * cam.ang.ctheta - p.z * cam.ang.stheta, 92 | z: p.y * cam.ang.stheta + p.z * cam.ang.ctheta 93 | }; 94 | }, 95 | set: function (p) { 96 | return { 97 | x: p.x - cam.obj.x, 98 | y: p.y - cam.obj.y, 99 | z: p.z - cam.obj.z 100 | }; 101 | } 102 | }, 103 | persp: function (p) { 104 | return { 105 | x: p.x * cam.dist.z / p.z * cam.zoom, 106 | y: p.y * cam.dist.z / p.z * cam.zoom, 107 | z: p.z * cam.zoom, 108 | p: cam.dist.z / p.z 109 | }; 110 | }, 111 | disp: function (p, disp) { 112 | return { 113 | x: p.x + disp.x, 114 | y: -p.y + disp.y, 115 | z: p.z + disp.z, 116 | p: p.p 117 | }; 118 | }, 119 | steps: function (_obj_, sz, rot, pos, disp) { 120 | var _args = trans.parts.sz(_obj_, sz); 121 | _args = trans.parts.rot.x(_args, rot); 122 | _args = trans.parts.rot.y(_args, rot); 123 | _args = trans.parts.rot.z(_args, rot); 124 | _args = trans.parts.pos(_args, pos); 125 | _args = trans.pov.plane(_args); 126 | _args = trans.pov.theta(_args); 127 | _args = trans.pov.set(_args); 128 | _args = trans.persp(_args); 129 | _args = trans.disp(_args, disp); 130 | return _args; 131 | } 132 | }; 133 | 134 | (function () { 135 | "use strict"; 136 | var threeD = function (param) { 137 | this.transIn = {}; 138 | this.transOut = {}; 139 | this.transIn.vtx = (param.vtx); 140 | this.transIn.sz = (param.sz); 141 | this.transIn.rot = (param.rot); 142 | this.transIn.pos = (param.pos); 143 | }; 144 | 145 | threeD.prototype.vupd = function () { 146 | this.transOut = trans.steps( 147 | this.transIn.vtx, 148 | this.transIn.sz, 149 | this.transIn.rot, 150 | this.transIn.pos, 151 | cam.disp 152 | ); 153 | }; 154 | 155 | var Build = function () { 156 | this.vel = 0.04; 157 | this.lim = 360; 158 | this.diff = 200; 159 | this.initPos = 100; 160 | this.toX = _x; 161 | this.toY = _y; 162 | this.go(); 163 | }; 164 | 165 | Build.prototype.go = function () { 166 | this.canvas = container 167 | this.canvas.width = window.innerWidth; 168 | this.canvas.height = window.innerHeight; 169 | this.$ = container.getContext("2d"); 170 | this.$.globalCompositeOperation = 'source-over'; 171 | this.varr = []; 172 | this.dist = []; 173 | this.calc = []; 174 | 175 | for (var i = 0, len = num; i < len; i++) { 176 | this.add(); 177 | } 178 | 179 | this.rotObj = { x: 0, y: 0, z: 0 }; 180 | this.objSz = { x: w / 5, y: h / 5, z: w / 5 }; 181 | }; 182 | 183 | Build.prototype.add = function () { 184 | this.varr.push(new threeD({ 185 | vtx: { x: rnd(), y: rnd(), z: rnd() }, 186 | sz: { x: 0, y: 0, z: 0 }, 187 | rot: { x: 20, y: -20, z: 0 }, 188 | pos: { 189 | x: this.diff * Math.sin(360 * Math.random() * Math.PI / 180), 190 | y: this.diff * Math.sin(360 * Math.random() * Math.PI / 180), 191 | z: this.diff * Math.sin(360 * Math.random() * Math.PI / 180) 192 | } 193 | })); 194 | this.calc.push({ 195 | x: 360 * Math.random(), 196 | y: 360 * Math.random(), 197 | z: 360 * Math.random() 198 | }); 199 | }; 200 | 201 | Build.prototype.upd = function () { 202 | cam.obj.x += (this.toX - cam.obj.x) * 0.05; 203 | cam.obj.y += (this.toY - cam.obj.y) * 0.05; 204 | }; 205 | 206 | Build.prototype.draw = function () { 207 | this.$.clearRect(0, 0, this.canvas.width, this.canvas.height); 208 | cam.upd(); 209 | this.rotObj.x += 0.1; 210 | this.rotObj.y += 0.1; 211 | this.rotObj.z += 0.1; 212 | 213 | for (var i = 0; i < this.varr.length; i++) { 214 | for (var val in this.calc[i]) { 215 | if (this.calc[i].hasOwnProperty(val)) { 216 | this.calc[i][val] += this.vel; 217 | if (this.calc[i][val] > this.lim) this.calc[i][val] = 0; 218 | } 219 | } 220 | 221 | this.varr[i].transIn.pos = { 222 | x: this.diff * Math.cos(this.calc[i].x * Math.PI / 180), 223 | y: this.diff * Math.sin(this.calc[i].y * Math.PI / 180), 224 | z: this.diff * Math.sin(this.calc[i].z * Math.PI / 180) 225 | }; 226 | this.varr[i].transIn.rot = this.rotObj; 227 | this.varr[i].transIn.sz = this.objSz; 228 | this.varr[i].vupd(); 229 | if (this.varr[i].transOut.p < 0) continue; 230 | var g = this.$.createRadialGradient(this.varr[i].transOut.x, this.varr[i].transOut.y, this.varr[i].transOut.p, this.varr[i].transOut.x, this.varr[i].transOut.y, this.varr[i].transOut.p * 2); 231 | this.$.globalCompositeOperation = 'lighter'; 232 | g.addColorStop(0, 'hsla(255, 255%, 255%, 1)'); 233 | g.addColorStop(.5, 'hsla(' + (i + 2) + ',85%, 40%,1)'); 234 | g.addColorStop(1, 'hsla(' + (i) + ',85%, 40%,.5)'); 235 | this.$.fillStyle = g; 236 | this.$.beginPath(); 237 | this.$.arc(this.varr[i].transOut.x, this.varr[i].transOut.y, this.varr[i].transOut.p * 2, 0, Math.PI * 2, false); 238 | this.$.fill(); 239 | this.$.closePath(); 240 | } 241 | }; 242 | Build.prototype.anim = function () { 243 | window.requestAnimationFrame = (function () { 244 | return window.requestAnimationFrame || 245 | function (callback, element) { 246 | window.setTimeout(callback, 1000 / 60); 247 | }; 248 | })(); 249 | var anim = function () { 250 | this.upd(); 251 | this.draw(); 252 | window.requestAnimationFrame(anim); 253 | }.bind(this); 254 | window.requestAnimationFrame(anim); 255 | }; 256 | 257 | Build.prototype.run = function () { 258 | this.anim(); 259 | 260 | window.addEventListener('mousemove', function (e) { 261 | // this.toX = (e.clientX - this.canvas.width / 2) * -0.8; 262 | // this.toY = (e.clientY - this.canvas.height / 2) * 0.8; 263 | }.bind(this)); 264 | window.addEventListener('touchmove', function (e) { 265 | // e.preventDefault(); 266 | // this.toX = (e.touches[0].clientX - this.canvas.width / 2) * -0.8; 267 | // this.toY = (e.touches[0].clientY - this.canvas.height / 2) * 0.8; 268 | }.bind(this)); 269 | // window.addEventListener('mousedown', function(e) { 270 | // for (var i = 0; i < 100; i++) { 271 | // this.add(); 272 | // } 273 | // }.bind(this)); 274 | // window.addEventListener('touchstart', function(e) { 275 | // e.preventDefault(); 276 | // for (var i = 0; i < 100; i++) { 277 | // this.add(); 278 | // } 279 | // }.bind(this)); 280 | }; 281 | var app = new Build(); 282 | app.run(); 283 | })(); 284 | window.addEventListener('resize', function () { 285 | if ((typeof container !== 'undefined')) { 286 | container.width = w = window.innerWidth; 287 | container.height = h = window.innerHeight; 288 | } 289 | }, false); 290 | } 291 | 292 | const StarryGalaxy = () => { 293 | const widget = useRef() 294 | 295 | useEffect(() => { 296 | if ((typeof window !== 'undefined')) { 297 | run(widget.current) 298 | } 299 | } 300 | , []) 301 | return 302 | } 303 | 304 | export default StarryGalaxy 305 | --------------------------------------------------------------------------------