├── .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 | ![DESCRIPTION](LINK.png) 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] - <title>" 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] - <title>" 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] - <title>" 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] - <title>" 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 | <h1 align="center"> 2 | <a href="https://push.org/#gh-light-mode-only"> 3 | <img width='20%' height='10%' src="https://res.cloudinary.com/drdjegqln/image/upload/v1686227557/Push-Logo-Standard-Dark_xap7z5.png"> 4 | </a> 5 | <a href="https://push.org/#gh-dark-mode-only"> 6 | <img width='20%' height='10%' src="https://res.cloudinary.com/drdjegqln/image/upload/v1686227558/Push-Logo-Standard-White_dlvapc.png"> 7 | </a> 8 | </h1> 9 | 10 | <p align="center"> 11 | <i align="center">Push Protocol is a web3 communication network, enabling cross-chain notifications, messaging, video, and NFT chat for dapps, wallets, and services.🚀</i> 12 | </p> 13 | 14 | <h4 align="center"> 15 | 16 | <a href="https://discord.gg/pushprotocol"> 17 | <img src="https://img.shields.io/badge/discord-7289da.svg?style=flat-square" alt="discord"> 18 | </a> 19 | <a href="https://twitter.com/pushprotocol"> 20 | <img src="https://img.shields.io/badge/twitter-18a1d6.svg?style=flat-square" alt="twitter"> 21 | </a> 22 | <a href="https://www.youtube.com/@pushprotocol"> 23 | <img src="https://img.shields.io/badge/youtube-d95652.svg?style=flat-square&" alt="youtube"> 24 | </a> 25 | </h4> 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 <a href="https://docs.push.org/developers/developer-tooling/push-smart-contracts/epns-contract-addresses">Docs</a> 77 | 78 | ## 🧩 Modules 79 | 80 | <details closed><summary>Epnscomm</summary> 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 | </details> 93 | 94 | <details closed><summary>Epnscore</summary> 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 | </details> 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 <a href="https://github.com/ethereum-push-notification-service/push-smart-contracts/blob/master/contributing.md">HERE</a> 160 | 161 | <br /> 162 | Not sure where to start? Join our discord and we will help you get started! 163 | 164 | <a href="https://discord.gg/pushprotocol" title="Join Our Community"><img src="https://www.freepnglogos.com/uploads/discord-logo-png/playerunknown-battlegrounds-bgparty-15.png" width="200" alt="Discord" /></a> 165 | 166 | ## License 167 | Check out our License <a href='https://github.com/ethereum-push-notification-service/push-smart-contracts/blob/master/license-v1'>HERE </a> 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 <your-branch-name> 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 | [![Add and commit with Commitizen](https://github.com/commitizen/cz-cli/raw/master/meta/screenshots/add-commit.png)](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 | <span style="color:red">Don't run CI-prefixed targets in the NX console in local, they are only for CI.</span>. 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 --------------------------------------------------------------------------------