├── .env.sample
├── .github
├── ISSUE_TEMPLATE
│ ├── BUG_REPORT.yml
│ ├── DOCUMENTATION_README_ISSUE.yml
│ ├── FEATURE_ENHANCEMENT.yml
│ ├── NEW_FEATURE_REQUEST.yml
│ └── QUESTION_SUPPORT.yml
└── workflows
│ └── auto_add_project.yml
├── .gitignore
├── .gitmodules
├── README.md
├── app.js
├── contracts
├── PushComm
│ ├── EPNSCommAdmin.sol
│ ├── EPNSCommProxy.sol
│ ├── PushCommStorageV2.sol
│ └── PushCommV2.sol
├── PushCore
│ ├── EPNSCoreAdmin.sol
│ ├── EPNSCoreProxy.sol
│ ├── PushCoreStorageV1_5.sol
│ ├── PushCoreStorageV2.sol
│ └── PushCoreV2.sol
├── governance
│ ├── GovernorBravo.sol
│ ├── GovernorBravoInterfaces.sol
│ ├── PushBravoProxy.sol
│ ├── Timelock.sol
│ └── VerzionedInitializable.sol
├── interfaces
│ ├── IADai.sol
│ ├── IEPNSCommV1.sol
│ ├── IERC1271.sol
│ ├── ILendingPool.sol
│ ├── IPUSH.sol
│ ├── IPushCore.sol
│ ├── ITokenBridge.sol
│ └── IUniswapV2Router.sol
├── mocks
│ ├── IUniswapV2RouterMock.sol
│ ├── MockDai.sol
│ └── MockERC1271.sol
└── token
│ ├── EPNS.args
│ └── EPNS.sol
├── contributing.md
├── foundry.toml
├── hardhat.config.js
├── helpers
└── utils.js
├── license-v1
├── loaders
├── envVerifier.js
├── tokenAmountVerifier.js
└── versionVerifier.js
├── package-lock.json
├── package.json
├── scripts
├── 0_deploySample.js
├── 1_5_deployEPNSCoreV1_5.js
├── 1_deployEPNSCoreV1.js
├── 2_5_deployEPNSCommV1_5.js
├── 2_deployEPNSCommV1.js
├── 3_deployEPNSCoreV2.js
├── 4_deployEPNSCommV2.js
├── 5_deployEPNSCoreV3.js
├── 6_deployEPNSCommV3.js
└── versioncontrol
│ ├── 0_deploySample.config.js
│ ├── 1_5_deployEPNSCoreV1_5.config.js
│ ├── 1_deployEPNSCoreV1.config.js
│ ├── 2_5_deployEPNSCommV1_5.config.js
│ ├── 2_deployEPNSCommV1.config.js
│ ├── 3_deployEPNSCoreV2.config.js
│ ├── 4_deployEPNSCommV2.config.js
│ ├── 5_deployEPNSCoreV3.config.js
│ └── 6_deployEPNSCommV3.config.js
├── test
├── benchmarks
│ └── EPNSCoreV1.Benchmark.test.js
├── common
│ ├── expect.js
│ ├── fixtures.js
│ ├── fixturesV2.js
│ └── fixtures_temp.js
├── time.js
└── v2
│ ├── comm
│ ├── SendNotification.test.js
│ ├── SendNotificationFromSig.test.js
│ └── SubscribeBySig.test.js
│ └── core
│ ├── ChannelCreationPush.test.js
│ ├── ChannelStateCycle.test.js
│ ├── IncentivizedChatRequest.test.js
│ ├── Pausability.test.js
│ ├── StakeAndClaim.test.js
│ ├── TimeBoundChannel.test.js
│ └── UpdateChannelMeta.test.js
└── wallets
└── !noremove
/.env.sample:
--------------------------------------------------------------------------------
1 | # WEB3 CREDENTIALS
2 | ALCHEMY_API=your_alchemy_id
3 | INFURA_PROJECT_ID=your_infura_id
4 | INFURA_PROJECT_SECRET=your_infura_secret
5 | ETHERSCAN_API=your_ETHERSCAN_API
6 | POLYGONSCAN_API=your_polygonscan_api
7 | OPTIMISM_API=your_optimism_api
8 | ARBISCAN_API=your_arbitrum_api
9 | BNBSCAN_API=your_bnbscan_api
10 | FUSE_API=your_fuse_api
11 |
12 | # FILE SYSTEM PATHS
13 | FS_ARTIFCATS=artifacts
14 | FS_DEPLOYMENT_INFO=deployment_info
15 | FS_BULK_EXPORT=bulk_export
16 | FS_VERSIONING_INFO=version_control
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG_REPORT.yml:
--------------------------------------------------------------------------------
1 | name: "🐛 Bug Report"
2 | description: Create a bug report to help us improve.
3 | title: "🐛 [BUG] -
"
4 | labels: ["bug"]
5 | body:
6 | - type: textarea
7 | id: expected-behaviour
8 | attributes:
9 | label: "Expected Behaviour"
10 | description: Please describe the behavior you are expecting
11 | placeholder: Short and explicit description of your desired behaviour...
12 | validations:
13 | required: true
14 | - type: textarea
15 | id: current-behaviour
16 | attributes:
17 | label: "Current Behaviour"
18 | description: Please describe the current behavior
19 | placeholder: What is the current behavior?...
20 | validations:
21 | required: true
22 | - type: textarea
23 | id: reprod
24 | attributes:
25 | label: "Reproduction steps"
26 | description: Please enter an explicit description of your issue
27 | value: |
28 | 1. Go to '...'
29 | 2. Click on '....'
30 | 3. Scroll down to '....'
31 | 4. See error
32 | render: bash
33 | validations:
34 | required: true
35 | - type: textarea
36 | id: screenshot
37 | attributes:
38 | label: "Screenshots"
39 | description: If applicable, add screenshots to help explain your problem.
40 | value: |
41 | 
42 | render: bash
43 | validations:
44 | required: false
45 | - type: input
46 | id: POC-url
47 | attributes:
48 | label: "POC if available"
49 | description: Please enter POC url, if available
50 | placeholder: POC Link
51 | validations:
52 | required: false
53 | - type: dropdown
54 | id: contracts
55 | attributes:
56 | label: "Contract Name"
57 | description: What are the impacted Contract(s) ?
58 | multiple: true
59 | options:
60 | - Core Contract
61 | - Comm Contract
62 | - Push Token
63 | validations:
64 | required: true
65 | - type: dropdown
66 | id: contract-chain
67 | attributes:
68 | label: "Chains"
69 | description: On which chain does this issue primarily exists?
70 | multiple: true
71 | options:
72 | - Mainnet(Ethereum)
73 | - Testnet(Goerli)
74 | - Polygon
75 | - BSC
76 | validations:
77 | required: false
78 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/DOCUMENTATION_README_ISSUE.yml:
--------------------------------------------------------------------------------
1 | name: "✏️ Documentation/Readme Enhancement"
2 | description: Suggest an enhancement in documentation/readme.
3 | title: "✏️ [Documentation/Readme Enhancement] - "
4 | labels: [
5 | "documentation"
6 | ]
7 | body:
8 | - type: textarea
9 | id: expected-behaviour
10 | attributes:
11 | label: "Expected Behaviour"
12 | description: Please describe the behavior you are expecting
13 | placeholder: Short and explicit description of your desired behaviour...
14 | validations:
15 | required: false
16 | - type: textarea
17 | id: current-behaviour
18 | attributes:
19 | label: "Current Behaviour"
20 | description: Please describe the current behavior
21 | placeholder: What is the current behavior?...
22 | validations:
23 | required: false
24 | - type: textarea
25 | id: reprod
26 | attributes:
27 | label: "Steps to Reproduce"
28 | description: Please enter an explicit description of your issue
29 | value: |
30 | 1. Go to '...'
31 | 2. Click on '....'
32 | 3. Scroll down to '....'
33 | 4. See it
34 | render: bash
35 | validations:
36 | required: false
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE_ENHANCEMENT.yml:
--------------------------------------------------------------------------------
1 | name: "😈 Feature Enhancement"
2 | description: Suggest enhancement for an existing feature.
3 | title: "😈 [Feature Enhancement] - "
4 | labels: ["feature enhancement"]
5 | body:
6 | - type: input
7 | id: feature-name
8 | attributes:
9 | label: "Feature name"
10 | description: Current feature behaviour
11 | placeholder: Current Feature
12 | validations:
13 | required: false
14 | - type: textarea
15 | id: description
16 | attributes:
17 | label: "Describe the Enhancement"
18 | description: Please describe the feature in detail that you're expecting
19 | placeholder: Detailed description of your desired feature...
20 | validations:
21 | required: true
22 | - type: input
23 | id: POC-url
24 | attributes:
25 | label: "POC if available"
26 | description: Please enter POC url, if available
27 | placeholder: POC Link
28 | validations:
29 | required: false
30 | - type: dropdown
31 | id: contracts
32 | attributes:
33 | label: "Contract Name"
34 | description: Which contract will be enhanced?
35 | multiple: true
36 | options:
37 | - Core Contract
38 | - Comm Contract
39 | - Push Token
40 | - Push Governance Contracts
41 | - Push Staking V2
42 | - Scripts Or tests
43 | validations:
44 | required: true
45 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/NEW_FEATURE_REQUEST.yml:
--------------------------------------------------------------------------------
1 | name: "🚀 Feature Request"
2 | description: Suggest a new feature for this project.
3 | title: "🚀 [New Feature] - "
4 | labels: [
5 | "New feature"
6 | ]
7 | body:
8 | - type: textarea
9 | id: description
10 | attributes:
11 | label: "Describe the Feature"
12 | description: Please describe the feature in detail that you're expecting and how it helps the overall protocol
13 | placeholder: Detailed description of your desired feature...
14 | validations:
15 | required: true
16 | - type: textarea
17 | id: description
18 | attributes:
19 | label: "Does this break any existing part of the contract?"
20 | description: Explain (in brief) if this feature will have any effect on existing contracts...
21 | placeholder: Brief explanation
22 | validations:
23 | required: false
24 | - type: dropdown
25 | id: contracts
26 | attributes:
27 | label: "Contract Name"
28 | description: Which contract is this feature suggested for?
29 | multiple: true
30 | options:
31 | - Core Contract
32 | - Comm Contract
33 | - Push Token
34 | - Push Governance Contracts
35 | - Push Staking V2
36 | validations:
37 | required: false
38 |
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/QUESTION_SUPPORT.yml:
--------------------------------------------------------------------------------
1 | name: "❓ Question or Support Request"
2 | description: Questions and requests for support.
3 | title: "❓ [Question/Support] - "
4 | labels: [
5 | "support"
6 | ]
7 | body:
8 | - type: textarea
9 | id: support-request
10 | attributes:
11 | label: "Question or Support Request"
12 | description: Describe your question or ask for support.
13 | placeholder: Detailed description of your question/support request...
14 | validations:
15 | required: true
--------------------------------------------------------------------------------
/.github/workflows/auto_add_project.yml:
--------------------------------------------------------------------------------
1 | name: Auto-add issues to org project
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 |
8 | jobs:
9 | add-to-project:
10 | name: Auto-add issues to org project
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/add-to-project@v0.5.0
14 | with:
15 | project-url: https://github.com/orgs/push-protocol/projects/10
16 | github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | packages/buidler/*.txt
2 | **/aws.json
3 | *.lock
4 |
5 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
6 | **/node_modules
7 | packages/buidler/artifacts
8 | packages/react-app/src/contracts
9 | packages/buidler/cache
10 |
11 | # dependencies
12 | /node_modules
13 | /.pnp
14 | .pnp.js
15 |
16 | # testing
17 | coverage
18 |
19 | # production
20 | build
21 |
22 | # misc
23 | .DS_Store
24 | .env
25 | cache_forge
26 | out
27 |
28 | # debug
29 | npm-debug.log*
30 | yarn-debug.log*
31 | yarn-error.log*
32 |
33 | .idea
34 | ./cache
35 | /cache
36 | /cache/*
37 | /wallets/*.txt
38 | /artifacts
39 | /artifacts/*
40 | .txt
41 | package-lock.json
42 | yarn.lock
43 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lib/forge-std"]
2 | path = lib/forge-std
3 | url = https://github.com/foundry-rs/forge-std
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | Push Protocol is a web3 communication network, enabling cross-chain notifications, messaging, video, and NFT chat for dapps, wallets, and services.🚀
12 |
13 |
14 |
26 |
27 | # Push Protocol Smart Contracts
28 |
29 | Welcome to the repository for the smart contracts of the Push Protocol. This repository contains the core code that powers our decentralized communication network. The Push Protocol is a web3 communication protocol that enables cross-chain notifications and messaging for decentralized applications (dApps), wallets, and services.
30 |
31 | Our smart contracts are the backbone of the Push Protocol, enabling the functionality that allows for on-chain and off-chain communication via user wallet addresses. This is done in an open, gasless, multichain, and platform-agnostic fashion.
32 |
33 | In this repository, you will find the contracts that handle various aspects of the Push Protocol, from channel creation and verification to notification sending and subscription handling. We also provide a suite of tests to ensure the robustness and security of our contracts.
34 |
35 | We invite you to explore, contribute, and help us build the future of web3 communication.
36 |
37 |
38 |
39 | ---
40 |
41 | ## 📚 Table of Contents
42 | - [Smart Contract Address](#smart-contract-addresses)
43 | - [Modules](#-modules)
44 | - [Getting Started/Installation](#getting-started)
45 | - [Resources](#resources)
46 | - [Contributing](#contributing)
47 |
48 |
49 | ## Smart Contract Addresses
50 |
51 | Contract addresses for Ethereum Mainnet.
52 |
53 | | Contract Name | Contract Address |
54 | | ------------- | ---------------- |
55 | | Push Token | [0xf418588522d5dd018b425E472991E52EBBeEEEEE](https://etherscan.io/address/0xf418588522d5dd018b425E472991E52EBBeEEEEE) |
56 | | EPNS CoreV1.5 | [0x66329Fdd4042928BfCAB60b179e1538D56eeeeeE](https://etherscan.io/address/0x66329Fdd4042928BfCAB60b179e1538D56eeeeeE) |
57 | | EPNS CommV1.5 | [0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa](https://etherscan.io/address/0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa) |
58 |
59 | Contract addresses for Ethereum Goerli Testnet.
60 |
61 | | Contract Name | Contract Address |
62 | | ------------- | ---------------- |
63 | | Push Token | [0x2b9bE9259a4F5Ba6344c1b1c07911539642a2D33](https://goerli.etherscan.io/address/0x2b9bE9259a4F5Ba6344c1b1c07911539642a2D33) |
64 | | EPNS CoreV1.5 | [0xd4E3ceC407cD36d9e3767cD189ccCaFBF549202C](https://goerli.etherscan.io/address/0xd4E3ceC407cD36d9e3767cD189ccCaFBF549202C) |
65 | | EPNS CommV1.5 | [0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa](https://goerli.etherscan.io/address/0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa) |
66 |
67 |
68 | Contract addresses for Ethereum Sepolia Testnet.
69 |
70 | | Contract Name | Contract Address |
71 | | ------------- | ---------------- |
72 | | Push Token | [0x37c779a1564DCc0e3914aB130e0e787d93e21804](https://sepolia.etherscan.io/address/0x37c779a1564DCc0e3914aB130e0e787d93e21804) |
73 | | EPNS CoreV1.5 | [0x9d65129223451fbd58fc299C635Cd919BaF2564C](https://sepolia.etherscan.io/address/0x9d65129223451fbd58fc299C635Cd919BaF2564C#code) |
74 | | EPNS CommV1.5 | [0x0C34d54a09CFe75BCcd878A469206Ae77E0fe6e7](https://sepolia.etherscan.io/address/0x0c34d54a09cfe75bccd878a469206ae77e0fe6e7) |
75 |
76 | You can find addresses for other networks over at our Docs
77 |
78 | ## 🧩 Modules
79 |
80 | Epnscomm
81 |
82 | | File | Summary | Module |
83 | |:------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------|
84 | | EPNSCommV1.sol | This code is the implementation of the EPNS Communicator protocol, which is a communication layer between end users and the EPNS Core Protocol. It allows users to subscribe to channels, unsubscribe from channels, and send notifications to specific recipients or all subscribers of a channel.|
85 | | || |
86 | | EPNSCommStorageV1_5.sol | This Solidity code defines a contract for storing and managing user data in the Ethereum Push Notification Service (EPNS) protocol. It includes a User struct for organizing data about users and several mappings that track user and channel subscriptions. The contract also includes state variables for governance, user count, and more. | contracts/EPNSComm/EPNSCommStorageV1_5.sol |
87 | | EPNSCommAdmin.sol | This code snippet is a Solidity contract that extends the ProxyAdmin contract from the OpenZeppelin library. Its main functionality is to serve as a proxy administrator for a smart contract system, allowing the updating and upgrading of contracts in the system, while maintaining the same deployment address and keeping the contract functionalities intact. The SPDX-License-Identifier is also included, specifying the open-source MIT license. | contracts/EPNSComm/EPNSCommAdmin.sol |
88 | | EPNSCommProxy.sol | The provided Solidity contract is an implementation of a transparent upgradeable proxy using the OpenZeppelin library. It takes in parameters for the contract's logic, governance address, push-channel admin address, and chain name as part of its constructor function. Upon initialization, the contract transparently proxies its functionality, allowing future upgrades and modifications without breaking functionality or requiring migrations. | contracts/EPNSComm/EPNSCommProxy.sol |
89 | | EPNSCommV1_5.sol | This code defines the storage contract for the EPNS Communicator protocol version 1.5. It includes the user struct and mappings to track user details, subscriptions, notification settings, and delegated notification senders. It also includes state variables for governance, push channel admin, chain ID, user count, migration status, EPNS Core address, chain name, and type hashes for various types of transactions. | contracts/EPNSComm/EPNSCommV1_5.sol |
90 | | || |
91 |
92 |
93 |
94 | Epnscore
95 |
96 | | File | Summary | Module |
97 | |:------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------|
98 | | EPNSCoreV1.sol | The code is a smart contract implementation called "EPNSCoreV1" for a decentralized notification protocol. It includes functionalities such as creating and managing channels, channel verification, depositing and withdrawing funds, and fair share ratio calculations for distributing rewards. | contracts/EPNSCore/EPNSCoreV1.sol |
99 | | || |
100 | | EPNSCoreProxy.sol | The code defines a contract EPNSCoreProxy that extends the TransparentUpgradeableProxy to enable transparent and secure upgrades. It uses the constructor to set various parameters, such as logic contract, governance address, WETH and DAI addresses, and initialization parameters by encoding values using abi.encodeWithSignature(). | contracts/EPNSCore/EPNSCoreProxy.sol |
101 | | EPNSCoreStorageV2.sol | The provided code defines a contract called EPNSCoreStorageV2 that has three state variables. It defines two types of byte32 hash constants and mappings for nonces, channel update counters and rewards claimed by addresses for channel creation. It specifies the Solidity compiler version to be used as greater than or equal to 0.6.0 and less than 0.7.0. | contracts/EPNSCore/EPNSCoreStorageV2.sol |
102 | | EPNSCoreAdmin.sol | The code defines a contract called EPNSCoreAdmin that imports "ProxyAdmin" from the "@openzeppelin/contracts/proxy/" package. The contract defines no behavior of its own and essentially acts as a forwarding service that allows an admin to upgrade other contacts via a proxy. It is licensed under MIT. | contracts/EPNSCore/EPNSCoreAdmin.sol |
103 | | TempStorage.sol | The provided code is for a Solidity smart contract called TempStorage, which serves as a temporary storage for channels whose poolContribution and weight have been updated. It uses a mapping data structure to keep track of updated channels and has two functions that allow users to check if a channel has been adjusted and to mark a channel as adjusted, respectively. The constructor function sets the Core_Address of the contract and requires that it be a non-zero address. | contracts/EPNSCore/TempStorage.sol |
104 | | EPNSCoreStorageV1_5.sol | This Solidity contract defines the storage layout for an Ethereum Push Notification Service (EPNS). It includes various enums, constants, mappings, and state variables to keep track of channels created by users, historical data, fair share ratios, fee calculations, and more. | contracts/EPNSCore/EPNSCoreStorageV1_5.sol |
105 |
106 |
107 |
108 |
109 | ---
110 |
111 | ## Getting Started
112 |
113 |
114 | ### 🖥 Installation
115 |
116 | 1. Clone the push-smart-contracts repository:
117 | ```sh
118 | git clone https://github.com/ethereum-push-notification-service/push-smart-contracts
119 | ```
120 |
121 | 2. Change to the project directory:
122 | ```sh
123 | cd push-smart-contracts
124 | ```
125 |
126 | 3. Install the dependencies:
127 | ```sh
128 | npm install
129 | ```
130 |
131 | ### 🧪 Running Tests
132 | ```sh
133 | npx hardhat test
134 | ```
135 | OR
136 | ```sh
137 | forge test
138 | ```
139 | ---
140 |
141 | ## Resources
142 | - **[Website](https://push.org)** To checkout our Product.
143 | - **[Docs](https://push.org/docs/)** For comprehensive documentation.
144 | - **[Blog](https://medium.com/push-protocol)** To learn more about our partners, new launches, etc.
145 | - **[Discord](https://discord.gg/pushprotocol)** for support and discussions with the community and the team.
146 | - **[GitHub](https://github.com/push-protocol)** for source code, project board, issues, and pull requests.
147 | - **[Twitter](https://twitter.com/pushprotocol)** for the latest updates on the product and published blogs.
148 |
149 |
150 | ## Contributing
151 |
152 | Push Protocol is an open source Project. We firmly believe in a completely transparent development process and value any contributions. We would love to have you as a member of the community, whether you are assisting us in bug fixes, suggesting new features, enhancing our documentation, or simply spreading the word.
153 |
154 | - Bug Report: Please create a bug report if you encounter any errors or problems while utilising the Push Protocol.
155 | - Feature Request: Please submit a feature request if you have an idea or discover a capability that would make development simpler and more reliable.
156 | - Documentation Request: If you're reading the Push documentation and believe that we're missing something, please create a docs request.
157 |
158 |
159 | Read how you can contribute HERE
160 |
161 |
162 | Not sure where to start? Join our discord and we will help you get started!
163 |
164 |
165 |
166 | ## License
167 | Check out our License HERE
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk');
2 |
3 | async function startSetup() {
4 | const envVerifierLoader = require('./loaders/envVerifier');
5 | await envVerifierLoader(false);
6 | console.log(chalk.bgWhite.black('✔️ Setup Completed!'));
7 | console.log(chalk.bgBlue.white(`Let's npx hardhat and #BUIDL`));
8 | }
9 |
10 | startSetup();
11 |
--------------------------------------------------------------------------------
/contracts/PushComm/EPNSCommAdmin.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.6.0;
4 |
5 | import "@openzeppelin/contracts/proxy/ProxyAdmin.sol";
6 |
7 | contract EPNSCommAdmin is ProxyAdmin {}
8 |
--------------------------------------------------------------------------------
/contracts/PushComm/EPNSCommProxy.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.6.0;
4 |
5 | import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol";
6 |
7 | contract EPNSCommProxy is TransparentUpgradeableProxy {
8 | constructor(
9 | address _logic,
10 | address _governance,
11 | address _pushChannelAdmin,
12 | string memory _chainName
13 | )
14 | public
15 | payable
16 | TransparentUpgradeableProxy(
17 | _logic,
18 | _governance,
19 | abi.encodeWithSignature(
20 | "initialize(address,string)",
21 | _pushChannelAdmin,
22 | _chainName
23 | )
24 | )
25 | {}
26 | }
27 |
--------------------------------------------------------------------------------
/contracts/PushComm/PushCommStorageV2.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | contract PushCommStorageV2 {
4 | /**
5 | * @notice User Struct that involves imperative details about
6 | * a specific User.
7 | **/
8 | struct User {
9 | // @notice Depicts whether or not a user is ACTIVE
10 | bool userActivated;
11 | // @notice Will be false until public key is emitted
12 | bool publicKeyRegistered;
13 | // @notice Events should not be polled before this block as user doesn't exist
14 | uint256 userStartBlock;
15 | // @notice Keep track of subscribers
16 | uint256 subscribedCount;
17 | /**
18 | * Depicts if User subscribed to a Specific Channel Address
19 | * 1 -> User is Subscribed
20 | * 0 -> User is NOT SUBSCRIBED
21 | **/
22 | mapping(address => uint8) isSubscribed;
23 | // Keeps track of all subscribed channels
24 | mapping(address => uint256) subscribed;
25 | mapping(uint256 => address) mapAddressSubscribed;
26 | }
27 |
28 | /** MAPPINGS **/
29 | mapping(address => User) public users;
30 | mapping(address => uint256) public nonces;
31 | mapping(uint256 => address) public mapAddressUsers;
32 | mapping(address => mapping(address => string)) public userToChannelNotifs;
33 | mapping(address => mapping(address => bool))
34 | public delegatedNotificationSenders;
35 |
36 | /** STATE VARIABLES **/
37 | address public governance;
38 | address public pushChannelAdmin;
39 | uint256 public chainID;
40 | uint256 public usersCount;
41 | bool public isMigrationComplete;
42 | address public EPNSCoreAddress;
43 | string public chainName;
44 | string public constant name = "EPNS COMM V1";
45 | bytes32 public constant NAME_HASH = keccak256(bytes(name));
46 | bytes32 public constant DOMAIN_TYPEHASH =
47 | keccak256(
48 | "EIP712Domain(string name,uint256 chainId,address verifyingContract)"
49 | );
50 | bytes32 public constant SUBSCRIBE_TYPEHASH =
51 | keccak256(
52 | "Subscribe(address channel,address subscriber,uint256 nonce,uint256 expiry)"
53 | );
54 | bytes32 public constant UNSUBSCRIBE_TYPEHASH =
55 | keccak256(
56 | "Unsubscribe(address channel,address subscriber,uint256 nonce,uint256 expiry)"
57 | );
58 | bytes32 public constant SEND_NOTIFICATION_TYPEHASH =
59 | keccak256(
60 | "SendNotification(address channel,address recipient,bytes identity,uint256 nonce,uint256 expiry)"
61 | );
62 | // New State Variables
63 | address public PUSH_TOKEN_ADDRESS;
64 |
65 | struct ChatDetails {
66 | address requestSender;
67 | uint256 timestamp;
68 | uint256 amountDeposited;
69 | }
70 |
71 | mapping(address => ChatDetails) public userChatData;
72 | }
73 |
--------------------------------------------------------------------------------
/contracts/PushCore/EPNSCoreAdmin.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.6.0;
4 |
5 | import "@openzeppelin/contracts/proxy/ProxyAdmin.sol";
6 |
7 | contract EPNSCoreAdmin is ProxyAdmin {}
8 |
--------------------------------------------------------------------------------
/contracts/PushCore/EPNSCoreProxy.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.6.0;
4 |
5 | import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol";
6 |
7 | contract EPNSCoreProxy is TransparentUpgradeableProxy {
8 | constructor(
9 | address _logic,
10 | address _governance,
11 | address _pushChannelAdmin,
12 | address _pushTokenAddress,
13 | address _wethAddress,
14 | address _uniswapRouterAddress,
15 | address _lendingPoolProviderAddress,
16 | address _daiAddress,
17 | address _aDaiAddress,
18 | uint256 _referralCode
19 | )
20 | public
21 | payable
22 | TransparentUpgradeableProxy(
23 | _logic,
24 | _governance,
25 | abi.encodeWithSignature(
26 | "initialize(address,address,address,address,address,address,address,uint256)",
27 | _pushChannelAdmin,
28 | _pushTokenAddress,
29 | _wethAddress,
30 | _uniswapRouterAddress,
31 | _lendingPoolProviderAddress,
32 | _daiAddress,
33 | _aDaiAddress,
34 | _referralCode
35 | )
36 | )
37 | {}
38 | }
39 |
--------------------------------------------------------------------------------
/contracts/PushCore/PushCoreStorageV1_5.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | contract PushCoreStorageV1_5 {
4 | /* ***************
5 |
6 | DEFINE ENUMS AND CONSTANTS
7 |
8 | *************** */
9 |
10 | // For Message Type
11 | enum ChannelType {
12 | ProtocolNonInterest,
13 | ProtocolPromotion,
14 | InterestBearingOpen,
15 | InterestBearingMutual,
16 | TimeBound,
17 | TokenGaited
18 | }
19 | enum ChannelAction {
20 | ChannelRemoved,
21 | ChannelAdded,
22 | ChannelUpdated
23 | }
24 |
25 | /**
26 | * @notice Channel Struct that includes imperative details about a specific Channel.
27 | **/
28 | struct Channel {
29 | // @notice Denotes the Channel Type
30 | ChannelType channelType;
31 | /** @notice Symbolizes Channel's State:
32 | * 0 -> INACTIVE,
33 | * 1 -> ACTIVATED
34 | * 2 -> DeActivated By Channel Owner,
35 | * 3 -> BLOCKED by pushChannelAdmin/Governance
36 | **/
37 | uint8 channelState;
38 | // @notice denotes the address of the verifier of the Channel
39 | address verifiedBy;
40 | // @notice Total Amount of Dai deposited during Channel Creation
41 | uint256 poolContribution;
42 | // @notice Represents the Historical Constant
43 | uint256 channelHistoricalZ;
44 | // @notice Represents the FS Count
45 | uint256 channelFairShareCount;
46 | // @notice The last update block number, used to calculate fair share
47 | uint256 channelLastUpdate;
48 | // @notice Helps in defining when channel started for pool and profit calculation
49 | uint256 channelStartBlock;
50 | // @notice Helps in outlining when channel was updated
51 | uint256 channelUpdateBlock;
52 | // @notice The individual weight to be applied as per pool contribution
53 | uint256 channelWeight;
54 | // @notice The Expiry TimeStamp in case of TimeBound Channel Types
55 | uint256 expiryTime;
56 | }
57 |
58 | /* ***************
59 | MAPPINGS
60 | *************** */
61 |
62 | mapping(address => Channel) public channels;
63 | mapping(uint256 => address) public channelById; // NOT IN USE
64 | mapping(address => string) public channelNotifSettings;
65 |
66 | /* ***************
67 | STATE VARIABLES
68 | *************** */
69 | string public constant name = "EPNS_CORE_V2";
70 | bool oneTimeCheck;
71 | bool public isMigrationComplete;
72 |
73 | address public pushChannelAdmin;
74 | address public governance;
75 | address public daiAddress;
76 | address public aDaiAddress;
77 | address public WETH_ADDRESS;
78 | address public epnsCommunicator;
79 | address public UNISWAP_V2_ROUTER;
80 | address public PUSH_TOKEN_ADDRESS;
81 | address public lendingPoolProviderAddress;
82 |
83 | uint256 public REFERRAL_CODE;
84 | uint256 ADJUST_FOR_FLOAT;
85 | uint256 public channelsCount;
86 |
87 | // @notice Helper Variables for FSRatio Calculation | GROUPS = CHANNELS -> NOT IN USE
88 | uint256 public groupNormalizedWeight;
89 | uint256 public groupHistoricalZ;
90 | uint256 public groupLastUpdate;
91 | uint256 public groupFairShareCount;
92 |
93 | // @notice Necessary variables for Keeping track of Funds and Fees
94 | uint256 public CHANNEL_POOL_FUNDS;
95 | uint256 public PROTOCOL_POOL_FEES;
96 | uint256 public ADD_CHANNEL_MIN_FEES;
97 | uint256 public FEE_AMOUNT;
98 | uint256 public MIN_POOL_CONTRIBUTION;
99 | }
--------------------------------------------------------------------------------
/contracts/PushCore/PushCoreStorageV2.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | contract PushCoreStorageV2{
4 |
5 | /* *** V2 State variables *** */
6 | bytes32 public constant DOMAIN_TYPEHASH =
7 | keccak256(
8 | "EIP712Domain(string name, uint256 chainId, address verifyingContract)"
9 | );
10 | bytes32 public constant CREATE_CHANNEL_TYPEHASH =
11 | keccak256(
12 | "CreateChannel(ChannelType channelType, bytes identity, uint256 amount, uint256 channelExpiryTime, uint256 nonce, uint256 expiry)"
13 | );
14 |
15 | mapping(address => uint256) public nonces;
16 | mapping(address => uint256) public channelUpdateCounter;
17 | /** Staking V2 state variables **/
18 | mapping(address => uint256) public usersRewardsClaimed;
19 |
20 | //@notice: Stores all user's staking details
21 | struct UserFessInfo {
22 | uint256 stakedAmount;
23 | uint256 stakedWeight;
24 | uint256 lastStakedBlock;
25 | uint256 lastClaimedBlock;
26 | mapping(uint256 => uint256) epochToUserStakedWeight;
27 | }
28 |
29 | uint256 public genesisEpoch; // Block number at which Stakig starts
30 | uint256 lastEpochInitialized; // The last EPOCH ID initialized with the respective epoch rewards
31 | uint256 lastTotalStakeEpochInitialized; // The last EPOCH ID initialized with the respective total staked weight
32 | uint256 public totalStakedAmount; // Total token weight staked in Protocol at any given time
33 | uint256 public previouslySetEpochRewards; // Amount of rewards set in last initialized epoch
34 | uint256 public constant epochDuration = 21 * 7156; // 21 * number of blocks per day(7156) ~ 20 day approx
35 |
36 | // @notice: Stores all the individual epoch rewards
37 | mapping(uint256 => uint256) public epochRewards;
38 | // @notice: Stores User's Fees Details
39 | mapping(address => UserFessInfo) public userFeesInfo;
40 | // @notice: Stores the total staked weight at a specific epoch.
41 | mapping(uint256 => uint256) public epochToTotalStakedWeight;
42 |
43 | /** Handling bridged information **/
44 | mapping(address => uint256) public celebUserFunds;
45 | }
46 |
--------------------------------------------------------------------------------
/contracts/governance/GovernorBravoInterfaces.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 | pragma experimental ABIEncoderV2;
3 |
4 |
5 | contract GovernorBravoEvents {
6 | /// @notice An event emitted when a new proposal is created
7 | event ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string description);
8 |
9 | /// @notice An event emitted when a vote has been cast on a proposal
10 | /// @param voter The address which casted a vote
11 | /// @param proposalId The proposal id which was voted on
12 | /// @param support Support value for the vote. 0=against, 1=for, 2=abstain
13 | /// @param votes Number of votes which were cast by the voter
14 | /// @param reason The reason given for the vote by the voter
15 | event VoteCast(address indexed voter, uint proposalId, uint8 support, uint votes, string reason);
16 |
17 | /// @notice An event emitted when a proposal has been canceled
18 | event ProposalCanceled(uint id);
19 |
20 | /// @notice An event emitted when a proposal has been queued in the Timelock
21 | event ProposalQueued(uint id, uint eta);
22 |
23 | /// @notice An event emitted when a proposal has been executed in the Timelock
24 | event ProposalExecuted(uint id);
25 |
26 | /// @notice An event emitted when the voting delay is set
27 | event VotingDelaySet(uint oldVotingDelay, uint newVotingDelay);
28 |
29 | /// @notice An event emitted when the voting period is set
30 | event VotingPeriodSet(uint oldVotingPeriod, uint newVotingPeriod);
31 |
32 | /// @notice Emitted when proposal threshold is set
33 | event ProposalThresholdSet(uint oldProposalThreshold, uint newProposalThreshold);
34 |
35 | /// @notice Emitted when pendingAdmin is changed
36 | event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
37 |
38 | /// @notice Emitted when pendingAdmin is accepted, which means admin is updated
39 | event NewAdmin(address oldAdmin, address newAdmin);
40 | }
41 |
42 | contract GovernorBravoDelegatorStorage {
43 | /// @notice Administrator for this contract
44 | address public admin;
45 |
46 | /// @notice Pending administrator for this contract
47 | address public pendingAdmin;
48 | }
49 |
50 |
51 | /**
52 | * @title Storage for Governor Bravo Delegate
53 | * @notice For future upgrades, do not change GovernorBravoDelegateStorageV1. Create a new
54 | * contract which implements GovernorBravoDelegateStorageV1 and following the naming convention
55 | * GovernorBravoDelegateStorageVX.
56 | */
57 | contract GovernorBravoDelegateStorageV1 is GovernorBravoDelegatorStorage {
58 |
59 | /// @notice The delay before voting on a proposal may take place, once proposed, in blocks
60 | uint public votingDelay;
61 |
62 | /// @notice The duration of voting on a proposal, in blocks
63 | uint public votingPeriod;
64 |
65 | /// @notice The number of votes required in order for a voter to become a proposer
66 | uint public proposalThreshold;
67 |
68 | /// @notice The total number of proposals
69 | uint public proposalCount;
70 |
71 | /// @notice The address of the EPNS Protocol Timelock
72 | TimelockInterface public timelock;
73 |
74 | /// @notice The address of the EPNS governance token
75 | EPNSInterface public PUSH;
76 |
77 | /// @notice The official record of all proposals ever proposed
78 | mapping (uint => Proposal) public proposals;
79 |
80 | /// @notice The latest proposal for each proposer
81 | mapping (address => uint) public latestProposalIds;
82 |
83 |
84 | struct Proposal {
85 | /// @notice Unique id for looking up a proposal
86 | uint id;
87 |
88 | /// @notice Creator of the proposal
89 | address proposer;
90 |
91 | /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds
92 | uint eta;
93 |
94 | /// @notice the ordered list of target addresses for calls to be made
95 | address[] targets;
96 |
97 | /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made
98 | uint[] values;
99 |
100 | /// @notice The ordered list of function signatures to be called
101 | string[] signatures;
102 |
103 | /// @notice The ordered list of calldata to be passed to each call
104 | bytes[] calldatas;
105 |
106 | /// @notice The block at which voting begins: holders must delegate their votes prior to this block
107 | uint startBlock;
108 |
109 | /// @notice The block at which voting ends: votes must be cast prior to this block
110 | uint endBlock;
111 |
112 | /// @notice Current number of votes in favor of this proposal
113 | uint forVotes;
114 |
115 | /// @notice Current number of votes in opposition to this proposal
116 | uint againstVotes;
117 |
118 | /// @notice Current number of votes for abstaining for this proposal
119 | uint abstainVotes;
120 |
121 | /// @notice Flag marking whether the proposal has been canceled
122 | bool canceled;
123 |
124 | /// @notice Flag marking whether the proposal has been executed
125 | bool executed;
126 |
127 | /// @notice Receipts of ballots for the entire set of voters
128 | mapping (address => Receipt) receipts;
129 | }
130 |
131 | /// @notice Ballot receipt record for a voter
132 | struct Receipt {
133 | /// @notice Whether or not a vote has been cast
134 | bool hasVoted;
135 |
136 | /// @notice Whether or not the voter supports the proposal or abstains
137 | uint8 support;
138 |
139 | /// @notice The number of votes the voter had, which were cast
140 | uint96 votes;
141 | }
142 |
143 | /// @notice Possible states that a proposal may be in
144 | enum ProposalState {
145 | Pending,
146 | Active,
147 | Canceled,
148 | Defeated,
149 | Succeeded,
150 | Queued,
151 | Expired,
152 | Executed
153 | }
154 | }
155 |
156 | interface TimelockInterface {
157 | function delay() external view returns (uint);
158 | function GRACE_PERIOD() external view returns (uint);
159 | function acceptAdmin() external;
160 | function queuedTransactions(bytes32 hash) external view returns (bool);
161 | function queueTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external returns (bytes32);
162 | function cancelTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external;
163 | function executeTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external payable returns (bytes memory);
164 | }
165 |
166 | interface EPNSInterface {
167 | function getPriorVotes(address account, uint blockNumber) external view returns (uint96);
168 | }
169 |
--------------------------------------------------------------------------------
/contracts/governance/PushBravoProxy.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 |
3 | pragma solidity ^0.6.0;
4 |
5 | import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol";
6 |
7 | contract PushBravoProxy is TransparentUpgradeableProxy {
8 |
9 | constructor(
10 | address _logic,
11 | address _admin,
12 | address _timelock,
13 | address _push,
14 | uint _votingPeriod,
15 | uint _votingDelay,
16 | uint _proposalThreshold
17 | ) public payable TransparentUpgradeableProxy(_logic, _admin, abi.encodeWithSignature('initialize(address,address,address,uint,uint,uint)', _admin, _timelock, _push, _votingPeriod, _votingDelay, _proposalThreshold)) {}
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/contracts/governance/Timelock.sol:
--------------------------------------------------------------------------------
1 | /**
2 | *Submitted for verification at Etherscan.io on 2020-09-16
3 | */
4 |
5 | /**
6 | *Submitted for verification at Etherscan.io on 2020-09-14
7 | */
8 |
9 | pragma solidity >=0.6.0 <0.7.0;
10 | // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol
11 | // Subject to the MIT license.
12 |
13 | /**
14 | * @dev Wrappers over Solidity's arithmetic operations with added overflow
15 | * checks.
16 | *
17 | * Arithmetic operations in Solidity wrap on overflow. This can easily result
18 | * in bugs, because programmers usually assume that an overflow raises an
19 | * error, which is the standard behavior in high level programming languages.
20 | * `SafeMath` restores this intuition by reverting the transaction when an
21 | * operation overflows.
22 | *
23 | * Using this library instead of the unchecked operations eliminates an entire
24 | * class of bugs, so it's recommended to use it always.
25 | */
26 | library SafeMath {
27 | /**
28 | * @dev Returns the addition of two unsigned integers, reverting on overflow.
29 | *
30 | * Counterpart to Solidity's `+` operator.
31 | *
32 | * Requirements:
33 | * - Addition cannot overflow.
34 | */
35 | function add(uint256 a, uint256 b) internal pure returns (uint256) {
36 | uint256 c = a + b;
37 | require(c >= a, "SafeMath: addition overflow");
38 |
39 | return c;
40 | }
41 |
42 | /**
43 | * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.
44 | *
45 | * Counterpart to Solidity's `+` operator.
46 | *
47 | * Requirements:
48 | * - Addition cannot overflow.
49 | */
50 | function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
51 | uint256 c = a + b;
52 | require(c >= a, errorMessage);
53 |
54 | return c;
55 | }
56 |
57 | /**
58 | * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
59 | *
60 | * Counterpart to Solidity's `-` operator.
61 | *
62 | * Requirements:
63 | * - Subtraction cannot underflow.
64 | */
65 | function sub(uint256 a, uint256 b) internal pure returns (uint256) {
66 | return sub(a, b, "SafeMath: subtraction underflow");
67 | }
68 |
69 | /**
70 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
71 | *
72 | * Counterpart to Solidity's `-` operator.
73 | *
74 | * Requirements:
75 | * - Subtraction cannot underflow.
76 | */
77 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
78 | require(b <= a, errorMessage);
79 | uint256 c = a - b;
80 |
81 | return c;
82 | }
83 |
84 | /**
85 | * @dev Returns the multiplication of two unsigned integers, reverting on overflow.
86 | *
87 | * Counterpart to Solidity's `*` operator.
88 | *
89 | * Requirements:
90 | * - Multiplication cannot overflow.
91 | */
92 | function mul(uint256 a, uint256 b) internal pure returns (uint256) {
93 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
94 | // benefit is lost if 'b' is also tested.
95 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
96 | if (a == 0) {
97 | return 0;
98 | }
99 |
100 | uint256 c = a * b;
101 | require(c / a == b, "SafeMath: multiplication overflow");
102 |
103 | return c;
104 | }
105 |
106 | /**
107 | * @dev Returns the multiplication of two unsigned integers, reverting on overflow.
108 | *
109 | * Counterpart to Solidity's `*` operator.
110 | *
111 | * Requirements:
112 | * - Multiplication cannot overflow.
113 | */
114 | function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
115 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
116 | // benefit is lost if 'b' is also tested.
117 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
118 | if (a == 0) {
119 | return 0;
120 | }
121 |
122 | uint256 c = a * b;
123 | require(c / a == b, errorMessage);
124 |
125 | return c;
126 | }
127 |
128 | /**
129 | * @dev Returns the integer division of two unsigned integers.
130 | * Reverts on division by zero. The result is rounded towards zero.
131 | *
132 | * Counterpart to Solidity's `/` operator. Note: this function uses a
133 | * `revert` opcode (which leaves remaining gas untouched) while Solidity
134 | * uses an invalid opcode to revert (consuming all remaining gas).
135 | *
136 | * Requirements:
137 | * - The divisor cannot be zero.
138 | */
139 | function div(uint256 a, uint256 b) internal pure returns (uint256) {
140 | return div(a, b, "SafeMath: division by zero");
141 | }
142 |
143 | /**
144 | * @dev Returns the integer division of two unsigned integers.
145 | * Reverts with custom message on division by zero. The result is rounded towards zero.
146 | *
147 | * Counterpart to Solidity's `/` operator. Note: this function uses a
148 | * `revert` opcode (which leaves remaining gas untouched) while Solidity
149 | * uses an invalid opcode to revert (consuming all remaining gas).
150 | *
151 | * Requirements:
152 | * - The divisor cannot be zero.
153 | */
154 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
155 | // Solidity only automatically asserts when dividing by 0
156 | require(b > 0, errorMessage);
157 | uint256 c = a / b;
158 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold
159 |
160 | return c;
161 | }
162 |
163 | /**
164 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
165 | * Reverts when dividing by zero.
166 | *
167 | * Counterpart to Solidity's `%` operator. This function uses a `revert`
168 | * opcode (which leaves remaining gas untouched) while Solidity uses an
169 | * invalid opcode to revert (consuming all remaining gas).
170 | *
171 | * Requirements:
172 | * - The divisor cannot be zero.
173 | */
174 | function mod(uint256 a, uint256 b) internal pure returns (uint256) {
175 | return mod(a, b, "SafeMath: modulo by zero");
176 | }
177 |
178 | /**
179 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
180 | * Reverts with custom message when dividing by zero.
181 | *
182 | * Counterpart to Solidity's `%` operator. This function uses a `revert`
183 | * opcode (which leaves remaining gas untouched) while Solidity uses an
184 | * invalid opcode to revert (consuming all remaining gas).
185 | *
186 | * Requirements:
187 | * - The divisor cannot be zero.
188 | */
189 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
190 | require(b != 0, errorMessage);
191 | return a % b;
192 | }
193 | }
194 |
195 | contract Timelock {
196 | using SafeMath for uint;
197 |
198 | event NewAdmin(address indexed newAdmin);
199 | event NewPendingAdmin(address indexed newPendingAdmin);
200 | event NewDelay(uint indexed newDelay);
201 | event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);
202 | event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);
203 | event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);
204 |
205 | uint public constant GRACE_PERIOD = 14 days;
206 | uint public constant MINIMUM_DELAY = 0 days;
207 | uint public constant MAXIMUM_DELAY = 30 days;
208 |
209 | address public admin;
210 | address public pendingAdmin;
211 | uint public delay;
212 |
213 | mapping (bytes32 => bool) public queuedTransactions;
214 |
215 |
216 | constructor(address admin_, uint delay_) public {
217 | require(delay_ >= MINIMUM_DELAY, "Timelock::constructor: Delay must exceed minimum delay.");
218 | require(delay_ <= MAXIMUM_DELAY, "Timelock::constructor: Delay must not exceed maximum delay.");
219 |
220 | admin = admin_;
221 | delay = delay_;
222 | }
223 |
224 | function setDelay(uint delay_) public {
225 | require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock.");
226 | require(delay_ >= MINIMUM_DELAY, "Timelock::setDelay: Delay must exceed minimum delay.");
227 | require(delay_ <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay.");
228 | delay = delay_;
229 |
230 | emit NewDelay(delay);
231 | }
232 |
233 | function acceptAdmin() public {
234 | require(msg.sender == pendingAdmin, "Timelock::acceptAdmin: Call must come from pendingAdmin.");
235 | admin = msg.sender;
236 | pendingAdmin = address(0);
237 |
238 | emit NewAdmin(msg.sender);
239 | }
240 |
241 | function setPendingAdmin(address pendingAdmin_) public {
242 | require(msg.sender == address(this), "Timelock::setPendingAdmin: Call must come from Timelock.");
243 | pendingAdmin = pendingAdmin_;
244 |
245 | emit NewPendingAdmin(pendingAdmin);
246 | }
247 |
248 | function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {
249 | require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin.");
250 | require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay.");
251 |
252 | bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
253 | queuedTransactions[txHash] = true;
254 |
255 | emit QueueTransaction(txHash, target, value, signature, data, eta);
256 | return txHash;
257 | }
258 |
259 | function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {
260 | require(msg.sender == admin, "Timelock::cancelTransaction: Call must come from admin.");
261 |
262 | bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
263 | queuedTransactions[txHash] = false;
264 |
265 | emit CancelTransaction(txHash, target, value, signature, data, eta);
266 | }
267 |
268 | function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {
269 | require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin.");
270 |
271 | bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));
272 | require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued.");
273 | require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock.");
274 | require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "Timelock::executeTransaction: Transaction is stale.");
275 |
276 | queuedTransactions[txHash] = false;
277 |
278 | bytes memory callData;
279 |
280 | if (bytes(signature).length == 0) {
281 | callData = data;
282 | } else {
283 | callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);
284 | }
285 | // solium-disable-next-line security/no-call-value
286 | (bool success, bytes memory returnData) = target.call.value(value)(callData);
287 | require(success, "Timelock::executeTransaction: Transaction execution reverted.");
288 |
289 | emit ExecuteTransaction(txHash, target, value, signature, data, eta);
290 |
291 | return returnData;
292 | }
293 |
294 | function getBlockTimestamp() internal view returns (uint) {
295 | // solium-disable-next-line security/no-block-members
296 | return block.timestamp;
297 | }
298 | }
299 |
--------------------------------------------------------------------------------
/contracts/governance/VerzionedInitializable.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 |
4 | /**
5 | * @title VersionedInitializable
6 | *
7 | * @dev Helper contract to support initializer functions. To use it, replace
8 | * the constructor with a function that has the `initializer` modifier.
9 | * WARNING: Unlike constructors, initializer functions must be manually
10 | * invoked. This applies both to deploying an Initializable contract, as well
11 | * as extending an Initializable contract via inheritance.
12 | * WARNING: When used with inheritance, manual care must be taken to not invoke
13 | * a parent initializer twice, or ensure that all initializers are idempotent,
14 | * because this is not dealt with automatically as with constructors.
15 | *
16 | * @author Aave, inspired by the OpenZeppelin Initializable contract
17 | */
18 | abstract contract VersionedInitializable {
19 | /**
20 | * @dev Indicates that the contract has been initialized.
21 | */
22 | uint256 private lastInitializedRevision = 0;
23 |
24 | /**
25 | * @dev Indicates that the contract is in the process of being initialized.
26 | */
27 | bool private _initializing;
28 |
29 | /**
30 | * @dev Modifier to use in the initializer function of a contract.
31 | */
32 | modifier initializerV() {
33 | uint256 revision = getRevision();
34 | require(_initializing || isConstructor() || revision > lastInitializedRevision, "Contract instance has already been initialized");
35 |
36 | bool isTopLevelCall = !_initializing;
37 | if (isTopLevelCall) {
38 | _initializing = true;
39 | lastInitializedRevision = revision;
40 | }
41 |
42 | _;
43 |
44 | if (isTopLevelCall) {
45 | _initializing = false;
46 | }
47 | }
48 |
49 | /// @dev returns the revision number of the contract.
50 | /// Needs to be defined in the inherited class as a constant.
51 | function getRevision() virtual internal pure returns(uint256);
52 |
53 |
54 | /// @dev Returns true if and only if the function is running in the constructor
55 | function isConstructor() private view returns (bool) {
56 | // extcodesize checks the size of the code stored in an address, and
57 | // address returns the current address. Since the code is still not
58 | // deployed when running a constructor, any checks on its code size will
59 | // yield zero, making it an effective way to detect if a contract is
60 | // under construction or not.
61 | address self = address(this);
62 | uint256 cs;
63 | //solium-disable-next-line
64 | assembly {
65 | cs := extcodesize(self)
66 | }
67 | return cs == 0;
68 | }
69 |
70 | // Reserved storage space to allow for layout changes in the future.
71 | uint256[50] private ______gap;
72 | }
--------------------------------------------------------------------------------
/contracts/interfaces/IADai.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface IADai {
4 | function redeem(uint256 _amount) external;
5 | function balanceOf(address _user) external view returns(uint256) ;
6 | function principalBalanceOf(address _user) external view returns(uint256);
7 | function getInterestRedirectionAddress(address _user) external view returns(address);
8 | }
9 |
--------------------------------------------------------------------------------
/contracts/interfaces/IEPNSCommV1.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface IEPNSCommV1 {
4 | function subscribeViaCore(address _channel, address _user) external returns(bool);
5 | function unSubscribeViaCore(address _channel, address _user) external returns (bool);
6 | }
7 |
--------------------------------------------------------------------------------
/contracts/interfaces/IERC1271.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity >=0.6.0 <0.7.0;
3 |
4 | /**
5 | * @dev Interface of the ERC1271 standard signature validation method for
6 | * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
7 | */
8 | interface IERC1271 {
9 | /**
10 | * @dev Should return whether the signature provided is valid for the provided data
11 | * @param hash Hash of the data to be signed
12 | * @param signature Signature byte array associated with _data
13 | */
14 | function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);
15 | }
--------------------------------------------------------------------------------
/contracts/interfaces/ILendingPool.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface ILendingPool {
4 | function addressesProvider() external view returns (address);
5 |
6 | function deposit(address _reserve, uint256 _amount, uint16 _referralCode) external payable;
7 |
8 | function redeemUnderlying(address _reserve, address _user, uint256 _amount) external;
9 |
10 | function borrow(address _reserve, uint256 _amount, uint256 _interestRateMode, uint16 _referralCode) external;
11 |
12 | function repay(address _reserve, uint256 _amount, address _onBehalfOf) external payable;
13 |
14 | function swapBorrowRateMode(address _reserve) external;
15 |
16 | function rebalanceFixedBorrowRate(address _reserve, address _user) external;
17 |
18 | function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) external;
19 |
20 | function liquidationCall(address _collateral, address _reserve, address _user, uint256 _purchaseAmount, bool _receiveAToken) external payable;
21 |
22 | function flashLoan(address _receiver, address _reserve, uint256 _amount, bytes calldata _params) external;
23 |
24 | function getReserveConfigurationData(address _reserve) external view returns (uint256 ltv, uint256 liquidationThreshold, uint256 liquidationDiscount, address interestRateStrategyAddress, bool usageAsCollateralEnabled, bool borrowingEnabled, bool fixedBorrowRateEnabled, bool isActive);
25 |
26 | function getReserveData(address _reserve) external view returns (uint256 totalLiquidity, uint256 availableLiquidity, uint256 totalBorrowsFixed, uint256 totalBorrowsVariable, uint256 liquidityRate, uint256 variableBorrowRate, uint256 fixedBorrowRate, uint256 averageFixedBorrowRate, uint256 utilizationRate, uint256 liquidityIndex, uint256 variableBorrowIndex, address aTokenAddress, uint40 lastUpdateTimestamp);
27 |
28 | function getUserAccountData(address _user) external view returns (uint256 totalLiquidityETH, uint256 totalCollateralETH, uint256 totalBorrowsETH, uint256 availableBorrowsETH, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor);
29 |
30 | function getUserReserveData(address _reserve, address _user) external view returns (uint256 currentATokenBalance, uint256 currentUnderlyingBalance, uint256 currentBorrowBalance, uint256 principalBorrowBalance, uint256 borrowRateMode, uint256 borrowRate, uint256 liquidityRate, uint256 originationFee, uint256 variableBorrowIndex, uint256 lastUpdateTimestamp, bool usageAsCollateralEnabled);
31 |
32 | function getReserves() external view;
33 | }
34 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPUSH.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface IPUSH {
4 | function born() external view returns(uint);
5 | function totalSupply() external view returns(uint);
6 | function resetHolderWeight(address holder) external;
7 | function holderWeight(address) external view returns (uint);
8 | function returnHolderUnits(address account, uint atBlock) external view returns (uint);
9 | }
10 |
--------------------------------------------------------------------------------
/contracts/interfaces/IPushCore.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface IPushCore {
4 | function handleChatRequestData(address requestSender, address requestReceiver, uint256 amount) external;
5 | }
6 |
--------------------------------------------------------------------------------
/contracts/interfaces/ITokenBridge.sol:
--------------------------------------------------------------------------------
1 | interface ITokenBridge {
2 |
3 | function completeTransferWithPayload(bytes memory encodedVm) external returns (bytes memory);
4 |
5 | }
--------------------------------------------------------------------------------
/contracts/interfaces/IUniswapV2Router.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface IUniswapV2Router {
4 | function swapExactTokensForTokens(
5 | uint amountIn,
6 | uint amountOutMin,
7 | address[] calldata path,
8 | address to,
9 | uint deadline
10 | ) external returns (uint[] memory amounts);
11 | }
--------------------------------------------------------------------------------
/contracts/mocks/IUniswapV2RouterMock.sol:
--------------------------------------------------------------------------------
1 | pragma solidity >=0.6.0 <0.7.0;
2 |
3 | interface IUniswapV2RouterMock {
4 | function swapExactTokensForTokens(
5 | uint amountIn,
6 | uint amountOutMin,
7 | address[] calldata path,
8 | address to,
9 | uint deadline
10 | ) external returns (uint[] memory amounts);
11 |
12 | function getAmountsOut(uint amountIn, address[] memory path) external view returns (uint[] memory amounts);
13 |
14 | }
--------------------------------------------------------------------------------
/contracts/mocks/MockDai.sol:
--------------------------------------------------------------------------------
1 | /**
2 | *Submitted for verification at Etherscan.io on 2020-02-28
3 | */
4 |
5 | // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
6 |
7 | pragma solidity ^0.6.11;
8 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
9 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
10 | /**
11 | * @title ERC20Mintable
12 | * @dev ERC20 minting logic
13 | */
14 | abstract contract MintableERC20 is ERC20 {
15 | /**
16 | * @dev Function to mint tokens
17 | * @param value The amount of tokens to mint.
18 | * @return A boolean that indicates if the operation was successful.
19 | */
20 | function mint(uint256 value) public returns (bool) {
21 | _mint(msg.sender, value);
22 | return true;
23 | }
24 | }
25 |
26 | contract MockDAI is MintableERC20 {
27 | constructor () ERC20("DAI", "DAI") public {}
28 | }
--------------------------------------------------------------------------------
/contracts/mocks/MockERC1271.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | import "@openzeppelin/contracts/cryptography/ECDSA.sol";
3 | import "hardhat/console.sol";
4 | pragma solidity >=0.6.0 <0.7.0;
5 | pragma experimental ABIEncoderV2;
6 |
7 | contract SignatureVerifier {
8 | using ECDSA for bytes32;
9 |
10 | address public owner;
11 |
12 | constructor() public {
13 | owner = msg.sender;
14 | }
15 |
16 | bytes4 private constant ERC1271_IS_VALID_SIGNATURE =
17 | bytes4(keccak256("isValidSignature(bytes32,bytes)"));
18 |
19 | function supportsStaticCall(bytes4 _methodId)
20 | external
21 | pure
22 | returns (bool _isSupported)
23 | {
24 | return _methodId == ERC1271_IS_VALID_SIGNATURE;
25 | }
26 |
27 | function isValidSignature(bytes32 hash, bytes memory signature)
28 | public
29 | view
30 | returns (bytes4)
31 | {
32 | address recovered_address = hash.recover(signature);
33 | if (recovered_address == owner) return ERC1271_IS_VALID_SIGNATURE;
34 | return bytes4(0);
35 | }
36 | }
--------------------------------------------------------------------------------
/contracts/token/EPNS.args:
--------------------------------------------------------------------------------
1 | ["0xFbA7Df351ADD4E79099f63E33b2679EDFDD5e2aB"]
2 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Repo Setup
4 | ```
5 | git clone https://github.com/ethereum-push-notification-service/push-smart-contracts
6 |
7 | cd push-smart-contracts
8 | ```
9 |
10 | ```
11 | yarn install
12 | ```
13 | ***Note*** -
14 | We are using `yarn` and **strongly** advise to use yarn 1.x to avoid any NPM issues.
15 |
16 | ## Running the Demo React App
17 | We have a `demoreact` playground to test the individual packages being built out. To run the `demoreact` app
18 | ### By GUI (preferred)
19 | 1. click on the `NX console` extension icon in the VSCode sidebar.
20 | 2. click on the `build` target execute icon under `demoreact`
21 | 3. click on the `serve` target execute icon under `demoreact`
22 | 4. wait for the localhost to be ready in the terminal & then hit `http://localhost:4200/` on your browser to run the app.
23 |
24 | ### By CLI
25 | 1. run `yarn nx build demoreact`
26 | 2. run `yarn nx run demoreact:build:production`
27 |
28 | ## Pull Requests process
29 | - All changes should be requested through PRs from a feature/bug branch to `main` branch.
30 | - We are using
31 | - [conventional-commits](https://www.conventionalcommits.org/en/v1.0.0/#summary): to follow [semver](https://semver.org/#summary) for npm package versioning
32 | - [commitizen](https://github.com/commitizen/cz-cli) to restrict commits to follow conventional commits
33 | - [husky](https://typicode.github.io/husky/#/) to run pre-commit checks
34 |
35 | So, use `yarn cz` to commit changes after `git add` (recommended) or hand crafted git commit messages to follow conventional commit. Otherwise the CLI will prevent you from committing code.
36 |
37 | - Before starting on any dev on the repo,
38 | ```bash
39 | # pull latest from main
40 | git pull origin main
41 | git fetch --tags
42 |
43 | # checkout new branch
44 | git checkout -b
45 | ```
46 |
47 | ### How to add commits which will decide versioning when deploying
48 | When you are ready to commit your changes.
49 |
50 | Run
51 | ```
52 | git add -A
53 | ```
54 |
55 | then
56 |
57 | ```
58 | yarn cz
59 | ```
60 |
61 | this will pop up the below CLI
62 |
63 | [](https://github.com/commitizen/cz-cli/raw/master/meta/screenshots/add-commit.png)
64 |
65 | Read through the [conventional-commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) and [semver](https://semver.org/#summary) to get a better understanding for selecting which option.
66 |
67 | ### General guideline
68 | * for bug fixes use `fix`
69 | * for backward compatible new features use `feat`
70 |
71 | ## NX
72 | We are using [NX](https://nx.dev/getting-started/intro) and some NX plugins for monorepo management, verison & publish.
73 |
74 | ### NX console
75 | The repo comes in with a baked in NX console and some other VSCode extensions to -
76 | * help simplify processes like build, lint, test, run demo apps
77 | * run scripts on affected parts of the codebase
78 |
79 | ***Note*** -
80 | Don't run CI-prefixed targets in the NX console in local, they are only for CI..
81 |
82 | ## Adding new packages
83 | The NX monorepo uses `project.json` & `package.json` to manage the monorepo workspace and also ultimately build out the bundle that will be published to NPM registry.
84 |
85 | ### - adding `dependencies` to a package
86 | at root, simply run
87 | ```
88 | yarn add "dependency_package_name@x.y.z"
89 | ```
90 | And then simply import that dependency in your package. NX while running `build` for that package will take care of making it a `dependency` in the final bundle.
91 |
92 | ### - adding `devDependencies` to a package
93 | at root, simply run
94 | ```
95 | yarn add -D "dependency_package_name@x.y.z"
96 | ```
97 | And then simply import that dependency in your package. NX while running `build` for that package will take care of making it a `devDependency` in the final bundle.
98 |
99 | ### - adding `peerDependencies` to a package
100 | at root, simply run
101 | ```
102 | yarn add "dependency_package_name@x.y.z"
103 | ```
104 | And then simply import that dependency in your package. In the `package.json` of the package where you want to consume it, simply declare the dependency as `peerDependency`
105 | NX while running `build` for that package will take care of making it a `peerDependency` in the final bundle.
106 |
--------------------------------------------------------------------------------
/foundry.toml:
--------------------------------------------------------------------------------
1 | # General Configs
2 | [profile.default]
3 | src = 'contracts'
4 | out = 'out'
5 | libs = ['node_modules', 'lib'] # Includes node_modules too for any previous imports with npm
6 | test = 'testFoundry' # "testFoundry" -> foundry test only while "test" -> js test files
7 | cache_path = 'cache_forge'
8 |
9 | # Solidity & EVM Specific Configs
10 | solc = "0.6.11"
11 | optimizer = true
12 | optimizer_runs = 99999
13 | auto_detect_solc = false
14 | emv_version = "paris"
15 |
16 |
17 | # Test Specific Configs
18 | verbosity = 2
19 | gas_reports = [" "]
20 | sender = "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38"
21 |
22 |
23 | # Formatter Specific Configs
24 | [fmt]
25 | bracket_spacing = true
26 | int_types = "long"
27 | line_length = 120
28 | multiline_func_header = "all"
29 | number_underscore = "thousands"
30 | quote_style = "double"
31 | tab_width = 4
32 | wrap_comments = true
33 |
34 | # RPC & Etherscan Config Keys
35 | [etherscan]
36 | arbitrum_one = { key = "${process.env.ARBISCAN_API}" }
37 | bnb_smart_chain = { key = "${process.env.BNBSCAN_API}" }
38 | goerli = { key = "${process.env.ETHERSCAN_API}" }
39 | mainnet = { key = "${process.env.ETHERSCAN_API}" }
40 | optimism = { key = "${process.env.OPTIMISM_API}" }
41 | polygon = { key = "${process.env.POLYGONSCAN_API}" }
42 | sepolia = { key = "${process.env.ETHERSCAN_API}" }
43 |
44 | [rpc_endpoints]
45 | localhost = "http://localhost:8545"
46 |
47 | #ETH Networks
48 | mainnet = "https://mainnet.infura.io/v3/${process.env.INFURA_PROJECT_ID}"
49 | goerli = "https://goerli.infura.io/v3/${process.env.INFURA_PROJECT_ID}"
50 | sepolia = "https://sepolia.infura.io/v3/${process.env.INFURA_PROJECT_ID}"
51 |
52 | # Polygon Networks
53 | polygon = "https://polygon-rpc.com/"
54 | polygonMumbai = "https://rpc-mumbai.maticvigil.com/"
55 |
56 | #BNB Networks
57 | bnb_smart_chain = "https://bsc-dataseed.binance.org"
58 | bnb_testnet = "https://data-seed-prebsc-1-s1.binance.org:8545/"
59 |
60 | #Optimism Networks
61 | optimism = "https://mainnet.optimism.io"
62 | optimismSepolia = "https://sepolia.optimism.io"
63 |
64 | #zkEVM Networks
65 | zkEVMMainnet = "https://zkevm-rpc.com"
66 | polygonZkEVMTestnet = "https://rpc.public.zkevm-test.net"
--------------------------------------------------------------------------------
/license-v1:
--------------------------------------------------------------------------------
1 | Business Source License 1.1
2 |
3 | License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
4 | "Business Source License" is a trademark of MariaDB Corporation Ab.
5 |
6 | -----------------------------------------------------------------------------
7 |
8 | Parameters
9 |
10 | Licensor: Push Org
11 |
12 | Licensed Work: Push Protocol
13 | The Licensed Work is (c) 2022 ETHEREUM PUSH NOTIFICATION SERVICE LIMITED
14 |
15 | Additional Use Grant: Any uses listed and defined by Push Org
16 |
17 | Change Date: 2023-11-11
18 |
19 | Change License: GNU General Public License v2.0 or later
20 |
21 | -----------------------------------------------------------------------------
22 |
23 | Terms
24 |
25 | The Licensor hereby grants you the right to copy, modify, create derivative
26 | works, redistribute, and make non-production use of the Licensed Work. The
27 | Licensor may make an Additional Use Grant, above, permitting limited
28 | production use.
29 |
30 | Effective on the Change Date, or the fourth anniversary of the first publicly
31 | available distribution of a specific version of the Licensed Work under this
32 | License, whichever comes first, the Licensor hereby grants you rights under
33 | the terms of the Change License, and the rights granted in the paragraph
34 | above terminate.
35 |
36 | If your use of the Licensed Work does not comply with the requirements
37 | currently in effect as described in this License, you must purchase a
38 | commercial license from the Licensor, its affiliated entities, or authorized
39 | resellers, or you must refrain from using the Licensed Work.
40 |
41 | All copies of the original and modified Licensed Work, and derivative works
42 | of the Licensed Work, are subject to this License. This License applies
43 | separately for each version of the Licensed Work and the Change Date may vary
44 | for each version of the Licensed Work released by Licensor.
45 |
46 | You must conspicuously display this License on each original or modified copy
47 | of the Licensed Work. If you receive the Licensed Work in original or
48 | modified form from a third party, the terms and conditions set forth in this
49 | License apply to your use of that work.
50 |
51 | Any use of the Licensed Work in violation of this License will automatically
52 | terminate your rights under this License for the current and all other
53 | versions of the Licensed Work.
54 |
55 | This License does not grant you any right in any trademark or logo of
56 | Licensor or its affiliates (provided that you may use a trademark or logo of
57 | Licensor as expressly required by this License).
58 |
59 | TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
60 | AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
61 | EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
62 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
63 | TITLE.
64 |
65 | MariaDB hereby grants you permission to use this License’s text to license
66 | your works, and to refer to it using the trademark "Business Source License",
67 | as long as you comply with the Covenants of Licensor below.
68 |
69 | -----------------------------------------------------------------------------
70 |
71 | Covenants of Licensor
72 |
73 | In consideration of the right to use this License’s text and the "Business
74 | Source License" name and trademark, Licensor covenants to MariaDB, and to all
75 | other recipients of the licensed work to be provided by Licensor:
76 |
77 | 1. To specify as the Change License the GPL Version 2.0 or any later version,
78 | or a license that is compatible with GPL Version 2.0 or a later version,
79 | where "compatible" means that software provided under the Change License can
80 | be included in a program with software provided under GPL Version 2.0 or a
81 | later version. Licensor may specify additional Change Licenses without
82 | limitation.
83 |
84 | 2. To either: (a) specify an additional grant of rights to use that does not
85 | impose any additional restriction on the right granted in this License, as
86 | the Additional Use Grant; or (b) insert the text "None".
87 |
88 | 3. To specify a Change Date.
89 |
90 | 4. Not to modify this License in any other way.
91 |
92 | -----------------------------------------------------------------------------
93 |
94 | Notice
95 |
96 | The Business Source License (this document, or the "License") is not an Open
97 | Source license. However, the Licensed Work will eventually be made available
98 | under an Open Source License, as stated in this License.
99 |
--------------------------------------------------------------------------------
/loaders/envVerifier.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk');
2 |
3 | module.exports = async (failOnNoVerification) => {
4 | if (!failOnNoVerification) console.log(chalk.green('✌️ Verifying ENV'));
5 | try {
6 | // Load FS and Other dependency
7 | const fs = require('fs');
8 | const envfile = require('envfile');
9 | const readline = require('readline');
10 |
11 | var fileModified = false;
12 |
13 | // Load environment files
14 | const envpath = `${__dirname}/../.env`;
15 | const envsamplepath = `${__dirname}/../.env.sample`;
16 |
17 | // First check and create .env if it doesn't exists
18 | if (!fs.existsSync(envpath)) {
19 | if (!failOnNoVerification) console.log(chalk.green('-- Checking for ENV File... Not Found'));
20 | fs.writeFileSync(envpath, '', { flag: 'wx' });
21 | if (!failOnNoVerification) console.log(chalk.green(' -- ENV File Generated'));
22 | }
23 | else {
24 | if (!failOnNoVerification) console.log(chalk.green(' -- Checking for ENV File... Found'));
25 | }
26 |
27 | // Now Load the environment
28 | const envData = fs.readFileSync(envpath, 'utf8');
29 | const envObject = envfile.parse(envData);
30 |
31 | const envSampleData = fs.readFileSync(envsamplepath, 'utf8');
32 | const envSampleObject = envfile.parse(envSampleData);
33 |
34 | const readIntSampleENV = readline.createInterface({
35 | input: fs.createReadStream(envsamplepath),
36 | output: false,
37 | });
38 |
39 | let realENVContents = '';
40 | if (!failOnNoVerification) console.log(chalk.green(' -- Verifying and building ENV File...'));
41 |
42 | for await (const line of readIntSampleENV) {
43 | let moddedLine = line;
44 |
45 | // Check if line is comment or environment variable
46 | if (moddedLine.startsWith('#') || moddedLine.startsWith('\n') || moddedLine.trim().length == 0) {
47 | // do nothing, just include it in the line
48 | // console.log("----");
49 | }
50 | else {
51 | // This is an environtment variable, first segregate the comment if any and the variable info
52 | const delimiter = "#";
53 |
54 | const index = moddedLine.indexOf('#');
55 | const splits = index == -1 ? [moddedLine.slice(0, index), ''] : [moddedLine.slice(0, index), ' ' + delimiter + moddedLine.slice(index + 1)]
56 |
57 | const envVar = splits[0].split('=')[0]; // Get environment variable by splitting the sample and then taking first seperation
58 | const comment = splits[1];
59 |
60 | // Check if envVar exists in real env, if not ask for val
61 | // console.log(envObject[`${envVar}`])
62 | if (!envObject[`${envVar}`] || envObject[`${envVar}`].trim() == '') {
63 | if (failOnNoVerification) {
64 | console.log('🔥 ', chalk.underline.red(`Failed Verification of ENV! Please first run:`), chalk.bgWhite.black(' npm start '));
65 | process.exit(1);
66 | }
67 |
68 | // env key doesn't exist, ask for input
69 | if (!failOnNoVerification) console.log(chalk.bgWhite.black(` Enter ENV Variable Value --> ${envVar}`));
70 |
71 | var value = '';
72 |
73 | while (value.trim().length == 0) {
74 | const rl = readline.createInterface({
75 | input: process.stdin,
76 | output: null,
77 | });
78 | value = await doSyncPrompt(rl, `${envSampleObject[envVar]} >`);
79 |
80 | if (value.trim().length == 0) {
81 | if (!failOnNoVerification) console.log(chalk.red(" Incorrect Entry, Field can't be empty"));
82 | }
83 | }
84 |
85 | if (!failOnNoVerification) console.log(chalk.dim(` [Saved] `), chalk.bgWhite.black(` ${envVar}=${value} `));
86 | moddedLine = `${envVar}=${value}${comment}`;
87 |
88 | fileModified = true;
89 | }
90 | else {
91 | // Value exists so just replicate
92 | moddedLine = `${envVar}=${envObject[envVar]}${comment}`;
93 | }
94 | }
95 |
96 | // finally append the line
97 | realENVContents = `${realENVContents}\n${moddedLine}`;
98 | }
99 |
100 | if (fileModified) {
101 | if (!failOnNoVerification) console.log(chalk.green(' -- new ENV file generated, saving'));
102 | fs.writeFileSync(envpath, realENVContents, { flag: 'w' });
103 | if (!failOnNoVerification) console.log(chalk.green(' -- ENV file saved!'));
104 | }
105 | else {
106 | if (!failOnNoVerification) console.log(chalk.green(' -- ENV file verified!'));
107 | }
108 |
109 |
110 | if (!failOnNoVerification) console.log(chalk.green('✔️ ENV Verified / Generated and Loaded!'));
111 | return null;
112 | } catch (e) {
113 | console.log(chalk.red('🔥 Error on env verifier loader: %o', e));
114 | throw e;
115 | }
116 |
117 | // Leverages Node.js' awesome async/await functionality
118 | async function doSyncPrompt(rl, message) {
119 | var promptInput = await readLineAsync(rl, message);
120 | rl.close();
121 |
122 | return promptInput;
123 | }
124 |
125 | function readLineAsync(rl, message) {
126 | return new Promise((resolve, reject) => {
127 | rl.question(message, (answer) => {
128 | resolve(answer.trim());
129 | });
130 | });
131 | }
132 | };
133 |
--------------------------------------------------------------------------------
/loaders/tokenAmountVerifier.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk');
2 | const { bn } = require('../helpers/utils');
3 | const { DISTRIBUTION_INFO } = require('../scripts/constants/constants')
4 |
5 | let totalAmount = bn(0);
6 |
7 | function getTokens(obj){
8 | if(typeof(obj) == 'string') {
9 | const objBn = bn(obj)
10 | totalAmount = totalAmount.add(objBn)
11 | return obj;
12 | }
13 | for (const [key, value] of Object.entries(obj)) {
14 | if(key == 'total'){
15 | continue;
16 | }
17 | getTokens(value);
18 | }
19 | }
20 |
21 | function verifyTokensAmount(upgradeVersion, paramatersToVerify) {
22 | if(Object.entries(DISTRIBUTION_INFO).length > 0){
23 | let expectedTotalAmount = DISTRIBUTION_INFO.total;
24 |
25 | getTokens(DISTRIBUTION_INFO)
26 |
27 | if(totalAmount != expectedTotalAmount) {
28 | console.log('🔥 ', chalk.underline.red(`Total Amount and breakdown doesn't match`), chalk.bgWhite.black(` ${expectedTotalAmount} != ${totalAmount} `), chalk(` Please fix to continue! \n`))
29 | process.exit(1)
30 | }
31 |
32 | console.log(chalk.grey(` Total amount is equal to breakdown sum`), chalk.green.bold(`${expectedTotalAmount}`), chalk(`==`), chalk.green.bold(`${totalAmount}\n`))
33 | }
34 | }
35 |
36 | module.exports = {
37 | verifyTokensAmount: verifyTokensAmount
38 | }
39 |
--------------------------------------------------------------------------------
/loaders/versionVerifier.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 |
3 | const chalk = require('chalk')
4 | const path = require('path')
5 | const fs = require('fs')
6 |
7 | function versionVerifier(paramatersToVerify) {
8 | return versionControl(false, paramatersToVerify)
9 | }
10 |
11 | function upgradeVersion(paramatersToVerify) {
12 | return versionControl(true, paramatersToVerify)
13 | }
14 |
15 | function versionControl(upgradeVersion, paramatersToVerify) {
16 | // Get actual coEPNSnfig
17 | const configMeta = getConfigMeta(false) // true for version history
18 |
19 | // check if file exists
20 | if (!fs.existsSync(configMeta.configFileAbs)) {
21 | console.log('🔥 ', chalk.underline.red(`Failed Version Verification! Please first create:`), chalk.bgWhite.black(` ${configMeta.configFile} `), chalk(` in `), chalk.bgWhite.grey(` ${configMeta.configFileAbs}`))
22 | process.exit(1)
23 | }
24 |
25 | // check first to ensure file exists
26 | let config = require(configMeta.configFileAbs)
27 |
28 | // Get config history
29 | const configHistoryMeta = getConfigMeta(true) // true for version history
30 |
31 | // Check if version is found
32 | if (configHistoryMeta.versioningFound) {
33 | // Version history exists, check for current version > version deploy
34 | const configHistory = require(configHistoryMeta.configFileAbs)
35 |
36 | if (configHistory.deploy.history.version >= config.deploy.network[`${hre.network.name}`].version) {
37 | console.log('🔥 ', chalk.underline.red(`Failed Version Verification! Version of `), chalk.bgWhite.black(` ${configHistoryMeta.configFileRel} `), chalk(` version: `), chalk.red(`${configHistory.deploy.history.version}`), chalk(` vs source file version: `), chalk.green(`${config.deploy.network[`${hre.network.name}`].version}`))
38 | console.log('🔥 ', chalk.underline.red(`Please upgrade args and version of `), chalk.bgWhite.black(` ${configMeta.configFileRel} `), chalk(` to continue! \n`))
39 | process.exit(1)
40 | }
41 | }
42 |
43 | // Check for arguments in main config
44 | if (Object.keys(config.deploy.args).length > 0) {
45 | // Check if each key is present in parameters to verify
46 | for (const [key, value] of Object.entries(config.deploy.args)) {
47 | if (!value) {
48 | console.log('🔥 ', chalk.underline.red(`Arguments are undefined in`), chalk.bgWhite.black(` ${configMeta.configFile} -> deploy:args:${key} `), chalk(` Please fix to continue! \n`))
49 | process.exit(1)
50 | }
51 | }
52 | }
53 |
54 | // Check for arguments in params verifier
55 | if (paramatersToVerify && paramatersToVerify.length > 0) {
56 | paramatersToVerify.forEach((item) => {
57 | if (!(item in config.deploy.args)) {
58 | console.log('🔥 ', chalk.underline.red(`Parameters passed for verification not found in`), chalk.bgWhite.black(` ${configMeta.configFile} -> deploy:args:${item} `), chalk(` Please fix to continue! \n`))
59 | process.exit(1)
60 | }
61 | })
62 | }
63 |
64 |
65 | // so far so good, check if upgradeVersion flag is there, if so, overwrite the file with config
66 | if (upgradeVersion) {
67 | let json = {}
68 | json.args = config.deploy.args
69 | json.history = config.deploy.network[`${hre.network.name}`]
70 |
71 | // Write file
72 | const content = `const deploy = ${JSON.stringify(json, null, 2)}\n\nexports.deploy = deploy`
73 | const unquoted = content.replace(/"([^"]+)":/g, '$1:')
74 |
75 | fs.writeFileSync(configHistoryMeta.configFileAbs, unquoted)
76 |
77 | // Reset arguments of main config
78 | let modConfig = {
79 | network: config.deploy.network,
80 | args: config.deploy.args
81 | }
82 |
83 | for (const [key, value] of Object.entries(modConfig.args)) {
84 | modConfig.args[key] = null
85 | }
86 | const modContent = `const deploy = ${JSON.stringify(modConfig, null, 2)}\n\nexports.deploy = deploy`
87 | const modUnquoted = modContent.replace(/"([^"]+)":/g, '$1:')
88 |
89 | fs.writeFileSync(configMeta.configFileAbs, modUnquoted)
90 |
91 | console.log(chalk.grey(` Upgraded Version to `), chalk.green.bold(` ${config.deploy.network[`${hre.network.name}`].version}`), chalk(`for`), chalk.green.bold(`${hre.network.name}\n`))
92 | }
93 |
94 | config.version = config.deploy.network[`${hre.network.name}`].version
95 | return config
96 | }
97 |
98 | // private
99 | function getConfigMeta(forVersionHistory) {
100 | let configMeta = {}
101 |
102 | const absPath = _getCallerFile()
103 | const deployFile = path.basename(absPath)
104 | const configFile = forVersionHistory ? deployFile.slice(0, -3) + ".version.js" : deployFile.slice(0, -3) + ".config.js"
105 |
106 | let versioningFilePath = ''
107 | if (forVersionHistory) {
108 | console.log(process.env.FS_ARTIFCATS, process.env.FS_VERSIONING_INFO)
109 | const deploymentPath = path.join(process.env.FS_ARTIFCATS, process.env.FS_VERSIONING_INFO)
110 | const networkPath = path.join(deploymentPath, hre.network.name)
111 | versioningFilePath = path.join(networkPath, configFile)
112 |
113 | if (!fs.existsSync(deploymentPath)) {
114 | fs.mkdirSync(deploymentPath)
115 | }
116 |
117 | if (!fs.existsSync(networkPath)) {
118 | fs.mkdirSync(networkPath)
119 | }
120 |
121 | if (fs.existsSync(versioningFilePath)) {
122 | configMeta.versioningFound = true
123 | }
124 | }
125 | const configFileRel = forVersionHistory ? `../${versioningFilePath}` : `../scripts/versioncontrol/${configFile}`
126 |
127 | configMeta.deployFile = deployFile
128 | configMeta.configFile = configFile
129 | configMeta.configFileRel = configFileRel
130 | configMeta.configFileAbs = `${__dirname}/${configFileRel}`
131 | return configMeta
132 | }
133 |
134 | function _getCallerFile() {
135 | try {
136 | var err = new Error();
137 | var callerfile;
138 | var currentfile;
139 |
140 | Error.prepareStackTrace = function (err, stack) { return stack; };
141 |
142 | currentfile = err.stack.shift().getFileName();
143 |
144 | while (err.stack.length) {
145 | callerfile = err.stack.shift().getFileName();
146 |
147 | if(currentfile !== callerfile) return callerfile;
148 | }
149 | } catch (err) {}
150 | return undefined;
151 | }
152 |
153 | module.exports = {
154 | versionVerifier: versionVerifier,
155 | upgradeVersion: upgradeVersion
156 | }
157 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "epns-protocol-staging",
3 | "version": "1.0.0",
4 | "description": "Staging Smart Contracts of EPNS Protocol",
5 | "main": "app.js",
6 | "author": "Ethereum Push Notification Service",
7 | "license": "ISC",
8 | "bugs": {
9 | "url": "https://github.com/ethereum-push-notification-service/epns-protocol-staging/issues"
10 | },
11 | "homepage": "https://github.com/ethereum-push-notification-service/epns-protocol-staging#readme",
12 | "scripts": {
13 | "start": "node app.js",
14 | "chain": "hardhat node --network hardhat",
15 | "test": "hardhat test --network hardhat",
16 | "compile": "hardhat compile",
17 | "deploy": "hardhat run scripts/deploy.js && hardhat run scripts/publish.js",
18 | "watch": "node scripts/watch.js",
19 | "accounts": "hardhat accounts",
20 | "balance": "hardhat balance",
21 | "send": "hardhat send"
22 | },
23 | "dependencies": {
24 | "@nomiclabs/hardhat-ethers": "^2.0.2",
25 | "@nomiclabs/hardhat-waffle": "^2.0.6",
26 | "@openzeppelin/contracts": "3.4.0",
27 | "@openzeppelin/contracts-upgradeable": "3.4.0",
28 | "bip39": "3.0.3",
29 | "chai": "^4.3.4",
30 | "chalk": "^4.1.1",
31 | "dotenv": "10.0.0",
32 | "eip-712": "0.4.2",
33 | "envfile": "6.14.0",
34 | "ethereum-waffle": "^4.0.10",
35 | "ethereumjs-wallet": "1.0.1",
36 | "ethers": "^5.1.4",
37 | "hardhat": "^2.12.6",
38 | "hardhat-gas-reporter": "^1.0.4",
39 | "node-watch": "^0.7.1",
40 | "solidity-bytes-utils": "^0.8.2"
41 | },
42 | "devDependencies": {
43 | "@nomicfoundation/hardhat-verify": "^2.0.4",
44 | "hardhat-contract-sizer": "^2.8.0",
45 | "moment": "^2.29.1",
46 | "prettier": "^2.3.2",
47 | "prettier-plugin-solidity": "^1.0.0-beta.17"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/scripts/0_deploySample.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const EPNSCoreV5 = await deployContract("EPNSCoreV5", [], "EPNSCoreV5");
40 | deployedContracts.push(EPNSCoreV5)
41 |
42 | const EPNSProxy = await ethers.getContractFactory("EPNSProxy")
43 | const epnsProxyInstance = EPNSProxy.attach(versionDetails.deploy.args.epnsProxyAddress)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${EPNSCoreV5.address} \n\t\t\t\n`))
46 | await epnsProxyInstance.upgradeTo(EPNSCoreV5.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`));
48 |
49 | // const EPNSCoreV5P = EPNSCoreV5.attach(epnsProxyInstance.address)
50 | // console.log((await EPNSCoreV5P.connect(aliceSigner).getNumber()).toString())
51 |
52 | return deployedContracts
53 | }
54 |
55 | main()
56 | .then(() => process.exit(0))
57 | .catch((error) => {
58 | console.error(error);
59 | process.exit(1);
60 | });
61 |
--------------------------------------------------------------------------------
/scripts/1_5_deployEPNSCoreV1_5.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress", "epnsCoreAdmin"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const EPNSCoreV1_5 = await deployContract("EPNSCoreV1_5", [], "EPNSCoreV1_5");
40 | deployedContracts.push(EPNSCoreV1_5)
41 |
42 | const EPNSCoreAdmin = await ethers.getContractFactory("EPNSCoreAdmin")
43 | const EPNSCoreAdminInstance = EPNSCoreAdmin.attach(versionDetails.deploy.args.epnsCoreAdmin)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${EPNSCoreV1_5.address} \n\t\t\t\n`))
46 | await EPNSCoreAdminInstance.upgrade(versionDetails.deploy.args.epnsProxyAddress, EPNSCoreV1_5.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`))
48 |
49 | return deployedContracts
50 | }
51 |
52 | main()
53 | .then(() => process.exit(0))
54 | .catch((error) => {
55 | console.error(error);
56 | process.exit(1);
57 | });
58 |
--------------------------------------------------------------------------------
/scripts/1_deployEPNSCoreV1.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 |
3 | const moment = require('moment')
4 | const hre = require("hardhat")
5 |
6 | const fs = require("fs")
7 | const chalk = require("chalk")
8 | const { config, ethers } = require("hardhat")
9 |
10 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
11 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
12 |
13 | async function main() {
14 | // Version Check
15 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
16 | const versionDetails = versionVerifier(["daiAddress", "aDaiAddress", "wethAddress", "pushAddress", "uniswapRouterAddress", "aaveLendingAddress", "referralCode"])
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
18 |
19 | // First deploy all contracts
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
21 | const deployedContracts = await setupAllContracts(versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
23 |
24 | // Try to verify
25 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
26 | await verifyAllContracts(deployedContracts, versionDetails)
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
28 |
29 | // Upgrade Version
30 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
31 | upgradeVersion()
32 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
33 | }
34 |
35 | // IMOORTANT: ADD THIS FROM CONFIG
36 | // const DAI = "0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108";
37 | // const ADAI = "0xcB1Fe6F440c49E9290c3eb7f158534c2dC374201";
38 | // const WETH = "0xc778417E063141139Fce010982780140Aa0cD5Ab";
39 | // const PUSH = "0xf418588522d5dd018b425E472991E52EBBeEEEEE";
40 | // const UNISWAP_ROUTER = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
41 | // const AAVE_LENDING_POOL = "0x1c8756FD2B28e9426CDBDcC7E3c4d64fa9A54728";
42 | // const referralCode = "0";
43 |
44 | async function setupAllContracts(versionDetails) {
45 | let deployedContracts = []
46 | console.log("📡 Deploy \n");
47 |
48 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
49 | // await autoDeploy();
50 | // OR
51 | // custom deploy (to use deployed addresses dynamically for example:)
52 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
53 |
54 | // const admin = '0xA1bFBd2062f298a46f3E4160C89BEDa0716a3F51'; //admin of timelock, gets handed over to the governor.
55 |
56 | const delay = 0; // uint for the timelock delay
57 |
58 | // const epns = await deploy("EPNS");
59 | // const epns = await deployContract("EPNS", [], "EPNS");
60 | // deployedContracts.push(epns)
61 | const EPNSCoreV1 = await deployContract("EPNSCoreV1", [], "EPNSCoreV1");
62 | deployedContracts.push(EPNSCoreV1)
63 |
64 | const EPNSCoreAdmin = await deployContract("EPNSCoreAdmin", [], "EPNSCoreAdmin");
65 | deployedContracts.push(EPNSCoreAdmin)
66 |
67 | // const timelock = await deployContract("Timelock", [adminSigner.address, delay], "Timelock"); // governor and a guardian,
68 | // deployedContracts.push(timelock)
69 |
70 | // const governorAlpha = await deployContract("GovernorAlpha", [
71 | // timelock.address,
72 | // epns.address,
73 | // adminSigner.address
74 | // ]
75 | // , "GovernorAlpha");
76 | // deployedContracts.push(governorAlpha)
77 |
78 | // const currBlock = await ethers.provider.getBlock('latest');
79 |
80 | // const eta = currBlock.timestamp;
81 | // const coder = new ethers.utils.AbiCoder();
82 |
83 | // let data = coder.encode(['address'], [governorAlpha.address]);
84 |
85 | // await timelock.functions.queueTransaction(timelock.address, '0', 'setPendingAdmin(address)', data, (eta + 1));
86 | // await ethers.provider.send('evm_mine');
87 | // await ethers.provider.send('evm_mine');
88 | // await timelock.functions.executeTransaction(timelock.address, '0', 'setPendingAdmin(address)', data, (eta + 1));
89 |
90 | const EPNSCoreProxy = await deployContract("EPNSCoreProxy", [
91 | EPNSCoreV1.address,
92 | EPNSCoreAdmin.address,
93 | adminSigner.address,
94 | versionDetails.deploy.args.pushAddress,
95 | versionDetails.deploy.args.wethAddress,
96 | versionDetails.deploy.args.uniswapRouterAddress,
97 | versionDetails.deploy.args.aaveLendingAddress,
98 | versionDetails.deploy.args.daiAddress,
99 | versionDetails.deploy.args.aDaiAddress,
100 | parseInt(versionDetails.deploy.args.referralCode),
101 | ], "EPNSCoreProxy");
102 |
103 | deployedContracts.push(EPNSCoreProxy)
104 |
105 | return deployedContracts
106 | }
107 |
108 | main()
109 | .then(() => process.exit(0))
110 | .catch((error) => {
111 | console.error(error);
112 | process.exit(1);
113 | });
114 |
--------------------------------------------------------------------------------
/scripts/2_5_deployEPNSCommV1_5.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress", "epnsCommAdmin"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const PushCommV2 = await deployContract("PushCommV2", [], "PushCommV2");
40 | deployedContracts.push(PushCommV2)
41 |
42 | const EPNSCommAdmin = await ethers.getContractFactory("EPNSCommAdmin")
43 | const epnsAdminInstance = EPNSCommAdmin.attach(versionDetails.deploy.args.epnsCommAdmin)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${PushCommV2.address} \n\t\t\t\n`))
46 | await epnsAdminInstance.upgrade(versionDetails.deploy.args.epnsProxyAddress, PushCommV2.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`))
48 |
49 | return deployedContracts
50 | }
51 |
52 | main()
53 | .then(() => process.exit(0))
54 | .catch((error) => {
55 | console.error(error);
56 | process.exit(1);
57 | });
58 |
--------------------------------------------------------------------------------
/scripts/2_deployEPNSCommV1.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["chainName"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | // IMOORTANT: ADD THIS FROM CONFIG
31 | // const DAI = "0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108";
32 | // const ADAI = "0xcB1Fe6F440c49E9290c3eb7f158534c2dC374201";
33 | // const WETH = "0xc778417E063141139Fce010982780140Aa0cD5Ab";
34 | // const PUSH = "0xf418588522d5dd018b425E472991E52EBBeEEEEE";
35 | // const UNISWAP_ROUTER = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
36 | // const AAVE_LENDING_POOL = "0x1c8756FD2B28e9426CDBDcC7E3c4d64fa9A54728";
37 | // const referralCode = "0";
38 |
39 | async function setupAllContracts(versionDetails) {
40 | let deployedContracts = []
41 | console.log("📡 Deploy \n");
42 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
43 | // await autoDeploy();
44 | // OR
45 | // custom deploy (to use deployed addresses dynamically for example:)
46 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
47 |
48 | // const admin = '0xA1bFBd2062f298a46f3E4160C89BEDa0716a3F51'; //admin of timelock, gets handed over to the governor.
49 |
50 | const delay = 0; // uint for the timelock delay
51 |
52 | // const epns = await deploy("EPNS");
53 | // const epns = await deployContract("EPNS", [], "EPNS");
54 | // deployedContracts.push(epns)
55 |
56 | const EPNSCommV1 = await deployContract("PushCommV2", [], "PushCommV2");
57 | deployedContracts.push(EPNSCommV1)
58 |
59 | const EPNSCommAdmin = await deployContract("EPNSCommAdmin", [], "EPNSCommAdmin");
60 | deployedContracts.push(EPNSCommAdmin)
61 | // const timelock = await deployContract("Timelock", [adminSigner.address, delay], "Timelock"); // governor and a guardian,
62 | // deployedContracts.push(timelock)
63 |
64 | // const governorAlpha = await deployContract("GovernorAlpha", [
65 | // timelock.address,
66 | // epns.address,
67 | // adminSigner.address
68 | // ]
69 | // , "GovernorAlpha");
70 | // deployedContracts.push(governorAlpha)
71 |
72 | // const currBlock = await ethers.provider.getBlock('latest');
73 |
74 | // const eta = currBlock.timestamp;
75 | // const coder = new ethers.utils.AbiCoder();
76 |
77 | // let data = coder.encode(['address'], [governorAlpha.address]);
78 |
79 | // await timelock.functions.queueTransaction(timelock.address, '0', 'setPendingAdmin(address)', data, (eta + 1));
80 | // await ethers.provider.send('evm_mine');
81 | // await ethers.provider.send('evm_mine');
82 | // await timelock.functions.executeTransaction(timelock.address, '0', 'setPendingAdmin(address)', data, (eta + 1));
83 |
84 | const EPNSCommProxy = await deployContract("EPNSCommProxy", [
85 | EPNSCommV1.address,
86 | EPNSCommAdmin.address,
87 | adminSigner.address,
88 | versionDetails.deploy.args.chainName,
89 | ], "EPNSCommProxy");
90 |
91 | deployedContracts.push(EPNSCommProxy)
92 |
93 | return deployedContracts
94 | }
95 |
96 | main()
97 | .then(() => process.exit(0))
98 | .catch((error) => {
99 | console.error(error);
100 | process.exit(1);
101 | });
102 |
--------------------------------------------------------------------------------
/scripts/3_deployEPNSCoreV2.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress", "epnsCoreAdmin"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const PushCoreV2 = await deployContract("PushCoreV2", [], "PushCoreV2");
40 | deployedContracts.push(PushCoreV2)
41 |
42 | const EPNSCoreAdmin = await ethers.getContractFactory("EPNSCoreAdmin")
43 | const EPNSCoreAdminInstance = EPNSCoreAdmin.attach(versionDetails.deploy.args.epnsCoreAdmin)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${PushCoreV2.address} \n\t\t\t\n`))
46 | await EPNSCoreAdminInstance.upgrade(versionDetails.deploy.args.epnsProxyAddress, PushCoreV2.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`))
48 |
49 | return deployedContracts
50 | }
51 |
52 | main()
53 | .then(() => process.exit(0))
54 | .catch((error) => {
55 | console.error(error);
56 | process.exit(1);
57 | });
58 |
--------------------------------------------------------------------------------
/scripts/4_deployEPNSCommV2.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress", "epnsCommAdmin"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const PushCommV2 = await deployContract("PushCommV2", [], "PushCommV2");
40 | deployedContracts.push(PushCommV2)
41 |
42 | const EPNSCommAdmin = await ethers.getContractFactory("EPNSCommAdmin")
43 | const epnsAdminInstance = EPNSCommAdmin.attach(versionDetails.deploy.args.epnsCommAdmin)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${PushCommV2.address} \n\t\t\t\n`))
46 | // await epnsAdminInstance.upgrade(versionDetails.deploy.args.epnsProxyAddress, PushCommV2.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`))
48 |
49 | return deployedContracts
50 | }
51 |
52 | main()
53 | .then(() => process.exit(0))
54 | .catch((error) => {
55 | console.error(error);
56 | process.exit(1);
57 | });
58 |
--------------------------------------------------------------------------------
/scripts/5_deployEPNSCoreV3.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress", "epnsCoreAdmin"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const EPNSCoreV3 = await deployContract("PushCoreV3", [], "PushCoreV3");
40 | deployedContracts.push(EPNSCoreV3)
41 |
42 | const EPNSCoreAdmin = await ethers.getContractFactory("EPNSCoreAdmin")
43 | const epnsAdminInstance = EPNSCoreAdmin.attach(versionDetails.deploy.args.epnsCoreAdmin)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${EPNSCoreV3.address} \n\t\t\t\n`))
46 | await epnsAdminInstance.upgrade(versionDetails.deploy.args.epnsProxyAddress, EPNSCoreV3.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`))
48 |
49 | return deployedContracts
50 | }
51 |
52 | main()
53 | .then(() => process.exit(0))
54 | .catch((error) => {
55 | console.error(error);
56 | process.exit(1);
57 | });
58 |
--------------------------------------------------------------------------------
/scripts/6_deployEPNSCommV3.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const chalk = require("chalk");
3 | const { config, ethers } = require("hardhat");
4 | const { versionVerifier, upgradeVersion } = require('../loaders/versionVerifier')
5 |
6 | const { bn, tokens, bnToInt, timeInDays, timeInDate, readArgumentsFile, deployContract, verifyAllContracts } = require('../helpers/utils')
7 |
8 | async function main() {
9 | // Version Check
10 | console.log(chalk.bgBlack.bold.green(`\n✌️ Running Version Checks \n-----------------------\n`))
11 | const versionDetails = versionVerifier(["epnsProxyAddress", "epnsCommAdmin"])
12 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n Version Control Passed \n\t\t\t\n`))
13 |
14 | // First deploy all contracts
15 | console.log(chalk.bgBlack.bold.green(`\n📡 Deploying Contracts \n-----------------------\n`))
16 | const deployedContracts = await setupAllContracts(versionDetails)
17 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Deployed \n\t\t\t\n`))
18 |
19 | // Try to verify
20 | console.log(chalk.bgBlack.bold.green(`\n📡 Verifying Contracts \n-----------------------\n`))
21 | await verifyAllContracts(deployedContracts, versionDetails)
22 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n All Contracts Verified \n\t\t\t\n`))
23 |
24 | // Upgrade Version
25 | console.log(chalk.bgBlack.bold.green(`\n📟 Upgrading Version \n-----------------------\n`))
26 | upgradeVersion()
27 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Version upgraded \n\t\t\t\n`))
28 | }
29 |
30 | async function setupAllContracts(versionDetails) {
31 | let deployedContracts = []
32 | console.log("📡 Deploy \n");
33 | // auto deploy to read contract directory and deploy them all (add ".args" files for arguments)
34 | // await autoDeploy();
35 | // OR
36 | // custom deploy (to use deployed addresses dynamically for example:)
37 | const [adminSigner, aliceSigner, bobSigner, eventualAdmin] = await ethers.getSigners();
38 |
39 | const PushCommV3 = await deployContract("PushCommV3", [], "PushCommV3");
40 | deployedContracts.push(PushCommV3)
41 |
42 | const EPNSCommAdmin = await ethers.getContractFactory("EPNSCommAdmin")
43 | const epnsAdminInstance = EPNSCommAdmin.attach(versionDetails.deploy.args.epnsCommAdmin)
44 |
45 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Upgrading Contract to`), chalk.magenta(`${EPNSCoreV3.address} \n\t\t\t\n`))
46 | await epnsAdminInstance.upgrade(versionDetails.deploy.args.epnsProxyAddress, PushCommV3.address);
47 | console.log(chalk.bgWhite.bold.black(`\n\t\t\t\n ✅ Contracts Upgraded \n\t\t\t\n`))
48 |
49 | return deployedContracts
50 | }
51 |
52 | main()
53 | .then(() => process.exit(0))
54 | .catch((error) => {
55 | console.error(error);
56 | process.exit(1);
57 | });
58 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/0_deploySample.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1
5 | },
6 | goerli: {
7 | version: 1
8 | },
9 | hardhat: {
10 | version: 1
11 | },
12 | localhost: {
13 | version: 1
14 | },
15 | polygonMumbai: {
16 | version: 1
17 | },
18 | bscTestnet: {
19 | version: 1
20 | },
21 | polygonZkEVMTestnet: {
22 | version: 1
23 | },
24 | optimismSepolia: {
25 | version: 1
26 | },
27 | optimismMainnet: {
28 | version: 1
29 | },
30 | polygon: {
31 | version: 1
32 | },
33 | linea: {
34 | version: 1
35 | },
36 | bscMainnet: {
37 | version: 1
38 | },
39 | xdai: {
40 | version: 1
41 | },
42 | sepolia: {
43 | version: 1
44 | }
45 | },
46 | args: {
47 | mock: 'null'
48 | }
49 | }
50 |
51 | exports.deploy = deploy
52 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/1_5_deployEPNSCoreV1_5.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | arbitrumSepolia: {
19 | version: 1,
20 | },
21 | arbitrumMainnet: {
22 | version: 1,
23 | },
24 | optimismSepolia: {
25 | version: 1,
26 | },
27 | optimismMainnet: {
28 | version: 1,
29 | },
30 | hardhat: {
31 | version: 1,
32 | },
33 | localhost: {
34 | version: 1,
35 | }
36 | },
37 | args: {
38 | epnsProxyAddress: null,
39 | epnsCoreAdmin: null
40 | }
41 | }
42 |
43 | exports.deploy = deploy
44 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/1_deployEPNSCoreV1.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | arbitrumSepolia: {
19 | version: 1,
20 | },
21 | arbitrumMainnet: {
22 | version: 1,
23 | },
24 | optimismSepolia: {
25 | version: 1,
26 | },
27 | optimismMainnet: {
28 | version: 1,
29 | },
30 | hardhat: {
31 | version: 1,
32 | },
33 | localhost: {
34 | version: 1,
35 | }
36 | },
37 | args: {
38 | daiAddress: null,
39 | aDaiAddress: null,
40 | wethAddress: null,
41 | pushAddress: null,
42 | uniswapRouterAddress: null,
43 | aaveLendingAddress: null,
44 | referralCode: null
45 | }
46 | }
47 |
48 | exports.deploy = deploy
49 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/2_5_deployEPNSCommV1_5.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | arbitrumSepolia: {
19 | version: 1,
20 | },
21 | arbitrumMainnet: {
22 | version: 1,
23 | },
24 | optimismSepolia: {
25 | version: 1,
26 | },
27 | optimismMainnet: {
28 | version: 1,
29 | },
30 | hardhat: {
31 | version: 1,
32 | },
33 | localhost: {
34 | version: 1,
35 | }
36 | },
37 | args: {
38 | epnsProxyAddress: null,
39 | epnsCommAdmin: null
40 | }
41 | }
42 |
43 | exports.deploy = deploy
--------------------------------------------------------------------------------
/scripts/versioncontrol/2_deployEPNSCommV1.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1
5 | },
6 | polygon: {
7 | version: 1
8 | },
9 | polygonMumbai: {
10 | version: 1
11 | },
12 | bnbTestnet: {
13 | version: 1
14 | },
15 | bnbMainnet: {
16 | version: 1
17 | },
18 | arbitrumSepolia: {
19 | version: 1
20 | },
21 | arbitrumMainnet: {
22 | version: 1
23 | },
24 | optimismSepolia: {
25 | version: 1
26 | },
27 | optimismMainnet: {
28 | version: 1
29 | },
30 | hardhat: {
31 | version: 1
32 | },
33 | localhost: {
34 | version: 1
35 | },
36 | sepolia: {
37 | version: 1
38 | },
39 | fuse: {
40 | version: 1
41 | },
42 | fuseSpark: {
43 | version: 1
44 | },
45 | sphinx: {
46 | version: 1
47 | },
48 | berachainTestnet: {
49 | version: 1
50 | },
51 | polygonAmoy: {
52 | version: 1
53 | },
54 | X1: {
55 | version: 1
56 | },
57 | lineaMainnet: {
58 | version: 1
59 | },
60 | lineaSepolia: {
61 | version: 1
62 | },
63 | polygonZkEVMTestnet: {
64 | version: 1
65 | },
66 | cyberTestnet: {
67 | version: 1
68 | },
69 | cyberMainnet: {
70 | version: 1
71 | },
72 | baseSepolia:{
73 | version: 1
74 | },
75 | baseMainnet:{
76 | version: 1
77 | }
78 | },
79 | args: {
80 | chainName: null
81 | }
82 | }
83 |
84 | exports.deploy = deploy
--------------------------------------------------------------------------------
/scripts/versioncontrol/3_deployEPNSCoreV2.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | arbitrumSepolia: {
19 | version: 1,
20 | },
21 | hardhat: {
22 | version: 1
23 | },
24 | localhost: {
25 | version: 1
26 | },
27 | polygonMumbai: {
28 | version: 1
29 | },
30 | bscTestnet: {
31 | version: 1
32 | },
33 | polygonZkEVMTestnet: {
34 | version: 1
35 | },
36 | optimismSepolia: {
37 | version: 1
38 | },
39 | optimismMainnet: {
40 | version: 1
41 | },
42 | polygon: {
43 | version: 1
44 | },
45 | bscMainnet: {
46 | version: 1
47 | },
48 | xdai: {
49 | version: 1
50 | },
51 | sepolia: {
52 | version: 1
53 | },
54 | optimismSepolia:{
55 | version: 1,
56 | }
57 | },
58 | args: {
59 | epnsProxyAddress: null,
60 | epnsCoreAdmin: null
61 | }
62 | }
63 |
64 | exports.deploy = deploy
65 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/4_deployEPNSCommV2.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | hardhat: {
19 | version: 1
20 | },
21 | localhost: {
22 | version: 1
23 | },
24 | polygonMumbai: {
25 | version: 1
26 | },
27 | bscTestnet: {
28 | version: 1
29 | },
30 | polygonZkEVMTestnet: {
31 | version: 1
32 | },
33 | optimismSepolia: {
34 | version: 1
35 | },
36 | optimismMainnet: {
37 | version: 1
38 | },
39 | polygon: {
40 | version: 1
41 | },
42 | lineaMainnet: {
43 | version: 1
44 | },
45 | lineaSepolia: {
46 | version: 1
47 | },
48 | bscMainnet: {
49 | version: 1
50 | },
51 | xdai: {
52 | version: 1
53 | },
54 | sepolia: {
55 | version: 1
56 | },
57 | fuse : {
58 | version: 1
59 | },
60 | fuseSpark: {
61 | version: 1,
62 | },
63 | arbitrumSepolia:{
64 | version: 1,
65 | },
66 | arbitrumMainnet:{
67 | version:1,
68 | },
69 | polygonAmoy:{
70 | version: 1
71 | },
72 | X1:{
73 | version: 1
74 | },
75 | cyberTestnet:{
76 | version: 1
77 | },
78 | cyberMainnet:{
79 | version: 1
80 | },
81 | baseSepolia:{
82 | version: 1
83 | },
84 | baseMainnet:{
85 | version: 1
86 | }
87 | },
88 | args: {
89 | epnsProxyAddress: null,
90 | epnsCommAdmin: null
91 | }
92 | }
93 |
94 | exports.deploy = deploy
95 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/5_deployEPNSCoreV3.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | arbitrumSepolia: {
19 | version: 1,
20 | },
21 | hardhat: {
22 | version: 1
23 | },
24 | localhost: {
25 | version: 1
26 | },
27 | polygonMumbai: {
28 | version: 1
29 | },
30 | bscTestnet: {
31 | version: 1
32 | },
33 | polygonZkEVMTestnet: {
34 | version: 1
35 | },
36 | optimismSepolia: {
37 | version: 1
38 | },
39 | optimismMainnet: {
40 | version: 1
41 | },
42 | polygon: {
43 | version: 1
44 | },
45 | bscMainnet: {
46 | version: 1
47 | },
48 | xdai: {
49 | version: 1
50 | },
51 | sepolia: {
52 | version: 1
53 | },
54 | optimismSepolia:{
55 | version: 1,
56 | }
57 | },
58 | args: {
59 | epnsProxyAddress: null,
60 | epnsCoreAdmin: null
61 | }
62 | }
63 |
64 | exports.deploy = deploy
65 |
--------------------------------------------------------------------------------
/scripts/versioncontrol/6_deployEPNSCommV3.config.js:
--------------------------------------------------------------------------------
1 | const deploy = {
2 | network: {
3 | mainnet: {
4 | version: 1,
5 | },
6 | polygon: {
7 | version: 1,
8 | },
9 | polygonMumbai: {
10 | version: 1,
11 | },
12 | bnbTestnet: {
13 | version: 1,
14 | },
15 | bnbMainnet: {
16 | version: 1,
17 | },
18 | arbitrumSepolia: {
19 | version: 1,
20 | },
21 | hardhat: {
22 | version: 1
23 | },
24 | localhost: {
25 | version: 1
26 | },
27 | polygonMumbai: {
28 | version: 1
29 | },
30 | bscTestnet: {
31 | version: 1
32 | },
33 | polygonZkEVMTestnet: {
34 | version: 1
35 | },
36 | optimismSepolia: {
37 | version: 1
38 | },
39 | optimismMainnet: {
40 | version: 1
41 | },
42 | polygon: {
43 | version: 1
44 | },
45 | lineaMainnet: {
46 | version: 1
47 | },
48 | lineaSepolia: {
49 | version: 1
50 | },
51 | bscMainnet: {
52 | version: 1
53 | },
54 | xdai: {
55 | version: 1
56 | },
57 | sepolia: {
58 | version: 1
59 | },
60 | fuse : {
61 | version: 1
62 | },
63 | fuseSpark: {
64 | version: 1,
65 | },
66 | optimismSepolia:{
67 | version: 1,
68 | },
69 | polygonAmoy:{
70 | version: 1
71 | },
72 | X1:{
73 | version: 1
74 | },
75 | cyberTestnet:{
76 | version: 1
77 | },
78 | cyberMainnet:{
79 | version: 1
80 | },
81 | baseSepolia:{
82 | version: 1
83 | },
84 | baseMainnet:{
85 | version: 1
86 | }
87 | },
88 | args: {
89 | epnsProxyAddress: null,
90 | epnsCommAdmin: null
91 | }
92 | }
93 |
94 | exports.deploy = deploy
95 |
--------------------------------------------------------------------------------
/test/benchmarks/EPNSCoreV1.Benchmark.test.js:
--------------------------------------------------------------------------------
1 | // Import helper functions
2 | const { bn, tokensBN } = require('../../helpers/utils');
3 |
4 | // We import Chai to use its asserting functions here.
5 | const { expect } = require("chai");
6 |
7 |
8 | describe("Benchmaking Contracts", async function () {
9 | // Get addresses
10 | let owner
11 | let alice
12 | let bob
13 | let charles
14 | const AAVE_LENDING_POOL = "0x1c8756FD2B28e9426CDBDcC7E3c4d64fa9A54728";
15 | const DAI = "0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108";
16 | const ADAI = "0xcB1Fe6F440c49E9290c3eb7f158534c2dC374201";
17 | const referralCode = 0;
18 | const delay = 0; // uint for the timelock delay
19 | const ADD_CHANNEL_MIN_POOL_CONTRIBUTION = tokensBN(50)
20 | const ADD_CHANNEL_MAX_POOL_CONTRIBUTION = tokensBN(250000 * 50)
21 | const CHANNEL_TYPE = 2;
22 | const testChannel = ethers.utils.toUtf8Bytes("test-channel-hello-world");
23 |
24 | // To load benchmarks
25 | let EPNSBenchmarks
26 |
27 | // Initialize
28 | before(async function () {
29 | [owner, alice, bob, charles, eventualAdmin] = await ethers.getSigners()
30 |
31 | const TimeLock = await ethers.getContractFactory("Timelock");
32 | const TIMELOCK = await TimeLock.deploy(owner.address, delay);
33 |
34 | const proxyAdmin = await ethers.getContractFactory("EPNSAdmin");
35 | const PROXYADMIN = await proxyAdmin.deploy();
36 | await PROXYADMIN.transferOwnership(TIMELOCK.address);
37 |
38 | // Define all benchmarks
39 | EPNSBenchmarks = [
40 | {
41 | name: "EPNSStagingV4",
42 | changes: "EPNSStagingV4 Testing",
43 | args: [owner.address, AAVE_LENDING_POOL, DAI, ADAI, referralCode],
44 | functions: [
45 | {
46 | call: `createChannelWithFees(${CHANNEL_TYPE},${testChannel}'${ADD_CHANNEL_MIN_POOL_CONTRIBUTION}')`,
47 | from: owner.address
48 | },
49 | {
50 | call: `createPromoterChannel()`,
51 | from: owner.address
52 | },
53 | {
54 | call: `createChannelWithFees(${CHANNEL_TYPE},${testChannel}'${ADD_CHANNEL_MIN_POOL_CONTRIBUTION}')`,
55 | from: owner.address
56 | },
57 | {
58 | call: `createChannelWithFees(${CHANNEL_TYPE},${testChannel}'${ADD_CHANNEL_MIN_POOL_CONTRIBUTION}')`,
59 | from: owner.address
60 | },
61 | ]
62 | },
63 | {
64 | name: "EPNSStagingV1",
65 | changes: "EPNS_StagingV1 Testing",
66 | args: [owner.address, AAVE_LENDING_POOL, DAI, ADAI, referralCode],
67 | functions: [
68 | {
69 | call: `addToChannelizationWhitelist('${charles.address}')`,
70 | from: owner.address
71 | },
72 | {
73 | call: `addToChannelizationWhitelist('${charles.address}')`,
74 | from: owner.address
75 | },
76 | {
77 | call: `addToChannelizationWhitelist('${charles.address}')`,
78 | from: owner.address
79 | },
80 | {
81 | call: `addToChannelizationWhitelist('${charles.address}')`,
82 | from: owner.address
83 | },
84 | ]
85 | },
86 | {
87 | name: "EPNSStagingV1",
88 | changes: "EPNSCoreV3 Testing",
89 | args: [owner.address, AAVE_LENDING_POOL, DAI, ADAI, referralCode],
90 | functions: [
91 | {
92 | call: `addToChannelizationWhitelist('${charles.address}')`,
93 | from: owner.address
94 | },
95 | {
96 | call: `addToChannelizationWhitelist('${charles.address}')`,
97 | from: owner.address
98 | },
99 | {
100 | call: `addToChannelizationWhitelist('${charles.address}')`,
101 | from: owner.address
102 | },
103 | {
104 | call: `addToChannelizationWhitelist('${charles.address}')`,
105 | from: owner.address
106 | },
107 | ]
108 | },
109 | ]
110 | })
111 |
112 | // Prepare benchmarks
113 | describe("Running Benchmark on EPNS.sol", async function () {
114 | let deployments = []
115 |
116 | beforeEach(async function () {
117 | for (const item of EPNSBenchmarks) {
118 | const Contract = await ethers.getContractFactory(`${item.name}`)
119 | const deployedContract = await Contract.deploy()
120 |
121 | const EPNSPROXYContract = await ethers.getContractFactory("EPNSProxy");
122 |
123 | EPNSProxy = await EPNSPROXYContract.deploy(
124 | deployedContract.address,
125 | ...item.args
126 | );
127 | await EPNSProxy.changeAdmin(eventualAdmin.address);
128 |
129 | const deployedContractProxy = deployedContract.attach(EPNSProxy.address)
130 | const deployedProxy = {
131 | name: item.name,
132 | contract: deployedContractProxy,
133 | calls: item.functions
134 | }
135 | deployments.push(deployedProxy)
136 | }
137 |
138 | })
139 |
140 | afterEach(async function () {
141 | //deployments = []
142 | })
143 |
144 | it(`Benchmarking...`, async function () {
145 | for (const item of deployments) {
146 | const contract = item.contract
147 | for (const func of item.calls) {
148 | const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
149 |
150 | let execute = new AsyncFunction('contract', 'func', + `await contract.${func.call}`)
151 | const tx = await execute(contract, func)
152 | }
153 | }
154 | })
155 |
156 | })
157 |
158 | })
159 |
--------------------------------------------------------------------------------
/test/common/expect.js:
--------------------------------------------------------------------------------
1 | const { use, expect } = require("chai");
2 | const { solidity } = require("ethereum-waffle");
3 |
4 | use(solidity);
5 |
6 | module.exports = {
7 | expect
8 | }
--------------------------------------------------------------------------------
/test/common/fixtures.js:
--------------------------------------------------------------------------------
1 | const { tokensBN } = require("../../helpers/utils");
2 | const { ethers } = require("hardhat");
3 |
4 | const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
5 | const ADAI = "0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d";
6 | const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
7 | const AAVE_LENDING_POOL = "0x24a42fD28C976A61Df5D00D0599C34c4f90748c8";
8 |
9 | const EPNS_TOKEN_ADDRS = "0xf418588522d5dd018b425E472991E52EBBeEEEEE";
10 | const UNISWAP_ROUTER = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
11 | const WETH_ADDRS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
12 | const referralCode = 0;
13 |
14 | const CHAIN_NAME = "Mainnet"; // MAINNET, MATIC etc.
15 |
16 | const PUSH_WHALE_ADDRESS = "0xCB8EFB0c065071E4110932858A84365A80C8feF0";
17 | const AMT_TO_TRASFER = tokensBN(2_000_000);
18 |
19 | const epnsContractFixture = async ([adminSigner, others]) => {
20 | const ADMIN = await adminSigner.getAddress();
21 | ROUTER = await ethers.getContractAt("IUniswapV2Router", UNISWAP_ROUTER);
22 |
23 | // deploy dummy push token
24 | let PushToken = await ethers.getContractFactory("EPNS");
25 | PushToken = await PushToken.deploy(ADMIN);
26 |
27 | const EPNSCore = await ethers.getContractFactory("EPNSCoreV1_5");
28 | CORE_LOGIC = await EPNSCore.deploy();
29 |
30 | const proxyAdmin = await ethers.getContractFactory("EPNSCoreAdmin");
31 | PROXYADMIN = await proxyAdmin.deploy();
32 |
33 | const EPNSCommunicator = await ethers.getContractFactory("EPNSCommV1_5");
34 | COMMUNICATOR_LOGIC = await EPNSCommunicator.deploy();
35 |
36 | const EPNSCoreProxyContract = await ethers.getContractFactory(
37 | "EPNSCoreProxy"
38 | );
39 | EPNSCoreProxy = await EPNSCoreProxyContract.deploy(
40 | CORE_LOGIC.address,
41 | PROXYADMIN.address,
42 | ADMIN,
43 | PushToken.address,
44 | WETH,
45 | UNISWAP_ROUTER,
46 | AAVE_LENDING_POOL,
47 | DAI,
48 | ADAI,
49 | referralCode
50 | );
51 |
52 | const EPNSCommProxyContract = await ethers.getContractFactory(
53 | "EPNSCommProxy"
54 | );
55 | EPNSCommProxy = await EPNSCommProxyContract.deploy(
56 | COMMUNICATOR_LOGIC.address,
57 | PROXYADMIN.address,
58 | ADMIN,
59 | CHAIN_NAME
60 | );
61 |
62 | EPNSCoreV1Proxy = EPNSCore.attach(EPNSCoreProxy.address);
63 | EPNSCommV1Proxy = EPNSCommunicator.attach(EPNSCommProxy.address);
64 | await EPNSCommV1Proxy.setEPNSCoreAddress(EPNSCoreV1Proxy.address);
65 | await EPNSCoreV1Proxy.setEpnsCommunicatorAddress(EPNSCommV1Proxy.address);
66 |
67 | return {
68 | CORE_LOGIC,
69 | PROXYADMIN,
70 | COMMUNICATOR_LOGIC,
71 | EPNSCoreProxy,
72 | EPNSCoreV1Proxy,
73 | EPNSCommV1Proxy,
74 | ROUTER,
75 | PushToken,
76 | EPNS_TOKEN_ADDRS,
77 | };
78 | };
79 |
80 |
81 |
82 | module.exports = {
83 | epnsContractFixture,
84 | };
--------------------------------------------------------------------------------
/test/common/fixturesV2.js:
--------------------------------------------------------------------------------
1 | const { tokensBN } = require("../../helpers/utils");
2 | const { ethers } = require("hardhat");
3 |
4 | const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
5 | const ADAI = "0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d";
6 | const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
7 | const AAVE_LENDING_POOL = "0x24a42fD28C976A61Df5D00D0599C34c4f90748c8";
8 |
9 | const EPNS_TOKEN_ADDRS = "0xf418588522d5dd018b425E472991E52EBBeEEEEE";
10 | const UNISWAP_ROUTER = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
11 | const WETH_ADDRS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
12 | const referralCode = 0;
13 |
14 | const CHAIN_NAME = "Mainnet"; // MAINNET, MATIC etc.
15 |
16 | const PUSH_WHALE_ADDRESS = "0xCB8EFB0c065071E4110932858A84365A80C8feF0";
17 | const AMT_TO_TRASFER = tokensBN(2_000_000);
18 |
19 | const epnsContractFixture = async ([adminSigner, others]) => {
20 | const ADMIN = await adminSigner.getAddress();
21 | ROUTER = await ethers.getContractAt("IUniswapV2Router", UNISWAP_ROUTER);
22 |
23 | // deploy dummy push token
24 | let PushToken = await ethers.getContractFactory("EPNS");
25 | PushToken = await PushToken.deploy(ADMIN);
26 |
27 | const EPNSCore = await ethers.getContractFactory("PushCoreV2");
28 | CORE_LOGIC = await EPNSCore.deploy();
29 |
30 | const proxyAdmin = await ethers.getContractFactory("EPNSCoreAdmin");
31 | PROXYADMIN = await proxyAdmin.deploy();
32 |
33 | const EPNSCommunicator = await ethers.getContractFactory("PushCommV2");
34 | COMMUNICATOR_LOGIC = await EPNSCommunicator.deploy();
35 |
36 | const EPNSCoreProxyContract = await ethers.getContractFactory(
37 | "EPNSCoreProxy"
38 | );
39 | EPNSCoreProxy = await EPNSCoreProxyContract.deploy(
40 | CORE_LOGIC.address,
41 | PROXYADMIN.address,
42 | ADMIN,
43 | PushToken.address,
44 | WETH,
45 | UNISWAP_ROUTER,
46 | AAVE_LENDING_POOL,
47 | DAI,
48 | ADAI,
49 | referralCode
50 | );
51 |
52 | const EPNSCommProxyContract = await ethers.getContractFactory(
53 | "EPNSCommProxy"
54 | );
55 | EPNSCommProxy = await EPNSCommProxyContract.deploy(
56 | COMMUNICATOR_LOGIC.address,
57 | PROXYADMIN.address,
58 | ADMIN,
59 | CHAIN_NAME
60 | );
61 |
62 | EPNSCoreV1Proxy = EPNSCore.attach(EPNSCoreProxy.address);
63 | EPNSCommV1Proxy = EPNSCommunicator.attach(EPNSCommProxy.address);
64 | await EPNSCommV1Proxy.setEPNSCoreAddress(EPNSCoreV1Proxy.address);
65 | await EPNSCoreV1Proxy.setEpnsCommunicatorAddress(EPNSCommV1Proxy.address);
66 |
67 | return {
68 | CORE_LOGIC,
69 | PROXYADMIN,
70 | COMMUNICATOR_LOGIC,
71 | EPNSCoreProxy,
72 | EPNSCoreV1Proxy,
73 | EPNSCommV1Proxy,
74 | ROUTER,
75 | PushToken,
76 | EPNS_TOKEN_ADDRS,
77 | };
78 | };
79 |
80 |
81 |
82 | module.exports = {
83 | epnsContractFixture,
84 | };
--------------------------------------------------------------------------------
/test/common/fixtures_temp.js:
--------------------------------------------------------------------------------
1 | const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
2 | const ADAI = "0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d";
3 | const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
4 | const AAVE_LENDING_POOL = "0x24a42fD28C976A61Df5D00D0599C34c4f90748c8";
5 |
6 | const EPNS_TOKEN_ADDRS = "0xf418588522d5dd018b425E472991E52EBBeEEEEE";
7 | const UNISWAP_ROUTER = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
8 | const WETH_ADDRS = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
9 | const referralCode = 0;
10 |
11 | const CHAIN_NAME = "Mainnet"; // MAINNET, MATIC etc.
12 |
13 | const epnsContractFixture = async ([adminSigner, others]) => {
14 | const ADMIN = await adminSigner.getAddress();
15 |
16 | ROUTER = await ethers.getContractAt("IUniswapV2RouterMock", UNISWAP_ROUTER);
17 |
18 | const EPNSTOKEN = await ethers.getContractFactory("EPNS");
19 | EPNS = await EPNSTOKEN.attach(EPNS_TOKEN_ADDRS);
20 |
21 | const EPNSCore = await ethers.getContractFactory("EPNSCoreV1_Temp");
22 | CORE_LOGIC = await EPNSCore.deploy();
23 |
24 | const proxyAdmin = await ethers.getContractFactory("EPNSCoreAdmin");
25 | PROXYADMIN = await proxyAdmin.deploy();
26 |
27 | const EPNSCommunicator = await ethers.getContractFactory("EPNSCommV1");
28 | COMMUNICATOR_LOGIC = await EPNSCommunicator.deploy();
29 |
30 | const EPNSCoreProxyContract = await ethers.getContractFactory(
31 | "EPNSCoreProxy"
32 | );
33 | EPNSCoreProxy = await EPNSCoreProxyContract.deploy(
34 | CORE_LOGIC.address,
35 | PROXYADMIN.address,
36 | ADMIN,
37 | EPNS.address,
38 | WETH,
39 | UNISWAP_ROUTER,
40 | AAVE_LENDING_POOL,
41 | DAI,
42 | ADAI,
43 | referralCode
44 | );
45 |
46 | const EPNSCommProxyContract = await ethers.getContractFactory(
47 | "EPNSCommProxy"
48 | );
49 | EPNSCommProxy = await EPNSCommProxyContract.deploy(
50 | COMMUNICATOR_LOGIC.address,
51 | PROXYADMIN.address,
52 | ADMIN,
53 | CHAIN_NAME
54 | );
55 |
56 | EPNSCoreV1Proxy = EPNSCore.attach(EPNSCoreProxy.address);
57 | EPNSCommV1Proxy = EPNSCommunicator.attach(EPNSCommProxy.address);
58 | await EPNSCommV1Proxy.setEPNSCoreAddress(EPNSCoreV1Proxy.address);
59 | await EPNSCoreV1Proxy.setEpnsCommunicatorAddress(EPNSCommV1Proxy.address);
60 |
61 | return {
62 | CORE_LOGIC,
63 | PROXYADMIN,
64 | COMMUNICATOR_LOGIC,
65 | EPNSCoreProxy,
66 | EPNSCoreV1Proxy,
67 | EPNSCommV1Proxy,
68 | ROUTER,
69 | EPNS,
70 | EPNS_TOKEN_ADDRS,
71 | WETH_ADDRS,
72 | };
73 | };
74 |
75 | const tokenFixture = async ([adminSigner, others]) => {
76 | const MOCKDAITOKEN = await ethers.getContractFactory("MockDAI");
77 | MOCKDAI = await MOCKDAITOKEN.attach(DAI);
78 |
79 | const ADAIContract = await ethers.getContractAt("IADai", ADAI);
80 | const DAI_WHALE_SIGNER = await ethers.getImpersonatedSigner(
81 | "0x7c8CA1a587b2c4c40fC650dB8196eE66DC9c46F4"
82 | );
83 |
84 | return {
85 | MOCKDAI,
86 | ADAI: ADAIContract,
87 | DAI_WHALE_SIGNER,
88 | };
89 | };
90 |
91 | module.exports = {
92 | epnsContractFixture,
93 | tokenFixture,
94 | };
95 |
--------------------------------------------------------------------------------
/test/time.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require("hardhat");
2 |
3 | const BN = require("bn.js");
4 |
5 | async function advanceBlock() {
6 | return ethers.provider.send("evm_mine");
7 | }
8 |
9 | // Advance the block to the passed height
10 | async function advanceBlockTo(target) {
11 | if (!BN.isBN(target)) {
12 | // eslint-disable-next-line no-param-reassign
13 | target = new BN(target);
14 | }
15 |
16 | const currentBlock = await latestBlock();
17 | const start = Date.now();
18 | let notified;
19 | if (target.lt(currentBlock))
20 | throw Error(
21 | `Target block #(${target}) is lower than current block #(${currentBlock})`
22 | );
23 | // eslint-disable-next-line no-await-in-loop
24 | while ((await latestBlock()).lt(target)) {
25 | if (!notified && Date.now() - start >= 5000) {
26 | notified = true;
27 | console.log("advancing too far will slow this test down");
28 | }
29 | // eslint-disable-next-line no-await-in-loop
30 | await advanceBlock();
31 | }
32 | }
33 |
34 | // Returns the time of the last mined block in seconds
35 | async function latest() {
36 | const block = await ethers.provider.getBlock("latest");
37 | return new BN(block.timestamp);
38 | }
39 |
40 | async function latestBlock() {
41 | const block = await ethers.provider.getBlock("latest");
42 | return new BN(block.number);
43 | }
44 | // Increases ganache time by the passed duration in seconds
45 | async function increase(duration) {
46 | if (!BN.isBN(duration)) {
47 | duration = new BN(duration);
48 | }
49 |
50 | if (duration.isNeg())
51 | throw Error(`Cannot increase time by a negative amount (${duration})`);
52 |
53 | await ethers.provider.send("evm_increaseTime", [duration.toNumber()]);
54 |
55 | await advanceBlock();
56 | }
57 |
58 | /**
59 | * Beware that due to the need of calling two separate ganache methods and rpc calls overhead
60 | * it's hard to increase time precisely to a target point so design your test to tolerate
61 | * small fluctuations from time to time.
62 | *
63 | * @param target time in seconds
64 | */
65 | async function increaseTo(target) {
66 | if (!BN.isBN(target)) {
67 | target = new BN(target);
68 | }
69 |
70 | const now = await latest();
71 |
72 | if (target.lt(now))
73 | throw Error(
74 | `Cannot increase current time (${now}) to a moment in the past (${target})`
75 | );
76 | const diff = target.sub(now);
77 | return increase(diff);
78 | }
79 |
80 | const duration = {
81 | seconds(val) {
82 | return new BN(val);
83 | },
84 | minutes(val) {
85 | return new BN(val).mul(this.seconds("60"));
86 | },
87 | hours(val) {
88 | return new BN(val).mul(this.minutes("60"));
89 | },
90 | days(val) {
91 | return new BN(val).mul(this.hours("24"));
92 | },
93 | weeks(val) {
94 | return new BN(val).mul(this.days("7"));
95 | },
96 | years(val) {
97 | return new BN(val).mul(this.days("365"));
98 | },
99 | };
100 |
101 | module.exports = {
102 | advanceBlock,
103 | advanceBlockTo,
104 | latest,
105 | latestBlock,
106 | increase,
107 | increaseTo,
108 | duration,
109 | };
110 |
--------------------------------------------------------------------------------
/test/v2/comm/SendNotification.test.js:
--------------------------------------------------------------------------------
1 | const { ethers, waffle } = require("hardhat");
2 |
3 | const { bn, tokensBN } = require("../../../helpers/utils");
4 |
5 | const { epnsContractFixture, tokenFixture } = require("../../common/fixturesV2");
6 | const { expect } = require("../../common/expect");
7 | const createFixtureLoader = waffle.createFixtureLoader;
8 |
9 | describe("EPNS Comm V2 Protocol", function () {
10 | const ADD_CHANNEL_MIN_POOL_CONTRIBUTION = tokensBN(50);
11 |
12 | let PushToken;
13 | let EPNSCoreV1Proxy;
14 | let EPNSCommV1Proxy;
15 | let ALICE;
16 | let BOB;
17 | let CHANNEL_CREATOR;
18 | let ADMINSIGNER;
19 | let ALICESIGNER;
20 | let BOBSIGNER;
21 | let CHANNEL_CREATORSIGNER;
22 |
23 | let loadFixture;
24 | before(async () => {
25 | [wallet, other] = await ethers.getSigners();
26 | loadFixture = createFixtureLoader([wallet, other]);
27 | });
28 |
29 | beforeEach(async function () {
30 | // Get the ContractFactory and Signers here.
31 | const [
32 | adminSigner,
33 | aliceSigner,
34 | bobSigner,
35 | charlieSigner,
36 | channelCreatorSigner,
37 | ] = await ethers.getSigners();
38 |
39 | ADMINSIGNER = adminSigner;
40 | ALICESIGNER = aliceSigner;
41 | BOBSIGNER = bobSigner;
42 | CHARLIESIGNER = charlieSigner;
43 | CHANNEL_CREATORSIGNER = channelCreatorSigner;
44 |
45 | ADMIN = await adminSigner.getAddress();
46 | ALICE = await aliceSigner.getAddress();
47 | BOB = await bobSigner.getAddress();
48 | CHARLIE = await charlieSigner.getAddress();
49 | CHANNEL_CREATOR = await channelCreatorSigner.getAddress();
50 |
51 | ({
52 | PROXYADMIN,
53 | EPNSCoreV1Proxy,
54 | EPNSCommV1Proxy,
55 | ROUTER,
56 | PushToken,
57 | EPNS_TOKEN_ADDRS,
58 | } = await loadFixture(epnsContractFixture));
59 | });
60 |
61 | describe("Send Notification", function () {
62 | const CHANNEL_TYPE = 2;
63 | const msg = ethers.utils.toUtf8Bytes("test-channel-hello-world");
64 |
65 | describe("Send Notification Tests", function () {
66 | beforeEach(async function () {
67 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).setEpnsCommunicatorAddress(
68 | EPNSCommV1Proxy.address
69 | );
70 | await EPNSCommV1Proxy.connect(ADMINSIGNER).setEPNSCoreAddress(
71 | EPNSCoreV1Proxy.address
72 | );
73 | await PushToken.transfer(BOB, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
74 | await PushToken.transfer(ALICE, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
75 | await PushToken.transfer(
76 | CHANNEL_CREATOR,
77 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
78 | );
79 | await PushToken.connect(BOBSIGNER).approve(
80 | EPNSCoreV1Proxy.address,
81 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
82 | );
83 | await PushToken.connect(ALICESIGNER).approve(
84 | EPNSCoreV1Proxy.address,
85 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
86 | );
87 | await PushToken.connect(CHANNEL_CREATORSIGNER).approve(
88 | EPNSCoreV1Proxy.address,
89 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
90 | );
91 |
92 | // create a channel
93 | await EPNSCoreV1Proxy.connect(
94 | CHANNEL_CREATORSIGNER
95 | ).createChannelWithPUSH(
96 | CHANNEL_TYPE,
97 | msg,
98 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION,
99 | 0
100 | );
101 | });
102 |
103 | it("Should return false if a User is sending Notif to Other Address Instead of themselves", async function () {
104 | var tx = await EPNSCommV1Proxy.connect(
105 | BOBSIGNER
106 | ).callStatic.sendNotification(CHANNEL_CREATOR, CHARLIE, msg);
107 | expect(tx).to.be.false;
108 |
109 | var tx = await EPNSCommV1Proxy.connect(BOBSIGNER).sendNotification(
110 | CHANNEL_CREATOR,
111 | CHARLIE,
112 | msg
113 | );
114 |
115 | await expect(tx).to.not.emit(EPNSCommV1Proxy, "SendNotification");
116 | });
117 |
118 | it("Should Emit Event if Recipient is Sending NOTIF Only to HIMself/Herself", async function () {
119 | var tx = await EPNSCommV1Proxy.connect(
120 | BOBSIGNER
121 | ).callStatic.sendNotification(CHANNEL_CREATOR, BOB, msg);
122 | expect(tx).to.be.false;
123 |
124 | //User can no more send notification to themselves.
125 |
126 | // var tx = await EPNSCommV1Proxy.connect(BOBSIGNER).sendNotification(
127 | // CHANNEL_CREATOR,
128 | // BOB,
129 | // msg
130 | // );
131 | // await expect(tx)
132 | // .to.emit(EPNSCommV1Proxy, "SendNotification")
133 | // .withArgs(CHANNEL_CREATOR, BOB, ethers.utils.hexlify(msg));
134 | });
135 |
136 | it("Should return false if Channel is 0x00.. But Caller is any address other than Admin/Governance", async function () {
137 | const EPNS_ALERTER_CHANNEL = '0x0000000000000000000000000000000000000000';
138 | var tx = await EPNSCommV1Proxy.connect(BOBSIGNER).callStatic.sendNotification(EPNS_ALERTER_CHANNEL, CHARLIE, msg);
139 | expect(tx).to.be.false;
140 |
141 | var tx = await EPNSCommV1Proxy.connect(BOBSIGNER).sendNotification(EPNS_ALERTER_CHANNEL, CHARLIE, msg);
142 | await expect(tx).to.not.emit(EPNSCommV1Proxy, "SendNotification");
143 | });
144 |
145 | it("Should Emit Event if Channel is 0x00.. and Caller is Admin/Governance", async function () {
146 | const EPNS_ALERTER_CHANNEL = '0x0000000000000000000000000000000000000000';
147 | var txn = await EPNSCommV1Proxy.connect(ADMINSIGNER).callStatic.sendNotification(EPNS_ALERTER_CHANNEL, CHARLIE, msg);
148 | expect(txn).to.be.true;
149 |
150 | var txn = await EPNSCommV1Proxy.connect(ADMINSIGNER).sendNotification(EPNS_ALERTER_CHANNEL, CHARLIE, msg);
151 | await expect(txn)
152 | .to.emit(EPNSCommV1Proxy, 'SendNotification')
153 | .withArgs(EPNS_ALERTER_CHANNEL, CHARLIE, ethers.utils.hexlify(msg));
154 | });
155 |
156 | it("Should return false if Delegate without send notification without Approval", async function () {
157 | var tx = await EPNSCommV1Proxy.connect(CHARLIESIGNER).callStatic.sendNotification(CHANNEL_CREATOR, BOB, msg);
158 | expect(tx).to.be.false;
159 |
160 | var tx = await EPNSCommV1Proxy.connect(CHARLIESIGNER).sendNotification(CHANNEL_CREATOR, BOB, msg);
161 | await expect(tx).to.not.emit(EPNSCommV1Proxy, "SendNotification");
162 | });
163 |
164 | it("Should Emit Event Allowed Delagtes Sends Notification to any Recipient", async function () {
165 | const isCharlieAllowed_before = await EPNSCommV1Proxy.connect(CHANNEL_CREATORSIGNER).delegatedNotificationSenders(CHANNEL_CREATOR, CHARLIE);
166 | await EPNSCommV1Proxy.connect(CHANNEL_CREATORSIGNER).addDelegate(CHARLIE);
167 | const isCharlieAllowed_after = await EPNSCommV1Proxy.connect(CHANNEL_CREATORSIGNER).delegatedNotificationSenders(CHANNEL_CREATOR, CHARLIE);
168 |
169 | const tx_sendNotif = EPNSCommV1Proxy.connect(CHARLIESIGNER).sendNotification(CHANNEL_CREATOR, BOB, msg);
170 |
171 | await expect(isCharlieAllowed_before).to.equal(false);
172 | await expect(isCharlieAllowed_after).to.equal(true);
173 | await expect(tx_sendNotif)
174 | .to.emit(EPNSCommV1Proxy, 'SendNotification')
175 | .withArgs(CHANNEL_CREATOR, BOB, ethers.utils.hexlify(msg));
176 | });
177 | });
178 | });
179 | });
--------------------------------------------------------------------------------
/test/v2/comm/SendNotificationFromSig.test.js:
--------------------------------------------------------------------------------
1 | const { ethers, waffle } = require("hardhat");
2 |
3 | const { bn, tokensBN } = require("../../../helpers/utils");
4 |
5 | const { epnsContractFixture } = require("../../common/fixturesV2");
6 | const { expect } = require("../../common/expect");
7 | const createFixtureLoader = waffle.createFixtureLoader;
8 |
9 | describe("EPNS Comm V2 Protocol", function () {
10 | const ADD_CHANNEL_MIN_POOL_CONTRIBUTION = tokensBN(50);
11 |
12 | let PushToken;
13 | let EPNSCoreV1Proxy;
14 | let EPNSCommV1Proxy;
15 | let ALICE;
16 | let BOB;
17 | let CHANNEL_CREATOR;
18 | let ADMINSIGNER;
19 | let ALICESIGNER;
20 | let BOBSIGNER;
21 | let CHANNEL_CREATORSIGNER;
22 |
23 | let loadFixture;
24 | before(async () => {
25 | [wallet, other] = await ethers.getSigners();
26 | loadFixture = createFixtureLoader([wallet, other]);
27 | });
28 |
29 | beforeEach(async function () {
30 | // Get the ContractFactory and Signers here.
31 | const [
32 | adminSigner,
33 | aliceSigner,
34 | bobSigner,
35 | charlieSigner,
36 | channelCreatorSigner,
37 | ] = await ethers.getSigners();
38 |
39 | ADMINSIGNER = adminSigner;
40 | ALICESIGNER = aliceSigner;
41 | BOBSIGNER = bobSigner;
42 | CHARLIESIGNER = charlieSigner;
43 | CHANNEL_CREATORSIGNER = channelCreatorSigner;
44 |
45 | ADMIN = await adminSigner.getAddress();
46 | ALICE = await aliceSigner.getAddress();
47 | BOB = await bobSigner.getAddress();
48 | CHARLIE = await charlieSigner.getAddress();
49 | CHANNEL_CREATOR = await channelCreatorSigner.getAddress();
50 |
51 | ({
52 | PROXYADMIN,
53 | EPNSCoreV1Proxy,
54 | EPNSCommV1Proxy,
55 | ROUTER,
56 | PushToken,
57 | EPNS_TOKEN_ADDRS,
58 | } = await loadFixture(epnsContractFixture));
59 | });
60 |
61 | describe("EPNS COMM: EIP 1271 & 712 Support", function () {
62 | const CHANNEL_TYPE = 2;
63 | const testChannel = ethers.utils.toUtf8Bytes("test-channel-hello-world");
64 |
65 | const getDomainParameters = (chainId, verifyingContract) => {
66 | const EPNS_DOMAIN = {
67 | name: "EPNS COMM V1",
68 | chainId: chainId,
69 | verifyingContract: verifyingContract,
70 | };
71 | return [EPNS_DOMAIN];
72 | };
73 |
74 | describe("Send Notification Tests", function () {
75 | beforeEach(async function () {
76 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).setEpnsCommunicatorAddress(
77 | EPNSCommV1Proxy.address
78 | );
79 | await EPNSCommV1Proxy.connect(ADMINSIGNER).setEPNSCoreAddress(
80 | EPNSCoreV1Proxy.address
81 | );
82 | await PushToken.transfer(BOB, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
83 | await PushToken.transfer(ALICE, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
84 | await PushToken.transfer(
85 | CHANNEL_CREATOR,
86 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
87 | );
88 | await PushToken.connect(BOBSIGNER).approve(
89 | EPNSCoreV1Proxy.address,
90 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
91 | );
92 | await PushToken.connect(ALICESIGNER).approve(
93 | EPNSCoreV1Proxy.address,
94 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
95 | );
96 | await PushToken.connect(CHANNEL_CREATORSIGNER).approve(
97 | EPNSCoreV1Proxy.address,
98 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION
99 | );
100 |
101 | // create a channel
102 | await EPNSCoreV1Proxy.connect(
103 | CHANNEL_CREATORSIGNER
104 | ).createChannelWithPUSH(
105 | CHANNEL_TYPE,
106 | testChannel,
107 | ADD_CHANNEL_MIN_POOL_CONTRIBUTION,
108 | 0
109 | );
110 | });
111 |
112 | const type = {
113 | SendNotification: [
114 | { name: "channel", type: "address" },
115 | { name: "recipient", type: "address" },
116 | { name: "identity", type: "bytes" },
117 | { name: "nonce", type: "uint256" },
118 | { name: "expiry", type: "uint256" },
119 | ],
120 | };
121 |
122 | it("Allows to send channel notification with 712 sig", async function () {
123 | const chainId = await EPNSCommV1Proxy.chainID().then((e) =>
124 | e.toNumber()
125 | );
126 | const [EPNS_DOMAIN, _] = getDomainParameters(
127 | chainId,
128 | EPNSCommV1Proxy.address
129 | );
130 |
131 | const [channel, subscriber, expiry] = [
132 | CHANNEL_CREATOR,
133 | BOBSIGNER.address,
134 | Date.now() + 3600,
135 | ];
136 |
137 | const nonce = await EPNSCommV1Proxy.nonces(channel);
138 | const message = {
139 | channel: channel,
140 | recipient: subscriber,
141 | identity: testChannel,
142 | nonce: nonce,
143 | expiry: expiry,
144 | };
145 |
146 | const signature = await CHANNEL_CREATORSIGNER._signTypedData(
147 | EPNS_DOMAIN,
148 | type,
149 | message
150 | );
151 | const { v, r, s } = ethers.utils.splitSignature(signature);
152 | const tx = EPNSCommV1Proxy.sendNotifBySig(
153 | channel,
154 | subscriber,
155 | CHANNEL_CREATOR,
156 | testChannel,
157 | nonce,
158 | expiry,
159 | v,
160 | r,
161 | s
162 | );
163 |
164 | await expect(tx).to.emit(EPNSCommV1Proxy, "SendNotification");
165 | });
166 |
167 | it("Allows delegatee to send notification with sig", async function () {
168 | const chainId = await EPNSCommV1Proxy.chainID().then((e) =>
169 | e.toNumber()
170 | );
171 | const [EPNS_DOMAIN, _] = getDomainParameters(
172 | chainId,
173 | EPNSCommV1Proxy.address
174 | );
175 |
176 | // Alice is not delegattee nut tries to send notification
177 | const [channel, subscriber, expiry] = [
178 | CHANNEL_CREATOR,
179 | BOBSIGNER.address,
180 | Date.now() + 3600,
181 | ];
182 | const nonce = await EPNSCommV1Proxy.nonces(channel);
183 | const message = {
184 | channel: channel,
185 | recipient: subscriber,
186 | identity: testChannel,
187 | nonce: nonce,
188 | expiry: expiry,
189 | };
190 | const signature = await ALICESIGNER._signTypedData(
191 | EPNS_DOMAIN,
192 | type,
193 | message
194 | );
195 | const { v, r, s } = ethers.utils.splitSignature(signature);
196 | var tx = await EPNSCommV1Proxy.callStatic.sendNotifBySig(
197 | channel,
198 | subscriber,
199 | ALICE,
200 | testChannel,
201 | nonce,
202 | expiry,
203 | v,
204 | r,
205 | s
206 | );
207 |
208 | // Not notification sent
209 | expect(tx).to.be.false;
210 |
211 | // Now channel creator adds Alice as delegattee
212 | await EPNSCommV1Proxy.connect(CHANNEL_CREATORSIGNER).addDelegate(ALICE);
213 |
214 | // Again alice tries to send notification with sig
215 | var tx = await EPNSCommV1Proxy.callStatic.sendNotifBySig(
216 | channel,
217 | subscriber,
218 | ALICE,
219 | testChannel,
220 | nonce,
221 | expiry,
222 | v,
223 | r,
224 | s
225 | );
226 | expect(tx).to.be.true;
227 |
228 | // Actual txn emits notification
229 | var tx = await EPNSCommV1Proxy.sendNotifBySig(
230 | channel,
231 | subscriber,
232 | ALICE,
233 | testChannel,
234 | nonce,
235 | expiry,
236 | v,
237 | r,
238 | s
239 | );
240 | await expect(tx).to.emit(EPNSCommV1Proxy, "SendNotification");
241 | });
242 |
243 | it("Allow to send channel notification with 1271 sig", async function () {
244 | // mock verifier contract
245 | const VerifierContract = await ethers
246 | .getContractFactory("SignatureVerifier")
247 | .then((c) => c.deploy());
248 | const chainId = await EPNSCommV1Proxy.chainID().then((e) =>
249 | e.toNumber()
250 | );
251 | const [EPNS_DOMAIN] = getDomainParameters(
252 | chainId,
253 | EPNSCommV1Proxy.address
254 | );
255 |
256 | // use verifier contract as subscriber
257 | const [channel, subscriber, expiry] = [
258 | VerifierContract.address,
259 | BOBSIGNER.address,
260 | Date.now() + 3600,
261 | ];
262 |
263 | const nonce = await EPNSCommV1Proxy.nonces(channel);
264 | const message = {
265 | channel: channel,
266 | recipient: subscriber,
267 | identity: testChannel,
268 | nonce: nonce,
269 | expiry: expiry,
270 | };
271 |
272 | // ALICE is not owner of Verifier Contract
273 | // so, ALIC signature is invalid
274 | // invalid signature should fail
275 | const invalid_signature = await ALICESIGNER._signTypedData(
276 | EPNS_DOMAIN,
277 | type,
278 | message
279 | );
280 | var { v, r, s } = ethers.utils.splitSignature(invalid_signature);
281 | var tx = await EPNSCommV1Proxy.callStatic.sendNotifBySig(
282 | channel,
283 | subscriber,
284 | VerifierContract.address,
285 | testChannel,
286 | nonce,
287 | expiry,
288 | v,
289 | r,
290 | s
291 | );
292 | // Invalid txn yields false
293 | await expect(tx).to.be.false;
294 |
295 | // Admin signer is owner of Verifier Contract
296 | // so Admin signer signs on behalf of contract
297 | const valid_signature = await ADMINSIGNER._signTypedData(
298 | EPNS_DOMAIN,
299 | type,
300 | message
301 | );
302 | var { v, r, s } = ethers.utils.splitSignature(valid_signature);
303 | var tx = await EPNSCommV1Proxy.callStatic.sendNotifBySig(
304 | channel,
305 | subscriber,
306 | VerifierContract.address,
307 | testChannel,
308 | nonce,
309 | expiry,
310 | v,
311 | r,
312 | s
313 | );
314 |
315 | // valid sig yields true
316 | await expect(tx).to.be.true;
317 |
318 | var tx = await EPNSCommV1Proxy.sendNotifBySig(
319 | channel,
320 | subscriber,
321 | VerifierContract.address,
322 | testChannel,
323 | nonce,
324 | expiry,
325 | v,
326 | r,
327 | s
328 | );
329 |
330 | // actual txn emits event
331 | await expect(tx).to.emit(EPNSCommV1Proxy, "SendNotification");
332 | });
333 |
334 | it("Returns false on signature replay", async function () {
335 | const chainId = await EPNSCommV1Proxy.chainID().then((e) =>
336 | e.toNumber()
337 | );
338 | const [EPNS_DOMAIN, _] = getDomainParameters(
339 | chainId,
340 | EPNSCommV1Proxy.address
341 | );
342 |
343 | const [channel, subscriber, expiry] = [
344 | CHANNEL_CREATORSIGNER.address,
345 | BOBSIGNER.address,
346 | Date.now() + 3600,
347 | ];
348 |
349 | const nonce = await EPNSCommV1Proxy.nonces(subscriber);
350 | const message = {
351 | channel: channel,
352 | recipient: subscriber,
353 | identity: testChannel,
354 | nonce: nonce,
355 | expiry: expiry,
356 | };
357 |
358 | const signature = await CHANNEL_CREATORSIGNER._signTypedData(
359 | EPNS_DOMAIN,
360 | type,
361 | message
362 | );
363 | const { v, r, s } = ethers.utils.splitSignature(signature);
364 | const tx = EPNSCommV1Proxy.sendNotifBySig(
365 | channel,
366 | subscriber,
367 | CHANNEL_CREATOR,
368 | testChannel,
369 | nonce,
370 | expiry,
371 | v,
372 | r,
373 | s
374 | );
375 | await expect(tx).to.emit(EPNSCommV1Proxy, "SendNotification");
376 |
377 | // should return false
378 | var tx2 = await EPNSCommV1Proxy.callStatic.sendNotifBySig(
379 | channel,
380 | subscriber,
381 | CHANNEL_CREATOR,
382 | testChannel,
383 | nonce,
384 | expiry,
385 | v,
386 | r,
387 | s
388 | );
389 | expect(tx2).to.be.false;
390 |
391 | // should not emit any envy
392 | var tx2 = EPNSCommV1Proxy.sendNotifBySig(
393 | channel,
394 | subscriber,
395 | CHANNEL_CREATOR,
396 | testChannel,
397 | nonce,
398 | expiry,
399 | v,
400 | r,
401 | s
402 | );
403 | await expect(tx2).to.not.emit(EPNSCommV1Proxy, "SendNotification");
404 | });
405 |
406 | it("Returns false on signature expire", async function () {
407 | const chainId = await EPNSCommV1Proxy.chainID().then((e) =>
408 | e.toNumber()
409 | );
410 | const [EPNS_DOMAIN, _] = getDomainParameters(
411 | chainId,
412 | EPNSCommV1Proxy.address
413 | );
414 |
415 | const [channel, subscriber, expiry] = [
416 | CHANNEL_CREATORSIGNER.address,
417 | BOBSIGNER.address,
418 | 3600,
419 | ];
420 |
421 | const nonce = await EPNSCommV1Proxy.nonces(subscriber);
422 | const message = {
423 | channel: channel,
424 | recipient: subscriber,
425 | identity: testChannel,
426 | nonce: nonce,
427 | expiry: expiry,
428 | };
429 |
430 | const signature = await CHANNEL_CREATORSIGNER._signTypedData(
431 | EPNS_DOMAIN,
432 | type,
433 | message
434 | );
435 | const { v, r, s } = ethers.utils.splitSignature(signature);
436 |
437 | // it should return false
438 | var tx = await EPNSCommV1Proxy.callStatic.sendNotifBySig(
439 | channel,
440 | subscriber,
441 | CHANNEL_CREATOR,
442 | testChannel,
443 | nonce,
444 | expiry,
445 | v,
446 | r,
447 | s
448 | );
449 | expect(tx).to.be.false;
450 |
451 | // it should not emit event
452 | var tx = EPNSCommV1Proxy.sendNotifBySig(
453 | channel,
454 | subscriber,
455 | CHANNEL_CREATOR,
456 | testChannel,
457 | nonce,
458 | expiry,
459 | v,
460 | r,
461 | s
462 | );
463 | await expect(tx).to.not.emit(EPNSCommV1Proxy, "SendNotification");
464 | });
465 | });
466 | });
467 | });
--------------------------------------------------------------------------------
/test/v2/core/IncentivizedChatRequest.test.js:
--------------------------------------------------------------------------------
1 | const { ethers, waffle } = require("hardhat");
2 |
3 | const { bn, tokensBN } = require("../../../helpers/utils");
4 |
5 | const { epnsContractFixture } = require("../../common/fixturesV2");
6 | const { expect } = require("../../common/expect");
7 | const createFixtureLoader = waffle.createFixtureLoader;
8 |
9 | describe("Incentivized chats", function () {
10 | const ADD_CHANNEL_MIN_POOL_CONTRIBUTION = tokensBN(50);
11 |
12 | let PushToken;
13 | let EPNSCoreV1Proxy;
14 | let EPNSCommV1Proxy;
15 | let ALICE;
16 | let BOB;
17 | let CHANNEL_CREATOR;
18 | let ADMINSIGNER;
19 | let ALICESIGNER;
20 | let BOBSIGNER;
21 | let CHARLIESIGNER;
22 | let CHANNEL_CREATORSIGNER;
23 |
24 | let loadFixture;
25 | before(async () => {
26 | [wallet, other] = await ethers.getSigners();
27 | loadFixture = createFixtureLoader([wallet, other]);
28 | });
29 |
30 | beforeEach(async function () {
31 | // Get the ContractFactory and Signers here.
32 | const [
33 | adminSigner,
34 | aliceSigner,
35 | bobSigner,
36 | charlieSigner,
37 | channelCreatorSigner,
38 | ] = await ethers.getSigners();
39 |
40 | ADMINSIGNER = adminSigner;
41 | ALICESIGNER = aliceSigner;
42 | BOBSIGNER = bobSigner;
43 | CHARLIESIGNER = charlieSigner;
44 | CHANNEL_CREATORSIGNER = channelCreatorSigner;
45 |
46 | ADMIN = await adminSigner.getAddress();
47 | ALICE = await aliceSigner.getAddress();
48 | BOB = await bobSigner.getAddress();
49 | CHARLIE = await charlieSigner.getAddress();
50 | CHANNEL_CREATOR = await channelCreatorSigner.getAddress();
51 |
52 | ({
53 | PROXYADMIN,
54 | EPNSCoreV1Proxy,
55 | EPNSCommV1Proxy,
56 | ROUTER,
57 | PushToken,
58 | EPNS_TOKEN_ADDRS,
59 | } = await loadFixture(epnsContractFixture));
60 | await EPNSCommV1Proxy.setPushTokenAddress(PushToken.address);
61 | // await EPNSCoreV1Proxy.setFeeAmount(10);
62 |
63 | await PushToken.transfer(BOB, ethers.utils.parseEther("10000"));
64 | await PushToken.transfer(ALICE, ethers.utils.parseEther("10000"));
65 | await PushToken.transfer(CHARLIE, ethers.utils.parseEther("10000"));
66 | await PushToken.transfer(CHANNEL_CREATOR, ethers.utils.parseEther("10000"));
67 | await PushToken.connect(BOBSIGNER).approve(
68 | EPNSCommV1Proxy.address,
69 | ethers.utils.parseEther("10000")
70 | );
71 | await PushToken.connect(ALICESIGNER).approve(
72 | EPNSCommV1Proxy.address,
73 | ethers.utils.parseEther("10000")
74 | );
75 | await PushToken.connect(CHARLIESIGNER).approve(
76 | EPNSCommV1Proxy.address,
77 | ethers.utils.parseEther("10000")
78 | );
79 | await PushToken.connect(CHANNEL_CREATORSIGNER).approve(
80 | EPNSCommV1Proxy.address,
81 | ethers.utils.parseEther("10000")
82 | );
83 | });
84 |
85 | it("should transfer tokens to core", async () => {
86 | const BobBalanceBefore = await PushToken.balanceOf(BOB);
87 | const CoreBalanceBefore = await PushToken.balanceOf(
88 | EPNSCoreV1Proxy.address
89 | );
90 | await EPNSCommV1Proxy.connect(BOBSIGNER).createIncentivizeChatRequest(
91 | ALICE,
92 | ethers.utils.parseEther("100")
93 | );
94 | const BobBalanceAfter = await PushToken.balanceOf(BOB);
95 | const CoreBalanceAfter = await PushToken.balanceOf(EPNSCoreV1Proxy.address);
96 | expect(BobBalanceAfter).to.be.equal(ethers.utils.parseEther("9900"));
97 | expect(CoreBalanceAfter).to.be.equal(ethers.utils.parseEther("100"));
98 | });
99 | it("should update the struct", async () => {
100 | await EPNSCommV1Proxy.connect(BOBSIGNER).createIncentivizeChatRequest(
101 | ALICE,
102 | ethers.utils.parseEther("100")
103 | );
104 | blockTimestamp = (await ethers.provider.getBlock("latest")).timestamp;
105 |
106 | const chatData = await EPNSCommV1Proxy.userChatData(BOB);
107 |
108 | expect(chatData.requestSender).to.be.equal(BOB);
109 |
110 | expect(chatData.timestamp).to.be.equal(blockTimestamp);
111 |
112 | expect(chatData.amountDeposited).to.be.equal(
113 | ethers.utils.parseEther("100")
114 | );
115 | });
116 |
117 | it("should call handleChatRequest in core and it should fail if caller is not Comm ", async () => {
118 | await expect(
119 | EPNSCoreV1Proxy.handleChatRequestData(
120 | BOB,
121 | ALICE,
122 | ethers.utils.parseEther("100")
123 | )
124 | ).to.be.revertedWith(
125 | "PushCoreV2:handleChatRequestData::Unauthorized caller"
126 | );
127 | const beforeCelebFunds = await EPNSCoreV1Proxy.celebUserFunds(ALICE);
128 | const beforePoolFees = await EPNSCoreV1Proxy.PROTOCOL_POOL_FEES();
129 | await EPNSCommV1Proxy.connect(BOBSIGNER).createIncentivizeChatRequest(
130 | ALICE,
131 | ethers.utils.parseEther("100")
132 | );
133 | const expectedCelebFunds = beforeCelebFunds + ethers.utils.parseEther("90");
134 | const expectedPoolFees = beforeCelebFunds + ethers.utils.parseEther("10");
135 | expect(await EPNSCoreV1Proxy.celebUserFunds(ALICE)).to.be.equal(
136 | expectedCelebFunds
137 | );
138 | expect(await EPNSCoreV1Proxy.PROTOCOL_POOL_FEES()).to.be.equal(
139 | expectedPoolFees
140 | );
141 | });
142 |
143 | it("should emit events in both contracts ", async () => {
144 | const txn = await EPNSCommV1Proxy.connect(
145 | BOBSIGNER
146 | ).createIncentivizeChatRequest(ALICE, ethers.utils.parseEther("100"));
147 |
148 | await expect(txn)
149 | .to.emit(EPNSCommV1Proxy, "IncentivizeChatReqInitiated")
150 | .withArgs(
151 | BOB,
152 | ALICE,
153 | ethers.utils.parseEther("100"),
154 | (
155 | await ethers.provider.getBlock("latest")
156 | ).timestamp
157 | );
158 |
159 | await expect(txn)
160 | .to.emit(EPNSCoreV1Proxy, "IncentivizeChatReqReceived")
161 | .withArgs(
162 | BOB,
163 | ALICE,
164 | ethers.utils.parseEther("90"),
165 | await EPNSCoreV1Proxy.FEE_AMOUNT(),
166 | (
167 | await ethers.provider.getBlock("latest")
168 | ).timestamp
169 | );
170 | });
171 |
172 | it("celeb should be able to claim the funds", async () => {
173 | await EPNSCommV1Proxy.connect(BOBSIGNER).createIncentivizeChatRequest(
174 | ALICE,
175 | ethers.utils.parseEther("100")
176 | );
177 | const beforeBalance = await PushToken.balanceOf(ALICE);
178 | const avaialbleToClaim = await EPNSCoreV1Proxy.celebUserFunds(ALICE);
179 | const claim = avaialbleToClaim.toString();
180 | await EPNSCoreV1Proxy.connect(ALICESIGNER).claimChatIncentives(claim);
181 |
182 | const expectedBalance = beforeBalance.add(avaialbleToClaim);
183 | expect(await PushToken.balanceOf(ALICE)).to.be.equal(expectedBalance);
184 | });
185 |
186 | describe("Multiple celebs", async () => {
187 |
188 | beforeEach(async()=>{
189 | await EPNSCommV1Proxy.connect(BOBSIGNER).createIncentivizeChatRequest(
190 | ALICE,
191 | ethers.utils.parseEther("100")
192 | );
193 | await EPNSCommV1Proxy.connect(BOBSIGNER).createIncentivizeChatRequest(
194 | CHARLIE,
195 | ethers.utils.parseEther("100")
196 | );
197 | })
198 | it("Should update the struct", async () => {
199 |
200 | blockTimestamp = (await ethers.provider.getBlock("latest")).timestamp;
201 |
202 | const chatData = await EPNSCommV1Proxy.userChatData(BOB);
203 |
204 | expect(chatData.requestSender).to.be.equal(BOB);
205 | expect(chatData.timestamp).to.be.equal(blockTimestamp);
206 | expect(chatData.amountDeposited).to.be.equal(
207 | ethers.utils.parseEther("200")
208 | );
209 | });
210 | it("ALICE should be able to withdraw funds",async()=>{
211 | const beforeBalance = await PushToken.balanceOf(ALICE);
212 | const avaialbleToClaim = await EPNSCoreV1Proxy.celebUserFunds(ALICE);
213 | const claim = avaialbleToClaim.toString();
214 | expect(claim).to.be.equal(ethers.utils.parseEther("90"))
215 | await EPNSCoreV1Proxy.connect(ALICESIGNER).claimChatIncentives(claim);
216 |
217 | const expectedBalance = beforeBalance.add(avaialbleToClaim);
218 | expect(await PushToken.balanceOf(ALICE)).to.be.equal(expectedBalance);
219 | })
220 | it("CHARLIE should be able to withdraw funds",async()=>{
221 | const beforeBalance = await PushToken.balanceOf(CHARLIE);
222 | const avaialbleToClaim = await EPNSCoreV1Proxy.celebUserFunds(CHARLIE);
223 | const claim = avaialbleToClaim.toString();
224 | expect(claim).to.be.equal(ethers.utils.parseEther("90"))
225 | await EPNSCoreV1Proxy.connect(CHARLIESIGNER).claimChatIncentives(claim);
226 |
227 | const expectedBalance = beforeBalance.add(avaialbleToClaim);
228 | expect(await PushToken.balanceOf(CHARLIE)).to.be.equal(expectedBalance);
229 | })
230 | });
231 | });
232 |
--------------------------------------------------------------------------------
/test/v2/core/Pausability.test.js:
--------------------------------------------------------------------------------
1 | const { ethers,waffle } = require("hardhat");
2 | const {epnsContractFixture} = require("../../common/fixturesV2")
3 | const {expect} = require("../../common/expect")
4 | const createFixtureLoader = waffle.createFixtureLoader;
5 |
6 | const {
7 | tokensBN,
8 | } = require("../../../helpers/utils");
9 |
10 | describe("EPNS Core Protocol", function () {
11 | const ADD_CHANNEL_MIN_POOL_CONTRIBUTION = tokensBN(50)
12 |
13 | let EPNSCoreV1Proxy;
14 | let EPNSCommV1Proxy;
15 | let MOCKDAI;
16 | let CHANNEL_CREATOR;
17 | let ADMINSIGNER;
18 | let CHANNEL_CREATORSIGNER;
19 | let PushToken;
20 |
21 |
22 | let loadFixture;
23 | before(async() => {
24 | [wallet, other] = await ethers.getSigners()
25 | loadFixture = createFixtureLoader([wallet, other])
26 | });
27 |
28 | beforeEach(async function () {
29 | // Get the ContractFactory and Signers here.
30 | const [
31 | adminSigner,
32 | aliceSigner,
33 | bobSigner,
34 | charlieSigner,
35 | channelCreatorSigner,
36 | ] = await ethers.getSigners();
37 |
38 | ADMINSIGNER = adminSigner;
39 | ALICESIGNER = aliceSigner;
40 | BOBSIGNER = bobSigner;
41 | CHARLIESIGNER = charlieSigner;
42 | CHANNEL_CREATORSIGNER = channelCreatorSigner;
43 |
44 | ADMIN = await adminSigner.getAddress();
45 | ALICE = await aliceSigner.getAddress();
46 | BOB = await bobSigner.getAddress();
47 | CHARLIE = await charlieSigner.getAddress();
48 | CHANNEL_CREATOR = await channelCreatorSigner.getAddress();
49 |
50 |
51 | ({
52 | PROXYADMIN,
53 | EPNSCoreV1Proxy,
54 | EPNSCommV1Proxy,
55 | ROUTER,
56 | PushToken,
57 | EPNS_TOKEN_ADDRS,
58 | } = await loadFixture(epnsContractFixture));
59 |
60 | });
61 |
62 | describe("EPNS CORE: Channel Creation Tests", function(){
63 | describe("Testing the Base Create Channel Function", function()
64 | {
65 | const CHANNEL_TYPE = 2;
66 | const testChannel = ethers.utils.toUtf8Bytes("test-channel-hello-world");
67 |
68 | beforeEach(async function(){
69 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).setEpnsCommunicatorAddress(EPNSCommV1Proxy.address)
70 | await EPNSCommV1Proxy.connect(ADMINSIGNER).setEPNSCoreAddress(EPNSCoreV1Proxy.address);
71 |
72 | await PushToken.transfer(CHANNEL_CREATOR, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
73 | await PushToken.connect(CHANNEL_CREATORSIGNER).approve(EPNSCoreV1Proxy.address, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
74 | });
75 | /**
76 | * "createChannelWithFees" Function CheckPoints
77 | * REVERT CHECKS
78 | * Should revert IF EPNSCoreV1::onlyInactiveChannels: Channel already Activated
79 | * Should revert if Channel Type is NOT THE Allowed One
80 | * Should revert if AMOUNT Passed if Not greater than or equal to the 'ADD_CHANNEL_MIN_POOL_CONTRIBUTION'
81 | *
82 | * FUNCTION Execution CHECKS
83 | * The Channel Creation Fees should be Transferred to the EPNS Core Proxy
84 | * Should deposit funds to the POOL and Recieve aDAI
85 | * Should Update the State Variables Correctly and Activate the Channel
86 | * Readjustment of the FS Ratio should be checked
87 | * Should Interact successfully with EPNS Communicator and Subscribe Channel Owner to his own Channel
88 | * Should subscribe Channel owner to 0x000 channel
89 | * Should subscribe ADMIN to the Channel Creator's Channel
90 | **/
91 |
92 | it("Should revert if IF EPNSCoreV1::onlyInactiveChannels: Channel already Activated ", async function () {
93 | const CHANNEL_TYPE = 2;
94 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel,ADD_CHANNEL_MIN_POOL_CONTRIBUTION,0)
95 | await expect(
96 | EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel,ADD_CHANNEL_MIN_POOL_CONTRIBUTION,0)
97 | ).to.be.revertedWith("PushCoreV2::onlyInactiveChannels: Channel already Activated")
98 | });
99 |
100 | // Pauseable Tests
101 | it("Contract should only be Paused via GOVERNANCE", async function(){
102 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).pauseContract();
103 |
104 | await expect(tx).to.be.revertedWith('PushCoreV2::onlyGovernance: Invalid Caller')
105 | });
106 |
107 | it("Contract should only be UnPaused via GOVERNANCE", async function(){
108 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).unPauseContract();
109 |
110 | await expect(tx).to.be.revertedWith('PushCoreV2::onlyGovernance: Invalid Caller')
111 | });
112 |
113 | it("Channel Creation Should not be executed if Contract is Paused", async function(){
114 | const CHANNEL_TYPE = 2;
115 |
116 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).pauseContract();
117 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel,ADD_CHANNEL_MIN_POOL_CONTRIBUTION,0)
118 |
119 | await expect(tx).to.be.revertedWith("Pausable: paused")
120 | });
121 |
122 | it("Channel Creation Should execute after UNPAUSE", async function(){
123 | const CHANNEL_TYPE = 2;
124 |
125 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).pauseContract();
126 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel,ADD_CHANNEL_MIN_POOL_CONTRIBUTION,0)
127 |
128 | await expect(tx).to.be.revertedWith("Pausable: paused");
129 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).unPauseContract();
130 | const tx_2 = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel,ADD_CHANNEL_MIN_POOL_CONTRIBUTION,0)
131 |
132 | await expect(tx_2)
133 | .to.emit(EPNSCoreV1Proxy, 'AddChannel')
134 | .withArgs(CHANNEL_CREATOR, CHANNEL_TYPE, ethers.utils.hexlify(testChannel));
135 |
136 | });
137 |
138 | it("Channel Deactivation Should not be executed if Contract is Paused", async function(){
139 | const CHANNEL_TYPE = 2;
140 |
141 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).pauseContract();
142 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).deactivateChannel();
143 |
144 | await expect(tx).to.be.revertedWith("Pausable: paused")
145 | });
146 |
147 | it("Channel Reactivation Should not be executed if Contract is Paused", async function(){
148 | const CHANNEL_TYPE = 2;
149 |
150 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).pauseContract();
151 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).reactivateChannel(ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
152 |
153 | await expect(tx).to.be.revertedWith("Pausable: paused")
154 | });
155 |
156 | it("Channel Blocking Should not be executed if Contract is Paused", async function(){
157 | const CHANNEL_TYPE = 2;
158 |
159 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).pauseContract();
160 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).blockChannel(CHANNEL_CREATOR);
161 |
162 | await expect(tx).to.be.revertedWith("Pausable: paused")
163 | });
164 | });
165 |
166 | });
167 | });
--------------------------------------------------------------------------------
/test/v2/core/TimeBoundChannel.test.js:
--------------------------------------------------------------------------------
1 | const { ethers,waffle } = require("hardhat");
2 |
3 | const {
4 | bn,
5 | tokensBN,
6 | } = require("../../../helpers/utils");
7 |
8 |
9 | const {epnsContractFixture} = require("../../common/fixturesV2")
10 | const {expect} = require("../../common/expect")
11 | const createFixtureLoader = waffle.createFixtureLoader;
12 |
13 | describe("EPNS CoreV2 Protocol", function () {
14 | const ADD_CHANNEL_MIN_POOL_CONTRIBUTION = tokensBN(50)
15 | const CHANNEL_DEACTIVATION_FEES = tokensBN(10)
16 | const ADD_CHANNEL_MAX_POOL_CONTRIBUTION = tokensBN(250 * 50)
17 | const ADJUST_FOR_FLOAT = bn(10 ** 7)
18 |
19 | let PushToken;
20 | let EPNSCoreV1Proxy;
21 | let EPNSCommV1Proxy;
22 | let ADMIN;
23 | let ALICE;
24 | let BOB;
25 | let CHARLIE;
26 | let CHANNEL_CREATOR;
27 | let ADMINSIGNER;
28 | let ALICESIGNER;
29 | let BOBSIGNER;
30 | let CHARLIESIGNER;
31 | let CHANNEL_CREATORSIGNER;
32 |
33 |
34 | let loadFixture;
35 | before(async() => {
36 | [wallet, other] = await ethers.getSigners()
37 | loadFixture = createFixtureLoader([wallet, other])
38 | });
39 |
40 | beforeEach(async function () {
41 | // Get the ContractFactory and Signers here.
42 | const [
43 | adminSigner,
44 | aliceSigner,
45 | bobSigner,
46 | charlieSigner,
47 | channelCreatorSigner,
48 | ] = await ethers.getSigners();
49 |
50 | ADMINSIGNER = adminSigner;
51 | ALICESIGNER = aliceSigner;
52 | BOBSIGNER = bobSigner;
53 | CHARLIESIGNER = charlieSigner;
54 | CHANNEL_CREATORSIGNER = channelCreatorSigner;
55 |
56 | ADMIN = await adminSigner.getAddress();
57 | ALICE = await aliceSigner.getAddress();
58 | BOB = await bobSigner.getAddress();
59 | CHARLIE = await charlieSigner.getAddress();
60 | CHANNEL_CREATOR = await channelCreatorSigner.getAddress();
61 |
62 |
63 | ({
64 | PROXYADMIN,
65 | EPNSCoreV1Proxy,
66 | EPNSCommV1Proxy,
67 | ROUTER,
68 | PushToken,
69 | EPNS_TOKEN_ADDRS,
70 | } = await loadFixture(epnsContractFixture));
71 |
72 | });
73 |
74 |
75 | describe("EPNS CORE: Channel Creation Tests", function(){
76 | describe("Testing the Base Create Channel Function", function(){
77 | const CHANNEL_TYPE = 2;
78 | const TIME_BOUND_CHANNEL_TYPE = 4;
79 | const testChannel = ethers.utils.toUtf8Bytes("test-channel-hello-world");
80 | const ONE_DAY = 3600*24;
81 |
82 | beforeEach(async function(){
83 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).setEpnsCommunicatorAddress(EPNSCommV1Proxy.address)
84 | await EPNSCommV1Proxy.connect(ADMINSIGNER).setEPNSCoreAddress(EPNSCoreV1Proxy.address);
85 | await PushToken.transfer(BOB, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
86 | await PushToken.transfer(ALICE, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
87 | await PushToken.transfer(CHANNEL_CREATOR, ADD_CHANNEL_MIN_POOL_CONTRIBUTION.mul(10));
88 | await PushToken.connect(BOBSIGNER).approve(EPNSCoreV1Proxy.address, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
89 | await PushToken.connect(ALICESIGNER).approve(EPNSCoreV1Proxy.address, ADD_CHANNEL_MIN_POOL_CONTRIBUTION);
90 | await PushToken.connect(CHANNEL_CREATORSIGNER).approve(EPNSCoreV1Proxy.address, ADD_CHANNEL_MIN_POOL_CONTRIBUTION.mul(10));
91 | });
92 |
93 | const getFutureTIme = async (futureTime) =>{
94 | const blockNumber = await ethers.provider.getBlockNumber();
95 | const block = await ethers.provider.getBlock(blockNumber);
96 | return block.timestamp + futureTime;
97 | }
98 | const passTime = async(time)=>{
99 | await network.provider.send("evm_increaseTime", [time]);
100 | await network.provider.send("evm_mine");
101 | }
102 |
103 | it("Should allow to create time bound channel", async function(){
104 | const expiryTime = await getFutureTIme(ONE_DAY);
105 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
106 |
107 | await expect(tx)
108 | .to.emit(EPNSCoreV1Proxy, 'AddChannel')
109 | .withArgs(CHANNEL_CREATOR, TIME_BOUND_CHANNEL_TYPE, ethers.utils.hexlify(testChannel));
110 | });
111 |
112 | it("Should revert on creating channel with invalid expiry", async function(){
113 | await expect(
114 | EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, 0)
115 | ).to.be.revertedWith("PushCoreV2::createChannel: Invalid channelExpiryTime");
116 |
117 | // allow with valid channel type
118 | const expiryTime = await getFutureTIme(ONE_DAY);
119 | const tx = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
120 | await expect(tx).to.emit(EPNSCoreV1Proxy, 'AddChannel')
121 | });
122 |
123 | it("Should set correct _channelExpiryTime value", async function(){
124 | const expiryTime = await getFutureTIme(ONE_DAY);
125 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
126 | const channelInfo = await EPNSCoreV1Proxy.channels(CHANNEL_CREATOR);
127 | expect(channelInfo.expiryTime).to.equal(expiryTime);
128 | expect(channelInfo.channelType).to.equal(TIME_BOUND_CHANNEL_TYPE);
129 | });
130 |
131 | it("It allows creator to destroy the time bound channel", async function(){
132 | const expiryTime = await getFutureTIme(ONE_DAY);
133 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
134 |
135 | await passTime(ONE_DAY);
136 |
137 | const txn = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
138 |
139 | await expect(txn)
140 | .to.emit(EPNSCoreV1Proxy,"TimeBoundChannelDestroyed")
141 | .withArgs(CHANNEL_CREATOR, ADD_CHANNEL_MIN_POOL_CONTRIBUTION.sub(CHANNEL_DEACTIVATION_FEES));
142 | });
143 |
144 | it("Should only allow channel destruction after time is reached", async function(){
145 | const expiryTime = await getFutureTIme(15*ONE_DAY);
146 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
147 | const txn = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
148 | await expect(txn)
149 | .to.be.revertedWith("PushCoreV2::destroyTimeBoundChannel: Invalid Caller or Channel Not Expired'");
150 |
151 | // after time pass channel should be able to destoryed
152 | await passTime(15*ONE_DAY)
153 |
154 | const txn2 = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
155 | await expect(txn2)
156 | .to.emit(EPNSCoreV1Proxy,"TimeBoundChannelDestroyed");
157 | });
158 |
159 | it("Should allow allow admin channel destruction after time is reached + 14days", async function(){
160 | const expiryTime = await getFutureTIme(15*ONE_DAY);
161 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
162 | const txn = EPNSCoreV1Proxy.connect(ADMINSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
163 | await expect(txn)
164 | .to.be.revertedWith("PushCoreV2::destroyTimeBoundChannel: Invalid Caller or Channel Not Expired'");
165 |
166 | // after time pass channel should be able to destoryed
167 | await passTime(15*ONE_DAY + 14*ONE_DAY)
168 |
169 | const txn2 = EPNSCoreV1Proxy.connect(ADMINSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
170 | await expect(txn2)
171 | .to.emit(EPNSCoreV1Proxy,"TimeBoundChannelDestroyed");
172 | });
173 |
174 | it("Should decrement channel count on channel Destroty", async function(){
175 | const expiryTime = await getFutureTIme(ONE_DAY);
176 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
177 | const channelCountBefore = await EPNSCoreV1Proxy.channelsCount();
178 |
179 | await passTime(ONE_DAY);
180 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
181 |
182 | const channelCountAfter = await EPNSCoreV1Proxy.channelsCount();
183 | await expect(channelCountAfter).to.equal(channelCountBefore-1);
184 | });
185 |
186 | it("Gives refunds on channel destroy", async function(){
187 | const expiryTime = await getFutureTIme(ONE_DAY);
188 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
189 | const userBalBefore = await PushToken.balanceOf(CHANNEL_CREATOR);
190 |
191 | await passTime(ONE_DAY);
192 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
193 |
194 | const userBalAfter = await PushToken.balanceOf(CHANNEL_CREATOR);
195 | const expectedUserBalance = userBalBefore.add(ADD_CHANNEL_MIN_POOL_CONTRIBUTION.sub(CHANNEL_DEACTIVATION_FEES));
196 | expect(userBalAfter).to.equal(expectedUserBalance);
197 | });
198 |
199 | it("Reverts on destroying others channel", async function(){
200 | const expiryTime = await getFutureTIme(ONE_DAY);
201 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
202 |
203 | await passTime(ONE_DAY);
204 | const txn = EPNSCoreV1Proxy.connect(BOBSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
205 |
206 | await expect(txn).to.be.revertedWith("PushCoreV2::destroyTimeBoundChannel: Invalid Caller or Channel Not Expired'");
207 | });
208 |
209 | it("Reverts if user destroys channel twice", async function(){
210 | const expiryTime = await getFutureTIme(ONE_DAY);
211 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
212 | await passTime(ONE_DAY);
213 |
214 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
215 | const txn = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
216 |
217 | await expect(txn).to.be.revertedWith("PushCoreV2::onlyActivatedChannels: Invalid Channel");
218 | });
219 |
220 | it.skip("Should revert on Destroying the Deactivated channel", async function(){
221 | const expiryTime = await getFutureTIme(ONE_DAY);
222 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
223 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).deactivateChannel()
224 |
225 | await passTime(ONE_DAY);
226 |
227 | // const txn = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
228 | // await expect(txn).to.be.revertedWith("PushCoreV2::onlyActivatedChannels: Invalid Channel");
229 | });
230 |
231 | it("Should revert on Deactivating the Destroyed channel", async function(){
232 | const expiryTime = await getFutureTIme(ONE_DAY);
233 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
234 |
235 | await passTime(ONE_DAY);
236 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
237 |
238 | const txn = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).deactivateChannel()
239 | await expect(txn).to.be.revertedWith("PushCoreV2::onlyActivatedChannels: Invalid Channel");
240 | });
241 |
242 | it("Should allow user to create channel again after destroying", async function(){
243 | var expiryTime = await getFutureTIme(ONE_DAY);
244 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
245 |
246 | await passTime(ONE_DAY);
247 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
248 |
249 | var expiryTime = await getFutureTIme(ONE_DAY);
250 | const txn = EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
251 | await expect(txn).to.emit(EPNSCoreV1Proxy,"AddChannel");
252 | });
253 |
254 | it("Channel destruction unsubscribes to all", async function(){
255 | var expiryTime = await getFutureTIme(ONE_DAY);
256 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_POOL_CONTRIBUTION, expiryTime);
257 |
258 | // before destruction should subscribe to these
259 | var isSubscribedToOwnChannel = await EPNSCommV1Proxy.isUserSubscribed(CHANNEL_CREATOR, CHANNEL_CREATOR);
260 | var isSubscribedTOChannelAlerter = await EPNSCommV1Proxy.isUserSubscribed(ethers.constants.AddressZero, CHANNEL_CREATOR);
261 | var isEPNSAdminSubscribed = await EPNSCommV1Proxy.isUserSubscribed(CHANNEL_CREATOR, ADMIN);
262 | expect(isSubscribedToOwnChannel).to.be.true;
263 | expect(isSubscribedTOChannelAlerter).to.be.true;
264 | expect(isEPNSAdminSubscribed).to.be.true;
265 |
266 | await passTime(ONE_DAY);
267 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
268 |
269 | // after destruction should unsubscribe to these
270 | var isSubscribedToOwnChannel = await EPNSCommV1Proxy.isUserSubscribed(CHANNEL_CREATOR, CHANNEL_CREATOR);
271 | var isSubscribedTOChannelAlerter = await EPNSCommV1Proxy.isUserSubscribed(ethers.constants.AddressZero, CHANNEL_CREATOR);
272 | var isEPNSAdminSubscribed = await EPNSCommV1Proxy.isUserSubscribed(CHANNEL_CREATOR, ADMIN);
273 | expect(isSubscribedToOwnChannel).to.be.false;
274 | expect(isSubscribedTOChannelAlerter).to.be.false;
275 | expect(isEPNSAdminSubscribed).to.be.false;
276 | });
277 |
278 | it("Should delete channel info after channel destroy", async function(){
279 | var expiryTime = await getFutureTIme(ONE_DAY);
280 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).createChannelWithPUSH(TIME_BOUND_CHANNEL_TYPE, testChannel,ADD_CHANNEL_MIN_POOL_CONTRIBUTION,expiryTime);
281 | const fullChannelInfo = await EPNSCoreV1Proxy.channels(CHANNEL_CREATOR);
282 | // destroy channel
283 | await passTime(ONE_DAY);
284 | await EPNSCoreV1Proxy.connect(CHANNEL_CREATORSIGNER).destroyTimeBoundChannel(CHANNEL_CREATOR);
285 |
286 | const channelInfo = await EPNSCoreV1Proxy.channels(CHANNEL_CREATOR);
287 | const emptyChannelInfo = await EPNSCoreV1Proxy.channels(CHARLIE);
288 | expect(channelInfo.toString()).to.equal(emptyChannelInfo.toString());
289 |
290 | });
291 | });
292 | });
293 | });
--------------------------------------------------------------------------------
/test/v2/core/UpdateChannelMeta.test.js:
--------------------------------------------------------------------------------
1 | const { ethers,waffle} = require("hardhat");
2 | const {epnsContractFixture} = require("../../common/fixturesV2")
3 | const {expect} = require("../../common/expect")
4 | const createFixtureLoader = waffle.createFixtureLoader;
5 |
6 | const {
7 | tokensBN,
8 | } = require("../../../helpers/utils");
9 |
10 | describe("EPNS CoreV2 Protocol", function () {
11 | const FEE_AMOUNT = tokensBN(10)
12 | const ADJUST_FOR_FLOAT = bn(10 ** 7)
13 | const MIN_POOL_CONTRIBUTION = tokensBN(1)
14 | const ADD_CHANNEL_MIN_FEES = tokensBN(50)
15 | const ADD_CHANNEL_MAX_POOL_CONTRIBUTION = tokensBN(250 * 50)
16 |
17 | let EPNSCoreV1Proxy;
18 | let EPNSCommV1Proxy;
19 | let ALICE;
20 | let BOB;
21 | let ADMINSIGNER;
22 | let ALICESIGNER;
23 | let BOBSIGNER;
24 |
25 |
26 | let loadFixture;
27 | before(async() => {
28 | [wallet, other] = await ethers.getSigners()
29 | loadFixture = createFixtureLoader([wallet, other])
30 | });
31 |
32 | beforeEach(async function () {
33 | // Get the ContractFactory and Signers here.
34 | const [
35 | adminSigner,
36 | aliceSigner,
37 | bobSigner,
38 | charlieSigner,
39 | channelCreatorSigner,
40 | ] = await ethers.getSigners();
41 |
42 | ADMINSIGNER = adminSigner;
43 | ALICESIGNER = aliceSigner;
44 | BOBSIGNER = bobSigner;
45 | CHARLIESIGNER = charlieSigner;
46 | CHANNEL_CREATORSIGNER = channelCreatorSigner;
47 |
48 | ADMIN = await adminSigner.getAddress();
49 | ALICE = await aliceSigner.getAddress();
50 | BOB = await bobSigner.getAddress();
51 | CHARLIE = await charlieSigner.getAddress();
52 | CHANNEL_CREATOR = await channelCreatorSigner.getAddress();
53 |
54 | ({
55 | PROXYADMIN,
56 | EPNSCoreV1Proxy,
57 | EPNSCommV1Proxy,
58 | ROUTER,
59 | PushToken,
60 | EPNS_TOKEN_ADDRS,
61 | } = await loadFixture(epnsContractFixture));
62 |
63 | });
64 |
65 | describe("EPNS CORE: Channel Creation Tests", function(){
66 | describe("Testing the Base Create Channel Function", function()
67 | {
68 | const CHANNEL_TYPE = 2;
69 | const testChannel = ethers.utils.toUtf8Bytes("test-channel-hello-world");
70 | const channelNewIdentity = ethers.utils.toUtf8Bytes("test-channel-hello-world");
71 |
72 | beforeEach(async function(){
73 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).setMinPoolContribution(ethers.utils.parseEther('1'));
74 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).setEpnsCommunicatorAddress(EPNSCommV1Proxy.address)
75 | await EPNSCommV1Proxy.connect(ADMINSIGNER).setEPNSCoreAddress(EPNSCoreV1Proxy.address);
76 | await PushToken.transfer(BOB, ADD_CHANNEL_MIN_FEES.mul(20));
77 | await PushToken.transfer(ALICE, ADD_CHANNEL_MIN_FEES.mul(20));
78 | await PushToken.connect(BOBSIGNER).approve(EPNSCoreV1Proxy.address, ADD_CHANNEL_MIN_FEES.mul(20));
79 | await PushToken.connect(ALICESIGNER).approve(EPNSCoreV1Proxy.address, ADD_CHANNEL_MIN_FEES.mul(20));
80 |
81 | await EPNSCoreV1Proxy.connect(BOBSIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_FEES,0);
82 | await EPNSCoreV1Proxy.connect(ALICESIGNER).createChannelWithPUSH(CHANNEL_TYPE, testChannel, ADD_CHANNEL_MIN_FEES,0);
83 | });
84 | /**
85 | * "updateChannelMeta" Function CheckPoints
86 | * REVERT CHECKS
87 | * Should revert IF Contract is Paused
88 | * Should revert if Caller is not the Channel Owner
89 | * If Channel Creator is Updating Channel Meta for first time:
90 | * => Fee Amount should be at least 50 PUSH Tokens, else Revert
91 | *
92 | * If Channel Creator is Updating Channel Meta for N time:
93 | * => Fee Amount should be at least (50 * N) PUSH Tokens, else Revert
94 | *
95 | * FUNCTION Execution CHECKS
96 | * Should charge 50 PUSH Tokens for first time update
97 | * Should charge 100, 150, 200 PUSH Tokens for 2nd, 3rd or 4th time update.
98 | * Should update the PROTOCOL_POOL_FEES state variable
99 | * Should increase the channel's update counter by 1
100 | * Should update the update block number for the channel
101 | * Should transfer the PUSH Tokens from User to Channel
102 | * Should emit the event with right args
103 | **/
104 |
105 | // Pauseable Tests
106 | it("Should revert IF Contract is Paused", async function(){
107 | await EPNSCoreV1Proxy.connect(ADMINSIGNER).pauseContract();
108 | const tx = EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
109 | await expect(tx).to.be.revertedWith("Pausable: paused")
110 | });
111 |
112 | it('Should revert If channel address is 0x0', async function(){
113 | const zeroAddress = "0x0000000000000000000000000000000000000000";
114 | const tx = EPNSCoreV1Proxy.connect(ALICESIGNER).updateChannelMeta(
115 | zeroAddress,
116 | channelNewIdentity,
117 | ADD_CHANNEL_MIN_FEES
118 | );
119 | await expect(tx).to.be.revertedWith("PushCoreV2::onlyChannelOwner: Invalid Channel Owner")
120 | });
121 |
122 | it("Should revert IF Caller is not the Channel Owner", async function(){
123 | const tx = EPNSCoreV1Proxy.connect(ALICESIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
124 | await expect(tx).to.be.revertedWith("PushCoreV2::onlyChannelOwner: Invalid Channel Owner")
125 | });
126 |
127 | it("Should revert IF Amount is 0 Push tokens", async function(){
128 | const LESS_AMOUNT = tokensBN(0)
129 | const tx = EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, LESS_AMOUNT);
130 | await expect(tx).to.be.revertedWith("PushCoreV2::updateChannelMeta: Insufficient Deposit Amount")
131 | });
132 |
133 | it("Should revert IF Amount is less than Required Push tokens", async function(){
134 | const LESS_AMOUNT = tokensBN(20)
135 | const tx = EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, LESS_AMOUNT);
136 |
137 | await expect(tx).to.be.revertedWith("PushCoreV2::updateChannelMeta: Insufficient Deposit Amount")
138 | });
139 |
140 | it("Updating Channel Meta should update CHANNEL_POOL_FUNDS and PROTOCOL_POOL_FEES correctly", async function(){
141 | const poolFunds_before = await EPNSCoreV1Proxy.CHANNEL_POOL_FUNDS();
142 | const poolFees_before = await EPNSCoreV1Proxy.PROTOCOL_POOL_FEES();
143 |
144 | const tx = await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
145 |
146 | const block_num = tx.blockNumber;
147 | const channel = await EPNSCoreV1Proxy.channels(BOB)
148 | const poolFunds_after = await EPNSCoreV1Proxy.CHANNEL_POOL_FUNDS();
149 | const poolFees_after = await EPNSCoreV1Proxy.PROTOCOL_POOL_FEES();
150 | const counter = await EPNSCoreV1Proxy.channelUpdateCounter(BOB);
151 |
152 | const expectedPoolFundsAfter = poolFunds_before;
153 | const expectedPoolFeesAfter = poolFees_before.add(ADD_CHANNEL_MIN_FEES);
154 |
155 | await expect(counter).to.equal(1);
156 | await expect(channel.channelUpdateBlock).to.equal(block_num);
157 | await expect(poolFunds_after).to.equal(expectedPoolFundsAfter);
158 | await expect(poolFees_after).to.equal(expectedPoolFeesAfter);
159 |
160 | });
161 |
162 | it("Contract should recieve 50 Push tokens for 1st Channel Update", async function(){
163 | const pushBalanceBefore_coreContract = await PushToken.balanceOf(EPNSCoreV1Proxy.address);
164 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
165 | const pushBalanceAfter_coreContract = await PushToken.balanceOf(EPNSCoreV1Proxy.address);
166 | expect(pushBalanceAfter_coreContract.sub(pushBalanceBefore_coreContract)).to.equal(ADD_CHANNEL_MIN_FEES);
167 | });
168 |
169 | it("2nd Channel Update should NOT execute if Fees deposited is NOT 50 * 2 Push Tokens", async function(){
170 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
171 | const counter_1 = await EPNSCoreV1Proxy.channelUpdateCounter(BOB);
172 | const tx_2nd = EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
173 |
174 | await expect(counter_1).to.equal(1);
175 | await expect(tx_2nd).to.be.revertedWith("PushCoreV2::updateChannelMeta: Insufficient Deposit Amount")
176 | });
177 |
178 | it("Contract should recieve 500 Push tokens for 4th Channel Update", async function(){
179 | const pushBalanceBefore_coreContract = await PushToken.balanceOf(EPNSCoreV1Proxy.address);
180 |
181 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
182 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES.mul(2));
183 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES.mul(3));
184 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES.mul(4));
185 |
186 | const pushBalanceAfter_coreContract = await PushToken.balanceOf(EPNSCoreV1Proxy.address);
187 |
188 | expect(pushBalanceAfter_coreContract.sub(pushBalanceBefore_coreContract)).to.equal(ADD_CHANNEL_MIN_FEES.mul(10));
189 |
190 | });
191 |
192 | it("Grows the update fees linearly", async function(){
193 | const numUpdates = 5;
194 |
195 | for (let i = 1; i <= numUpdates; i++) {
196 | // should revert on paying same fees on lastupdate
197 | const feePaidOnLastUpdate = ADD_CHANNEL_MIN_FEES.mul(i-1);
198 | await expect(
199 | EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, feePaidOnLastUpdate)
200 | ).to.be.revertedWith("PushCoreV2::updateChannelMeta: Insufficient Deposit Amount")
201 |
202 | // should pass on incresing fees linearly
203 | const feeToPay = ADD_CHANNEL_MIN_FEES.mul(i);
204 | await EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, feeToPay)
205 | }
206 |
207 | });
208 |
209 | it("Should Emit right args for Update Channel Meta correctly for right Amount -> 50 PUSH Tokens", async function(){
210 | const tx = EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
211 | await expect(tx)
212 | .to.emit(EPNSCoreV1Proxy, 'UpdateChannel')
213 | .withArgs(BOB, ethers.utils.hexlify(channelNewIdentity), ADD_CHANNEL_MIN_FEES);
214 | });
215 |
216 | it("Should Emit right args for Update Channel Meta correctly for right Amount -> 50 PUSH Tokens", async function(){
217 | const tx = EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES);
218 | await expect(tx)
219 | .to.emit(EPNSCoreV1Proxy, 'UpdateChannel')
220 | .withArgs(BOB, ethers.utils.hexlify(channelNewIdentity), ADD_CHANNEL_MIN_FEES);
221 | });
222 |
223 | it("Only allows activate channel to be updated", async function(){
224 | // on channel deactivation cannnot create channel
225 | await EPNSCoreV1Proxy.connect(BOBSIGNER).deactivateChannel();
226 | await expect(
227 | EPNSCoreV1Proxy.connect(BOBSIGNER).updateChannelMeta(BOB, channelNewIdentity, ADD_CHANNEL_MIN_FEES)
228 | ).to.be.revertedWith("PushCoreV2::onlyChannelOwner: Invalid Channel Owner");
229 | });
230 | });
231 |
232 | });
233 | });
--------------------------------------------------------------------------------
/wallets/!noremove:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/push-protocol/push-smart-contracts/afeb537ef62909991f527727c95ad6ee22126663/wallets/!noremove
--------------------------------------------------------------------------------