├── 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 |
7 |
--------------------------------------------------------------------------------
/dapp/src/assets/svg/video-overlay.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 | 
14 | 
15 |
16 | ## Dashboard
17 | 
18 |
19 | ## Account
20 | 
21 |
22 | ## Reflection
23 | 
--------------------------------------------------------------------------------
/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 |

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

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 |
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 |
57 | }
58 | {type === 'info' &&
59 |
62 | }
63 | {
64 | type === 'danger' &&
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 |

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 |
260 | {txRes &&
}
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 |
--------------------------------------------------------------------------------