mirror of
https://github.com/interep-project/contracts.git
synced 2026-01-10 05:47:59 -05:00
style: update lint configuration
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
extends: ["@commitlint/config-conventional"],
|
||||
};
|
||||
3
.commitlintrc.json
Normal file
3
.commitlintrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
# EditorConfig http://EditorConfig.org
|
||||
#root = true
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# All files
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.sol]
|
||||
insert_final_newline = true
|
||||
max_line_length = 120
|
||||
indent_size = 4
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
43
.eslintrc.json
Normal file
43
.eslintrc.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"env": {
|
||||
"es6": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "tsconfig.json"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"comma-dangle": "warn",
|
||||
"comma-spacing": "warn",
|
||||
"comma-style": "warn",
|
||||
"func-call-spacing": "warn",
|
||||
"no-whitespace-before-property": "warn",
|
||||
"no-multi-spaces": "warn",
|
||||
"space-in-parens": "warn",
|
||||
"spaced-comment": "warn",
|
||||
"arrow-parens": "warn",
|
||||
"no-var": "error",
|
||||
"prefer-const": "warn",
|
||||
"prefer-destructuring": "warn",
|
||||
"prefer-template": "warn",
|
||||
"prefer-rest-params": "warn",
|
||||
"rest-spread-spacing": "warn",
|
||||
"template-curly-spacing": "warn",
|
||||
"prefer-arrow-callback": "warn",
|
||||
"object-shorthand": "warn",
|
||||
"no-useless-rename": "warn",
|
||||
"no-useless-computed-key": "warn",
|
||||
"no-duplicate-imports": "warn",
|
||||
"no-duplicate-case": "warn",
|
||||
"block-spacing": "warn",
|
||||
"brace-style": "warn",
|
||||
"camelcase": "warn",
|
||||
"computed-property-spacing": "warn",
|
||||
"eol-last": "warn",
|
||||
"function-call-argument-newline": ["warn", "consistent"]
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
extends:
|
||||
- "eslint:recommended"
|
||||
- "plugin:@typescript-eslint/eslint-recommended"
|
||||
- "plugin:@typescript-eslint/recommended"
|
||||
- "plugin:@typescript-eslint/recommended-requiring-type-checking"
|
||||
- "prettier"
|
||||
parser: "@typescript-eslint/parser"
|
||||
parserOptions:
|
||||
project: "tsconfig.json"
|
||||
plugins:
|
||||
- "@typescript-eslint"
|
||||
root: true
|
||||
rules:
|
||||
"@typescript-eslint/no-inferrable-types": "off"
|
||||
"@typescript-eslint/no-unused-vars":
|
||||
- error
|
||||
- argsIgnorePattern: _
|
||||
varsIgnorePattern: _
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"./**/*.{js,json,md,sol,ts}": [
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
]
|
||||
}
|
||||
6
.lintstagedrc.json
Normal file
6
.lintstagedrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"**/*.{js,json,md,sol,ts}": [
|
||||
"prettier --config ./.prettierrc.json --write",
|
||||
"eslint --config ./.eslintrc.json --fix"
|
||||
]
|
||||
}
|
||||
17
.prettierrc
17
.prettierrc
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine":"auto",
|
||||
"printWidth": 120,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.sol",
|
||||
"options": {
|
||||
"tabWidth": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
5
.prettierrc.json
Normal file
5
.prettierrc.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"semi": false,
|
||||
"arrowParens": "always",
|
||||
"trailingComma": "none"
|
||||
}
|
||||
33
.solcover.js
33
.solcover.js
@@ -1,23 +1,16 @@
|
||||
const shell = require("shelljs");
|
||||
const shell = require("shelljs")
|
||||
|
||||
// // The environment variables are loaded in hardhat.config.ts
|
||||
// const mnemonic = process.env.MNEMONIC;
|
||||
// if (!mnemonic) {
|
||||
// throw new Error("Please set your MNEMONIC in a .env file");
|
||||
// }
|
||||
// The environment variables are loaded in hardhat.config.ts.
|
||||
|
||||
module.exports = {
|
||||
istanbulReporter: ["html", "lcov"],
|
||||
onCompileComplete: async function (_config) {
|
||||
await run("typechain");
|
||||
},
|
||||
onIstanbulComplete: async function (_config) {
|
||||
// We need to do this because solcover generates bespoke artifacts.
|
||||
shell.rm("-rf", "./artifacts");
|
||||
shell.rm("-rf", "./typechain");
|
||||
},
|
||||
// providerOptions: {
|
||||
// mnemonic,
|
||||
// },
|
||||
skipFiles: ["mocks", "test"],
|
||||
};
|
||||
istanbulReporter: ["html", "lcov"],
|
||||
onCompileComplete: async function (_config) {
|
||||
run("typechain")
|
||||
},
|
||||
onIstanbulComplete: async function (_config) {
|
||||
// We need to do this because solcover generates bespoke artifacts.
|
||||
shell.rm("-rf", "./artifacts")
|
||||
shell.rm("-rf", "./typechain")
|
||||
},
|
||||
skipFiles: ["mocks", "test"]
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"extends": "solhint:recommended",
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"code-complexity": ["error", 7],
|
||||
"compiler-version": ["error", ">=0.8.0"],
|
||||
"const-name-snakecase": "off",
|
||||
"constructor-syntax": "error",
|
||||
"func-visibility": ["error", { "ignoreConstructors": true }],
|
||||
"max-line-length": ["error", 120],
|
||||
"not-rely-on-time": "off",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
],
|
||||
"reason-string": ["warn", { "maxLength": 64 }]
|
||||
}
|
||||
"extends": "solhint:recommended",
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"code-complexity": ["error", 7],
|
||||
"compiler-version": ["error", ">=0.8.0"],
|
||||
"const-name-snakecase": "off",
|
||||
"constructor-syntax": "error",
|
||||
"func-visibility": ["error", { "ignoreConstructors": true }],
|
||||
"max-line-length": ["error", 120],
|
||||
"not-rely-on-time": "off",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
],
|
||||
"reason-string": ["warn", { "maxLength": 64 }]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ Official website: https://interrep.link/
|
||||
For more details on how to use and a technical overview, please see the [wiki](https://github.com/ra-phael/interRep-contracts/wiki).
|
||||
|
||||
Deployed contracts:
|
||||
- Arbitrum One: [0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11](https://explorer.offchainlabs.com/address/0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11)
|
||||
- Ropsten: [0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11](https://ropsten.etherscan.io/address/0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11) (Proxy)
|
||||
|
||||
- Arbitrum One: [0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11](https://explorer.offchainlabs.com/address/0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11)
|
||||
- Ropsten: [0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11](https://ropsten.etherscan.io/address/0x2F4d1333337b5C4C47Db5DB3A36eD547a549BC11) (Proxy)
|
||||
|
||||
⚠️ If you had a badge minted on Ropsten and want to unlink your account, please visit [https://ropsten.interrep.link/](https://ropsten.interrep.link/)
|
||||
|
||||
@@ -110,8 +111,8 @@ compiler version is to add the following fields to your VSCode user settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"solidity.compileUsingRemoteVersion": "v0.8.4+commit.c7e474f2",
|
||||
"solidity.defaultCompiler": "remote"
|
||||
"solidity.compileUsingRemoteVersion": "v0.8.4+commit.c7e474f2",
|
||||
"solidity.defaultCompiler": "remote"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ InterRep is made up of 2 main components: a centralized verification service (wi
|
||||
|
||||
By interacting with the front-end, users are able to:
|
||||
|
||||
- link and unlink their Ethereum account with their Twitter account
|
||||
- mint and burn an NFT or “badge” representing this association
|
||||
- link and unlink their Ethereum account with their Twitter account
|
||||
- mint and burn an NFT or “badge” representing this association
|
||||
|
||||
Applications can also use InterRep through the API, which returns a Twitter account’s reputation based on publicly available data.
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
Any of the following will result in a `NOT_SUFFICIENT` reputation:
|
||||
|
||||
- Default profile picture
|
||||
- 0 tweets
|
||||
- 2 followers or less
|
||||
- Default profile picture
|
||||
- 0 tweets
|
||||
- 2 followers or less
|
||||
|
||||
Any of the following will result in a `CONFIRMED` reputation:
|
||||
|
||||
- Verified by Twitter
|
||||
- More than 7000 followers
|
||||
- Is among our list of 18,000+ seed accounts
|
||||
- Verified by Twitter
|
||||
- More than 7000 followers
|
||||
- Is among our list of 18,000+ seed accounts
|
||||
|
||||
Otherwise, the reputation is `UNCLEAR` and data from [botometer](https://botometer.osome.iu.edu/) is fetched
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
import "@nomiclabs/hardhat-etherscan";
|
||||
import "@nomiclabs/hardhat-waffle";
|
||||
import "@openzeppelin/hardhat-upgrades";
|
||||
import "@typechain/hardhat";
|
||||
import { config as dotenvConfig } from "dotenv";
|
||||
import "hardhat-gas-reporter";
|
||||
import { HardhatUserConfig } from "hardhat/config";
|
||||
import { NetworksUserConfig } from "hardhat/types";
|
||||
import { resolve } from "path";
|
||||
import "solidity-coverage";
|
||||
import "./tasks/accounts";
|
||||
import "./tasks/clean";
|
||||
import "@nomiclabs/hardhat-etherscan"
|
||||
import "@nomiclabs/hardhat-waffle"
|
||||
import "@openzeppelin/hardhat-upgrades"
|
||||
import "@typechain/hardhat"
|
||||
import { config as dotenvConfig } from "dotenv"
|
||||
import "hardhat-gas-reporter"
|
||||
import { HardhatUserConfig } from "hardhat/config"
|
||||
import { NetworksUserConfig } from "hardhat/types"
|
||||
import { resolve } from "path"
|
||||
import "solidity-coverage"
|
||||
import "./tasks/accounts"
|
||||
import "./tasks/clean"
|
||||
|
||||
dotenvConfig({ path: resolve(__dirname, "./.env") });
|
||||
dotenvConfig({ path: resolve(__dirname, "./.env") })
|
||||
|
||||
function getNetworks(): NetworksUserConfig | undefined {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
const infuraApiKey = process.env.INFURA_API_KEY;
|
||||
const mnemonic = process.env.MNEMONIC;
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
const infuraApiKey = process.env.INFURA_API_KEY
|
||||
const mnemonic = process.env.MNEMONIC
|
||||
|
||||
if (!infuraApiKey) {
|
||||
throw new Error("Please set your INFURA_API_KEY in a .env file");
|
||||
if (!infuraApiKey) {
|
||||
throw new Error("Please set your INFURA_API_KEY in a .env file")
|
||||
}
|
||||
|
||||
if (!mnemonic) {
|
||||
throw new Error("Please set MNEMONIC in a .env file")
|
||||
}
|
||||
|
||||
return {
|
||||
ropsten: {
|
||||
url: `https://ropsten.infura.io/v3/${infuraApiKey}`,
|
||||
chainId: 3,
|
||||
accounts: {
|
||||
count: 10,
|
||||
mnemonic
|
||||
}
|
||||
},
|
||||
kovan: {
|
||||
url: `https://kovan.infura.io/v3/${infuraApiKey}`,
|
||||
chainId: 42,
|
||||
accounts: {
|
||||
count: 10,
|
||||
mnemonic
|
||||
}
|
||||
},
|
||||
arbitrum: {
|
||||
url: "https://arb1.arbitrum.io/rpc",
|
||||
chainId: 42161,
|
||||
accounts: {
|
||||
count: 10,
|
||||
mnemonic
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mnemonic) {
|
||||
throw new Error("Please set MNEMONIC in a .env file");
|
||||
}
|
||||
|
||||
return {
|
||||
ropsten: {
|
||||
url: "https://ropsten.infura.io/v3/" + infuraApiKey,
|
||||
chainId: 3,
|
||||
accounts: {
|
||||
count: 10,
|
||||
mnemonic,
|
||||
},
|
||||
},
|
||||
kovan: {
|
||||
url: "https://kovan.infura.io/v3/" + infuraApiKey,
|
||||
chainId: 42,
|
||||
accounts: {
|
||||
count: 10,
|
||||
mnemonic,
|
||||
},
|
||||
},
|
||||
arbitrum: {
|
||||
url: "https://arb1.arbitrum.io/rpc",
|
||||
chainId: 42161,
|
||||
accounts: {
|
||||
count: 10,
|
||||
mnemonic,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
defaultNetwork: process.env.DEFAULT_NETWORK || "hardhat",
|
||||
networks: getNetworks(),
|
||||
solidity: {
|
||||
version: "0.8.0",
|
||||
},
|
||||
gasReporter: {
|
||||
currency: "USD",
|
||||
enabled: process.env.REPORT_GAS ? true : false,
|
||||
},
|
||||
typechain: {
|
||||
outDir: "typechain",
|
||||
target: "ethers-v5",
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: process.env.ETHERSCAN_API_KEY,
|
||||
},
|
||||
};
|
||||
defaultNetwork: process.env.DEFAULT_NETWORK || "hardhat",
|
||||
networks: getNetworks(),
|
||||
solidity: {
|
||||
version: "0.8.0"
|
||||
},
|
||||
gasReporter: {
|
||||
currency: "USD",
|
||||
enabled: process.env.REPORT_GAS ? true : false
|
||||
},
|
||||
typechain: {
|
||||
outDir: "typechain",
|
||||
target: "ethers-v5"
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: process.env.ETHERSCAN_API_KEY
|
||||
}
|
||||
}
|
||||
|
||||
export default config;
|
||||
export default config
|
||||
|
||||
174
package.json
174
package.json
@@ -1,89 +1,89 @@
|
||||
{
|
||||
"name": "interrep-contracts",
|
||||
"description": "InterRep smart contracts.",
|
||||
"version": "0.1.0",
|
||||
"author": {
|
||||
"name": "Raphael Roullet"
|
||||
},
|
||||
"files": [
|
||||
"/contracts"
|
||||
],
|
||||
"keywords": [
|
||||
"blockchain",
|
||||
"ethereum",
|
||||
"hardhat",
|
||||
"smart-contracts",
|
||||
"solidity"
|
||||
],
|
||||
"license": "WTFPL",
|
||||
"resolutions": {
|
||||
"@ethersproject/wallet": "^5.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "hardhat node",
|
||||
"clean": "hardhat clean",
|
||||
"compile": "hardhat compile",
|
||||
"deploy:reputation-badge": "hardhat deploy:reputation-badge",
|
||||
"mint": "hardhat mint",
|
||||
"test": "hardhat test",
|
||||
"coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"./test/**/*.ts\"",
|
||||
"lint": "yarn run lint:sol && yarn run lint:ts && yarn run prettier:check",
|
||||
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
|
||||
"lint:ts": "eslint --config ./.eslintrc.yaml --ignore-path ./.eslintignore --ext .js,.ts .",
|
||||
"prettier": "prettier --config ./.prettierrc --write \"**/*.{js,json,md,sol,ts}\"",
|
||||
"prettier:check": "prettier --check --config ./.prettierrc \"**/*.{js,json,md,sol,ts}\"",
|
||||
"postinstall": "husky install",
|
||||
"typechain": "hardhat typechain",
|
||||
"commit": "git-cz",
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codechecks/client": "^0.1.10",
|
||||
"@commitlint/cli": "^12.1.4",
|
||||
"@commitlint/config-conventional": "^12.1.4",
|
||||
"@ethersproject/abi": "^5.2.0",
|
||||
"@ethersproject/abstract-signer": "^5.2.0",
|
||||
"@ethersproject/bignumber": "^5.2.0",
|
||||
"@ethersproject/bytes": "^5.2.0",
|
||||
"@ethersproject/contracts": "^5.2.0",
|
||||
"@ethersproject/providers": "^5.2.0",
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||
"@nomiclabs/hardhat-etherscan": "^2.1.5",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||
"@openzeppelin/contracts": "^4.1.0",
|
||||
"@openzeppelin/contracts-upgradeable": "^4.1.0",
|
||||
"@openzeppelin/hardhat-upgrades": "^1.8.2",
|
||||
"@typechain/ethers-v5": "^7.0.0",
|
||||
"@typechain/hardhat": "^2.0.1",
|
||||
"@types/chai": "^4.2.18",
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/node": "^15.6.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
||||
"@typescript-eslint/parser": "^4.25.0",
|
||||
"chai": "^4.3.4",
|
||||
"commitizen": "^4.2.4",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"ethereum-waffle": "^3.3.0",
|
||||
"ethers": "^5.2.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"hardhat": "^2.3.0",
|
||||
"hardhat-gas-reporter": "^1.0.4",
|
||||
"husky": "^6.0.0",
|
||||
"lint-staged": "^11.0.0",
|
||||
"mocha": "^8.4.0",
|
||||
"prettier": "^2.3.0",
|
||||
"prettier-plugin-solidity": "^1.0.0-beta.11",
|
||||
"shelljs": "^0.8.4",
|
||||
"solhint": "^3.3.6",
|
||||
"solhint-plugin-prettier": "^0.0.5",
|
||||
"solidity-coverage": "^0.7.16",
|
||||
"ts-generator": "^0.1.1",
|
||||
"ts-node": "^10.0.0",
|
||||
"typechain": "^5.0.0",
|
||||
"typescript": "~4.2.4"
|
||||
}
|
||||
"name": "interrep-contracts",
|
||||
"description": "InterRep smart contracts.",
|
||||
"version": "0.1.0",
|
||||
"author": {
|
||||
"name": "Raphael Roullet"
|
||||
},
|
||||
"files": [
|
||||
"/contracts"
|
||||
],
|
||||
"keywords": [
|
||||
"blockchain",
|
||||
"ethereum",
|
||||
"hardhat",
|
||||
"smart-contracts",
|
||||
"solidity"
|
||||
],
|
||||
"license": "WTFPL",
|
||||
"resolutions": {
|
||||
"@ethersproject/wallet": "^5.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "hardhat node",
|
||||
"clean": "hardhat clean",
|
||||
"compile": "hardhat compile",
|
||||
"deploy:reputation-badge": "hardhat deploy:reputation-badge",
|
||||
"mint": "hardhat mint",
|
||||
"test": "hardhat test",
|
||||
"coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"./test/**/*.ts\"",
|
||||
"lint": "yarn run lint:sol && yarn run lint:ts",
|
||||
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
|
||||
"lint:ts": "eslint --config ./.eslintrc.json --ignore-path ./.eslintignore --ext .js,.ts .",
|
||||
"lint:fix": "yarn run lint:sol --fix && yarn run lint:ts --fix",
|
||||
"prettier": "prettier --check --config ./.prettierrc.json \"**/*.{js,json,md,sol,ts}\"",
|
||||
"prettier:write": "prettier --config ./.prettierrc.json --write \"**/*.{js,json,md,sol,ts}\"",
|
||||
"typechain": "hardhat typechain",
|
||||
"commit": "git-cz",
|
||||
"precommit": "lint-staged"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codechecks/client": "^0.1.10",
|
||||
"@commitlint/cli": "^12.1.4",
|
||||
"@commitlint/config-conventional": "^12.1.4",
|
||||
"@ethersproject/abi": "^5.2.0",
|
||||
"@ethersproject/abstract-signer": "^5.2.0",
|
||||
"@ethersproject/bignumber": "^5.2.0",
|
||||
"@ethersproject/bytes": "^5.2.0",
|
||||
"@ethersproject/contracts": "^5.2.0",
|
||||
"@ethersproject/providers": "^5.2.0",
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.2",
|
||||
"@nomiclabs/hardhat-etherscan": "^2.1.5",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||
"@openzeppelin/contracts": "^4.1.0",
|
||||
"@openzeppelin/contracts-upgradeable": "^4.1.0",
|
||||
"@openzeppelin/hardhat-upgrades": "^1.8.2",
|
||||
"@typechain/ethers-v5": "^7.0.0",
|
||||
"@typechain/hardhat": "^2.0.1",
|
||||
"@types/chai": "^4.2.18",
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/node": "^15.6.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
||||
"@typescript-eslint/parser": "^4.25.0",
|
||||
"chai": "^4.3.4",
|
||||
"commitizen": "^4.2.4",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"ethereum-waffle": "^3.3.0",
|
||||
"ethers": "^5.2.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"hardhat": "^2.3.0",
|
||||
"hardhat-gas-reporter": "^1.0.4",
|
||||
"husky": "^6.0.0",
|
||||
"lint-staged": "^11.0.0",
|
||||
"mocha": "^8.4.0",
|
||||
"prettier": "^2.3.0",
|
||||
"prettier-plugin-solidity": "^1.0.0-beta.11",
|
||||
"shelljs": "^0.8.4",
|
||||
"solhint": "^3.3.6",
|
||||
"solhint-plugin-prettier": "^0.0.5",
|
||||
"solidity-coverage": "^0.7.16",
|
||||
"ts-generator": "^0.1.1",
|
||||
"ts-node": "^10.0.0",
|
||||
"typechain": "^5.0.0",
|
||||
"typescript": "~4.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Signer } from "@ethersproject/abstract-signer";
|
||||
import { task } from "hardhat/config";
|
||||
import { Signer } from "@ethersproject/abstract-signer"
|
||||
import { task } from "hardhat/config"
|
||||
|
||||
task("accounts", "Prints the list of accounts", async (args, hre) => {
|
||||
const accounts: Signer[] = await hre.ethers.getSigners();
|
||||
const accounts: Signer[] = await hre.ethers.getSigners()
|
||||
|
||||
for (const account of accounts) {
|
||||
console.log(await account.getAddress());
|
||||
}
|
||||
});
|
||||
for (const account of accounts) {
|
||||
console.log(await account.getAddress())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import fsExtra from "fs-extra";
|
||||
import { TASK_CLEAN } from "hardhat/builtin-tasks/task-names";
|
||||
import { task } from "hardhat/config";
|
||||
import fsExtra from "fs-extra"
|
||||
import { TASK_CLEAN } from "hardhat/builtin-tasks/task-names"
|
||||
import { task } from "hardhat/config"
|
||||
|
||||
task(TASK_CLEAN, "Overrides the standard clean task", async (args, { config }, runSuper) => {
|
||||
await fsExtra.remove("./coverage");
|
||||
await fsExtra.remove("./coverage.json");
|
||||
await fsExtra.remove("./coverage")
|
||||
await fsExtra.remove("./coverage.json")
|
||||
|
||||
if (config.typechain?.outDir) {
|
||||
await fsExtra.remove(config.typechain.outDir);
|
||||
}
|
||||
if (config.typechain?.outDir) {
|
||||
await fsExtra.remove(config.typechain.outDir)
|
||||
}
|
||||
|
||||
await runSuper();
|
||||
});
|
||||
await runSuper()
|
||||
})
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { task } from "hardhat/config";
|
||||
import { ReputationBadge } from "../typechain";
|
||||
import { task } from "hardhat/config"
|
||||
import { ReputationBadge } from "../typechain"
|
||||
|
||||
task("deploy:reputation-badge", "Deploy a ReputationBadge contract")
|
||||
.addParam("name", "The name of the token")
|
||||
.addParam("symbol", "The symbol of the token")
|
||||
.setAction(async ({ name, symbol }, { ethers, upgrades }) => {
|
||||
const [signer] = await ethers.getSigners();
|
||||
const ReputationBadgeFactory = await ethers.getContractFactory("ReputationBadge");
|
||||
.addParam("name", "The name of the token")
|
||||
.addParam("symbol", "The symbol of the token")
|
||||
.setAction(async ({ name, symbol }, { ethers, upgrades }) => {
|
||||
const [signer] = await ethers.getSigners()
|
||||
const ReputationBadgeFactory = await ethers.getContractFactory("ReputationBadge")
|
||||
|
||||
// Unfortunately the first signer is used to deploy and there is no option to change that
|
||||
// See https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/271
|
||||
const reputationBadge: ReputationBadge = (await upgrades.deployProxy(ReputationBadgeFactory, [
|
||||
name,
|
||||
symbol,
|
||||
signer.address,
|
||||
])) as ReputationBadge;
|
||||
// Unfortunately the first signer is used to deploy and there is no option to change that
|
||||
// See https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/271
|
||||
const reputationBadge: ReputationBadge = (await upgrades.deployProxy(ReputationBadgeFactory, [
|
||||
name,
|
||||
symbol,
|
||||
signer.address
|
||||
])) as ReputationBadge
|
||||
|
||||
await reputationBadge.deployed();
|
||||
await reputationBadge.deployed()
|
||||
|
||||
console.log(`The ReputationBadge contract has been deployed to the address: ${reputationBadge.address}`);
|
||||
});
|
||||
console.log(`The ReputationBadge contract has been deployed to the address: ${reputationBadge.address}`)
|
||||
})
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { task } from "hardhat/config";
|
||||
import { ReputationBadge } from "../typechain";
|
||||
import { task } from "hardhat/config"
|
||||
import { ReputationBadge } from "../typechain"
|
||||
|
||||
task("mint", "Mint a token in the ReputationBadge contract")
|
||||
.addParam("contractAddress", "The address of the ReputationBadge contract")
|
||||
.addParam("to", "The address of the token owner")
|
||||
.addParam("tokenId", "The id of the token")
|
||||
.setAction(async ({ contractAddress, to, tokenId }, { ethers }) => {
|
||||
const [signer] = await ethers.getSigners();
|
||||
const reputationBadge: ReputationBadge = (await ethers.getContractAt(
|
||||
"ReputationBadge",
|
||||
contractAddress,
|
||||
)) as ReputationBadge;
|
||||
.addParam("contractAddress", "The address of the ReputationBadge contract")
|
||||
.addParam("to", "The address of the token owner")
|
||||
.addParam("tokenId", "The id of the token")
|
||||
.setAction(async ({ contractAddress, to, tokenId }, { ethers }) => {
|
||||
const [signer] = await ethers.getSigners()
|
||||
const reputationBadge: ReputationBadge = (await ethers.getContractAt(
|
||||
"ReputationBadge",
|
||||
contractAddress
|
||||
)) as ReputationBadge
|
||||
|
||||
await reputationBadge.connect(signer).safeMint(to, tokenId);
|
||||
await reputationBadge.connect(signer).safeMint(to, tokenId)
|
||||
|
||||
console.log(`The token has been minted correctly`);
|
||||
});
|
||||
console.log(`The token has been minted correctly`)
|
||||
})
|
||||
|
||||
@@ -1,264 +1,270 @@
|
||||
import hre from "hardhat";
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address";
|
||||
import { expect } from "chai";
|
||||
import { Contract, ContractFactory } from "@ethersproject/contracts";
|
||||
import hre from "hardhat"
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"
|
||||
import { expect } from "chai"
|
||||
import { Contract, ContractFactory } from "@ethersproject/contracts"
|
||||
|
||||
const { ethers, upgrades } = hre;
|
||||
const { ethers, upgrades } = hre
|
||||
|
||||
describe("ReputationBadge", function () {
|
||||
let badge: Contract;
|
||||
let deployer: SignerWithAddress;
|
||||
let backend: SignerWithAddress;
|
||||
let signer1: SignerWithAddress;
|
||||
let signer2: SignerWithAddress;
|
||||
describe("ReputationBadge", () => {
|
||||
let badge: Contract
|
||||
let deployer: SignerWithAddress
|
||||
let backend: SignerWithAddress
|
||||
let signer1: SignerWithAddress
|
||||
let signer2: SignerWithAddress
|
||||
|
||||
const badgeName = "TwitterBadge";
|
||||
const badgeSymbol = "iTWITT";
|
||||
const badgeName = "TwitterBadge"
|
||||
const badgeSymbol = "iTWITT"
|
||||
|
||||
before(async function () {
|
||||
[deployer, backend, signer1, signer2] = await hre.ethers.getSigners();
|
||||
});
|
||||
before(async () => {
|
||||
;[deployer, backend, signer1, signer2] = await hre.ethers.getSigners()
|
||||
})
|
||||
|
||||
beforeEach(async function () {
|
||||
const BadgeFactory: ContractFactory = await ethers.getContractFactory("ReputationBadge");
|
||||
beforeEach(async () => {
|
||||
const BadgeFactory: ContractFactory = await ethers.getContractFactory("ReputationBadge")
|
||||
|
||||
badge = await upgrades.deployProxy(BadgeFactory, [badgeName, badgeSymbol, backend.address]);
|
||||
badge = await upgrades.deployProxy(BadgeFactory, [badgeName, badgeSymbol, backend.address])
|
||||
|
||||
await badge.deployed();
|
||||
});
|
||||
await badge.deployed()
|
||||
})
|
||||
|
||||
it("should return the badge name", async () => {
|
||||
expect(await badge.name()).to.eq(badgeName);
|
||||
});
|
||||
it("should return the badge name", async () => {
|
||||
expect(await badge.name()).to.eq(badgeName)
|
||||
})
|
||||
|
||||
it("should return the badge symbol", async () => {
|
||||
expect(await badge.symbol()).to.eq(badgeSymbol);
|
||||
});
|
||||
it("should return the badge symbol", async () => {
|
||||
expect(await badge.symbol()).to.eq(badgeSymbol)
|
||||
})
|
||||
|
||||
/*
|
||||
**** PAUSING ****
|
||||
*/
|
||||
it("should let the deployer pause", async () => {
|
||||
await badge.connect(deployer).pause();
|
||||
/*
|
||||
**** PAUSING ****
|
||||
*/
|
||||
it("should let the deployer pause", async () => {
|
||||
await badge.connect(deployer).pause()
|
||||
|
||||
expect(await badge.paused()).to.be.true;
|
||||
});
|
||||
expect(await badge.paused()).to.be.true
|
||||
})
|
||||
|
||||
it("should let the deployer unpause", async () => {
|
||||
await badge.connect(deployer).pause();
|
||||
it("should let the deployer unpause", async () => {
|
||||
await badge.connect(deployer).pause()
|
||||
|
||||
await badge.connect(deployer).unpause();
|
||||
await badge.connect(deployer).unpause()
|
||||
|
||||
expect(await badge.paused()).to.be.false;
|
||||
});
|
||||
expect(await badge.paused()).to.be.false
|
||||
})
|
||||
|
||||
it("should not let another signer pause", async () => {
|
||||
await expect(badge.connect(signer1).pause()).to.be.revertedWith("Ownable: caller is not the owner");
|
||||
});
|
||||
it("should not let another signer pause", async () => {
|
||||
await expect(badge.connect(signer1).pause()).to.be.revertedWith("Ownable: caller is not the owner")
|
||||
})
|
||||
|
||||
it("should not let another signer unpause", async () => {
|
||||
await expect(badge.connect(signer1).unpause()).to.be.revertedWith("Ownable: caller is not the owner");
|
||||
});
|
||||
it("should not let another signer unpause", async () => {
|
||||
await expect(badge.connect(signer1).unpause()).to.be.revertedWith("Ownable: caller is not the owner")
|
||||
})
|
||||
|
||||
/*
|
||||
**** MINTING ****
|
||||
*/
|
||||
it("should let the backend mint a token", async () => {
|
||||
await badge.connect(backend).safeMint(signer1.address, 1);
|
||||
/*
|
||||
**** MINTING ****
|
||||
*/
|
||||
it("should let the backend mint a token", async () => {
|
||||
await badge.connect(backend).safeMint(signer1.address, 1)
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
expect(await badge.ownerOf(1)).to.eq(signer1.address);
|
||||
});
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
expect(await badge.ownerOf(1)).to.eq(signer1.address)
|
||||
})
|
||||
|
||||
it("should only let the backend mint a token", async () => {
|
||||
await expect(badge.connect(signer1).safeMint(signer1.address, 234)).to.be.revertedWith("Unauthorized");
|
||||
});
|
||||
it("should only let the backend mint a token", async () => {
|
||||
await expect(badge.connect(signer1).safeMint(signer1.address, 234)).to.be.revertedWith("Unauthorized")
|
||||
})
|
||||
|
||||
it("should not let minting happen when paused", async () => {
|
||||
await badge.connect(deployer).pause();
|
||||
it("should not let minting happen when paused", async () => {
|
||||
await badge.connect(deployer).pause()
|
||||
|
||||
await expect(badge.connect(backend).safeMint(signer1.address, 1)).to.be.revertedWith("Pausable: paused");
|
||||
});
|
||||
await expect(badge.connect(backend).safeMint(signer1.address, 1)).to.be.revertedWith("Pausable: paused")
|
||||
})
|
||||
|
||||
it("should not let mint twice with the same id", async () => {
|
||||
const tokenId = 5555;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
it("should not let mint twice with the same id", async () => {
|
||||
const tokenId = 5555
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
|
||||
await expect(badge.connect(backend).safeMint(signer2.address, tokenId)).to.be.revertedWith(
|
||||
"ERC721: token already minted",
|
||||
);
|
||||
});
|
||||
await expect(badge.connect(backend).safeMint(signer2.address, tokenId)).to.be.revertedWith(
|
||||
"ERC721: token already minted"
|
||||
)
|
||||
})
|
||||
|
||||
it("should batch mint several tokens", async () => {
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0);
|
||||
expect(await badge.balanceOf(signer2.address)).to.eq(0);
|
||||
it("should batch mint several tokens", async () => {
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0)
|
||||
expect(await badge.balanceOf(signer2.address)).to.eq(0)
|
||||
|
||||
const batchMintTx = await badge.connect(backend).batchMint([
|
||||
{ to: signer1.address, tokenId: 34 },
|
||||
{ to: signer2.address, tokenId: 45 },
|
||||
]);
|
||||
await batchMintTx.wait();
|
||||
const batchMintTx = await badge.connect(backend).batchMint([
|
||||
{ to: signer1.address, tokenId: 34 },
|
||||
{ to: signer2.address, tokenId: 45 }
|
||||
])
|
||||
await batchMintTx.wait()
|
||||
|
||||
expect(await badge.ownerOf(34)).to.eq(signer1.address);
|
||||
expect(await badge.ownerOf(45)).to.eq(signer2.address);
|
||||
});
|
||||
expect(await badge.ownerOf(34)).to.eq(signer1.address)
|
||||
expect(await badge.ownerOf(45)).to.eq(signer2.address)
|
||||
})
|
||||
|
||||
it("should restrict batch minting to the backend", async () => {
|
||||
await expect(
|
||||
badge.connect(signer2).batchMint([
|
||||
{ to: signer1.address, tokenId: 10 },
|
||||
{ to: signer2.address, tokenId: 11 },
|
||||
]),
|
||||
).to.be.revertedWith("Unauthorized");
|
||||
});
|
||||
it("should restrict batch minting to the backend", async () => {
|
||||
await expect(
|
||||
badge.connect(signer2).batchMint([
|
||||
{ to: signer1.address, tokenId: 10 },
|
||||
{ to: signer2.address, tokenId: 11 }
|
||||
])
|
||||
).to.be.revertedWith("Unauthorized")
|
||||
})
|
||||
|
||||
it("should return true if a token exists", async () => {
|
||||
await badge.connect(backend).safeMint(signer1.address, 1);
|
||||
it("should return true if a token exists", async () => {
|
||||
await badge.connect(backend).safeMint(signer1.address, 1)
|
||||
|
||||
expect(await badge.exists(1)).to.be.true;
|
||||
});
|
||||
expect(await badge.exists(1)).to.be.true
|
||||
})
|
||||
|
||||
it("should return false if a token does not exist", async () => {
|
||||
expect(await badge.exists(268080990909099)).to.be.false;
|
||||
});
|
||||
it("should return false if a token does not exist", async () => {
|
||||
expect(await badge.exists(268080990909099)).to.be.false
|
||||
})
|
||||
|
||||
/*
|
||||
**** BACKEND ADDRESS ****
|
||||
*/
|
||||
it("should return the backend address", async () => {
|
||||
expect(await badge.backendAddress()).to.eq(backend.address);
|
||||
});
|
||||
/*
|
||||
**** BACKEND ADDRESS ****
|
||||
*/
|
||||
it("should return the backend address", async () => {
|
||||
expect(await badge.backendAddress()).to.eq(backend.address)
|
||||
})
|
||||
|
||||
it("should let the deployer change the backend address", async () => {
|
||||
const newBackend = signer1;
|
||||
it("should let the deployer change the backend address", async () => {
|
||||
const newBackend = signer1
|
||||
|
||||
await expect(badge.connect(newBackend).safeMint(signer1.address, 234)).to.be.revertedWith("Unauthorized");
|
||||
await expect(badge.connect(newBackend).safeMint(signer1.address, 234)).to.be.revertedWith("Unauthorized")
|
||||
|
||||
// check balance is 0
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0);
|
||||
// check balance is 0
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0)
|
||||
|
||||
// change backend address
|
||||
const tx = await badge.connect(deployer).changeBackendAddress(signer1.address);
|
||||
await tx.wait();
|
||||
// change backend address
|
||||
const tx = await badge.connect(deployer).changeBackendAddress(signer1.address)
|
||||
await tx.wait()
|
||||
|
||||
// check backendAddress was changed
|
||||
expect(await badge.backendAddress()).to.eq(signer1.address);
|
||||
// check backendAddress was changed
|
||||
expect(await badge.backendAddress()).to.eq(signer1.address)
|
||||
|
||||
// try minting again
|
||||
await badge.connect(signer1).safeMint(signer1.address, 234);
|
||||
// try minting again
|
||||
await badge.connect(signer1).safeMint(signer1.address, 234)
|
||||
|
||||
// check balance is 1
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
});
|
||||
// check balance is 1
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
})
|
||||
|
||||
it("should only let the deployer change the backend address", async () => {
|
||||
await expect(badge.connect(signer1).changeBackendAddress(signer1.address)).to.be.revertedWith(
|
||||
"Ownable: caller is not the owner"
|
||||
)
|
||||
})
|
||||
|
||||
it("should only let the deployer change the backend address", async () => {
|
||||
await expect(badge.connect(signer1).changeBackendAddress(signer1.address)).to.be.revertedWith(
|
||||
"Ownable: caller is not the owner",
|
||||
);
|
||||
});
|
||||
/*
|
||||
**** BURNING ****
|
||||
*/
|
||||
it("should let tokens be burned by their owner", async () => {
|
||||
const tokenId = 5645324387978
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
/*
|
||||
**** BURNING ****
|
||||
*/
|
||||
it("should let tokens be burned by their owner", async () => {
|
||||
const tokenId = 5645324387978;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
|
||||
await badge.connect(signer1).burn(tokenId)
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0)
|
||||
})
|
||||
|
||||
it("should let approved accounts burn tokens on behalf", async () => {
|
||||
const tokenId = 44
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
|
||||
await badge.connect(signer1).approve(signer2.address, tokenId)
|
||||
|
||||
await expect(badge.connect(signer2).burn(tokenId)).to.not.be.reverted
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0)
|
||||
})
|
||||
|
||||
it("should not let tokens be burned if not approved or owner", async () => {
|
||||
const tokenId = 3333
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
|
||||
await expect(badge.connect(signer2).burn(tokenId)).to.be.revertedWith(
|
||||
"ERC721Burnable: caller is not owner nor approved"
|
||||
)
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
})
|
||||
|
||||
/*
|
||||
**** URI ****
|
||||
*/
|
||||
it("should set the base URI and return the proper tokenURI", async () => {
|
||||
const baseURI = "https://interrep.link/tokens/"
|
||||
const tokenId = 1
|
||||
|
||||
await badge.connect(deployer).changeBaseURI(baseURI)
|
||||
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
expect(await badge.tokenURI(1)).to.eq(baseURI + tokenId.toString())
|
||||
})
|
||||
|
||||
await badge.connect(signer1).burn(tokenId);
|
||||
it("should only let the deployer change the base URI", async () => {
|
||||
await expect(badge.connect(signer1).changeBaseURI("https://opensea.io/")).to.be.revertedWith(
|
||||
"Ownable: caller is not the owner"
|
||||
)
|
||||
})
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0);
|
||||
});
|
||||
/*
|
||||
**** TRANSFER ****
|
||||
*/
|
||||
it("should let token holders transfer their token", async () => {
|
||||
const tokenId = 6
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
it("should let approved accounts burn tokens on behalf", async () => {
|
||||
const tokenId = 44;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
await expect(() =>
|
||||
badge
|
||||
.connect(signer1)
|
||||
["safeTransferFrom(address,address,uint256)"](signer1.address, signer2.address, tokenId)
|
||||
).to.changeTokenBalances(badge, [signer1, signer2], [-1, 1])
|
||||
})
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
it("should let approved accounts transfer a token", async () => {
|
||||
const tokenId = 77
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
await badge.connect(signer1).approve(signer2.address, tokenId);
|
||||
await badge.connect(signer1).approve(signer2.address, tokenId)
|
||||
|
||||
await badge
|
||||
.connect(signer2)
|
||||
["safeTransferFrom(address,address,uint256)"](signer1.address, deployer.address, tokenId)
|
||||
|
||||
expect(await badge.ownerOf(tokenId)).to.eq(deployer.address)
|
||||
})
|
||||
|
||||
it("should not let unapproved transfers happen", async () => {
|
||||
const tokenId = 8
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
await expect(
|
||||
badge
|
||||
.connect(signer2)
|
||||
["safeTransferFrom(address,address,uint256)"](signer1.address, signer2.address, tokenId)
|
||||
).to.be.revertedWith("ERC721: transfer caller is not owner nor approved")
|
||||
})
|
||||
|
||||
it("should not let transfer happen when paused", async () => {
|
||||
const tokenId = 991
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId)
|
||||
|
||||
await expect(badge.connect(signer2).burn(tokenId)).to.not.be.reverted;
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(0);
|
||||
});
|
||||
|
||||
it("should not let tokens be burned if not approved or owner", async () => {
|
||||
const tokenId = 3333;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
|
||||
await expect(badge.connect(signer2).burn(tokenId)).to.be.revertedWith(
|
||||
"ERC721Burnable: caller is not owner nor approved",
|
||||
);
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
});
|
||||
|
||||
/*
|
||||
**** URI ****
|
||||
*/
|
||||
it("should set the base URI and return the proper tokenURI", async () => {
|
||||
const baseURI = "https://interrep.link/tokens/";
|
||||
const tokenId = 1;
|
||||
|
||||
await badge.connect(deployer).changeBaseURI(baseURI);
|
||||
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
|
||||
expect(await badge.tokenURI(1)).to.eq(baseURI + tokenId.toString());
|
||||
});
|
||||
|
||||
it("should only let the deployer change the base URI", async () => {
|
||||
await expect(badge.connect(signer1).changeBaseURI("https://opensea.io/")).to.be.revertedWith(
|
||||
"Ownable: caller is not the owner",
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
**** TRANSFER ****
|
||||
*/
|
||||
it("should let token holders transfer their token", async () => {
|
||||
const tokenId = 6;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
|
||||
await expect(() =>
|
||||
badge.connect(signer1)["safeTransferFrom(address,address,uint256)"](signer1.address, signer2.address, tokenId),
|
||||
).to.changeTokenBalances(badge, [signer1, signer2], [-1, 1]);
|
||||
});
|
||||
|
||||
it("should let approved accounts transfer a token", async () => {
|
||||
const tokenId = 77;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
|
||||
await badge.connect(signer1).approve(signer2.address, tokenId);
|
||||
|
||||
await badge
|
||||
.connect(signer2)
|
||||
["safeTransferFrom(address,address,uint256)"](signer1.address, deployer.address, tokenId);
|
||||
|
||||
expect(await badge.ownerOf(tokenId)).to.eq(deployer.address);
|
||||
});
|
||||
|
||||
it("should not let unapproved transfers happen", async () => {
|
||||
const tokenId = 8;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
|
||||
await expect(
|
||||
badge.connect(signer2)["safeTransferFrom(address,address,uint256)"](signer1.address, signer2.address, tokenId),
|
||||
).to.be.revertedWith("ERC721: transfer caller is not owner nor approved");
|
||||
});
|
||||
|
||||
it("should not let transfer happen when paused", async () => {
|
||||
const tokenId = 991;
|
||||
await badge.connect(backend).safeMint(signer1.address, tokenId);
|
||||
|
||||
await badge.connect(deployer).pause();
|
||||
|
||||
await expect(
|
||||
badge.connect(signer1)["safeTransferFrom(address,address,uint256)"](signer1.address, signer2.address, tokenId),
|
||||
).to.be.revertedWith("Pausable: paused");
|
||||
});
|
||||
});
|
||||
await badge.connect(deployer).pause()
|
||||
|
||||
await expect(
|
||||
badge
|
||||
.connect(signer1)
|
||||
["safeTransferFrom(address,address,uint256)"](signer1.address, signer2.address, tokenId)
|
||||
).to.be.revertedWith("Pausable: paused")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
import hre from "hardhat";
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address";
|
||||
import { expect } from "chai";
|
||||
import { Contract, ContractFactory } from "@ethersproject/contracts";
|
||||
import hre from "hardhat"
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"
|
||||
import { expect } from "chai"
|
||||
import { Contract, ContractFactory } from "@ethersproject/contracts"
|
||||
|
||||
const { ethers, upgrades } = hre;
|
||||
const { ethers, upgrades } = hre
|
||||
|
||||
describe("ReputationBadge upgrade", function () {
|
||||
let badge: Contract;
|
||||
let badgeTestV2: Contract;
|
||||
let deployer: SignerWithAddress;
|
||||
let backend: SignerWithAddress;
|
||||
let signer1: SignerWithAddress;
|
||||
describe("ReputationBadge upgrade", () => {
|
||||
let badge: Contract
|
||||
let badgeTestV2: Contract
|
||||
let deployer: SignerWithAddress
|
||||
let backend: SignerWithAddress
|
||||
let signer1: SignerWithAddress
|
||||
|
||||
const badgeName = "TwitterBadge";
|
||||
const badgeSymbol = "iTWITT";
|
||||
const badgeName = "TwitterBadge"
|
||||
const badgeSymbol = "iTWITT"
|
||||
|
||||
before(async function () {
|
||||
[deployer, backend, signer1] = await hre.ethers.getSigners();
|
||||
});
|
||||
before(async () => {
|
||||
;[deployer, backend, signer1] = await hre.ethers.getSigners()
|
||||
})
|
||||
|
||||
beforeEach(async function () {
|
||||
const BadgeFactory: ContractFactory = await ethers.getContractFactory("ReputationBadge");
|
||||
const BadgeV2Factory: ContractFactory = await ethers.getContractFactory("ReputationBadgeV2Test");
|
||||
beforeEach(async () => {
|
||||
const BadgeFactory: ContractFactory = await ethers.getContractFactory("ReputationBadge")
|
||||
const BadgeV2Factory: ContractFactory = await ethers.getContractFactory("ReputationBadgeV2Test")
|
||||
|
||||
badge = await upgrades.deployProxy(BadgeFactory, [badgeName, badgeSymbol, backend.address]);
|
||||
badgeTestV2 = await upgrades.upgradeProxy(badge.address, BadgeV2Factory);
|
||||
});
|
||||
badge = await upgrades.deployProxy(BadgeFactory, [badgeName, badgeSymbol, backend.address])
|
||||
badgeTestV2 = await upgrades.upgradeProxy(badge.address, BadgeV2Factory)
|
||||
})
|
||||
|
||||
it("should return from the new function", async () => {
|
||||
expect(await badgeTestV2.thisIsATest()).to.eq(42);
|
||||
});
|
||||
it("should return from the new function", async () => {
|
||||
expect(await badgeTestV2.thisIsATest()).to.eq(42)
|
||||
})
|
||||
|
||||
it("should return the badge name", async () => {
|
||||
expect(await badgeTestV2.name()).to.eq(badgeName);
|
||||
});
|
||||
it("should return the badge name", async () => {
|
||||
expect(await badgeTestV2.name()).to.eq(badgeName)
|
||||
})
|
||||
|
||||
it("should return the badge symbol", async () => {
|
||||
expect(await badgeTestV2.symbol()).to.eq(badgeSymbol);
|
||||
});
|
||||
it("should return the badge symbol", async () => {
|
||||
expect(await badgeTestV2.symbol()).to.eq(badgeSymbol)
|
||||
})
|
||||
|
||||
it("should let the deployer pause", async () => {
|
||||
await badge.connect(deployer).pause();
|
||||
it("should let the deployer pause", async () => {
|
||||
await badge.connect(deployer).pause()
|
||||
|
||||
expect(await badge.paused()).to.be.true;
|
||||
});
|
||||
expect(await badge.paused()).to.be.true
|
||||
})
|
||||
|
||||
it("should let the backend mint a token", async () => {
|
||||
await badge.connect(backend).safeMint(signer1.address, 1);
|
||||
it("should let the backend mint a token", async () => {
|
||||
await badge.connect(backend).safeMint(signer1.address, 1)
|
||||
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1);
|
||||
expect(await badge.ownerOf(1)).to.eq(signer1.address);
|
||||
});
|
||||
expect(await badge.balanceOf(signer1.address)).to.eq(1)
|
||||
expect(await badge.ownerOf(1)).to.eq(signer1.address)
|
||||
})
|
||||
|
||||
it("should only let the backend mint a token", async () => {
|
||||
await expect(badge.connect(signer1).safeMint(signer1.address, 234)).to.be.revertedWith("Unauthorized");
|
||||
});
|
||||
it("should only let the backend mint a token", async () => {
|
||||
await expect(badge.connect(signer1).safeMint(signer1.address, 234)).to.be.revertedWith("Unauthorized")
|
||||
})
|
||||
|
||||
it("should let the deployer change the backend address", async () => {
|
||||
// change backend address
|
||||
const tx = await badge.connect(deployer).changeBackendAddress(signer1.address);
|
||||
await tx.wait();
|
||||
it("should let the deployer change the backend address", async () => {
|
||||
// change backend address
|
||||
const tx = await badge.connect(deployer).changeBackendAddress(signer1.address)
|
||||
await tx.wait()
|
||||
|
||||
// check backendAddress was changed
|
||||
expect(await badge.backendAddress()).to.eq(signer1.address);
|
||||
});
|
||||
// check backendAddress was changed
|
||||
expect(await badge.backendAddress()).to.eq(signer1.address)
|
||||
})
|
||||
|
||||
it("should only let the deployer change the backend address", async () => {
|
||||
await expect(badge.connect(signer1).changeBackendAddress(signer1.address)).to.be.revertedWith(
|
||||
"Ownable: caller is not the owner",
|
||||
);
|
||||
});
|
||||
});
|
||||
it("should only let the deployer change the backend address", async () => {
|
||||
await expect(badge.connect(signer1).changeBackendAddress(signer1.address)).to.be.revertedWith(
|
||||
"Ownable: caller is not the owner"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": ["es5", "es6"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"target": "es5"
|
||||
},
|
||||
"exclude": ["artifacts", "node_modules"],
|
||||
"files": ["./hardhat.config.ts"],
|
||||
"include": [
|
||||
"artifacts/**/*",
|
||||
"artifacts/**/*.json",
|
||||
"scripts/**/*",
|
||||
"tasks/**/*",
|
||||
"test/**/*",
|
||||
"typechain/**/*",
|
||||
"types/**/*"
|
||||
]
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": ["es5", "es6"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"target": "es5"
|
||||
},
|
||||
"exclude": ["artifacts", "node_modules"],
|
||||
"files": ["./hardhat.config.ts"],
|
||||
"include": [
|
||||
"artifacts/**/*",
|
||||
"artifacts/**/*.json",
|
||||
"scripts/**/*",
|
||||
"tasks/**/*",
|
||||
"test/**/*",
|
||||
"typechain/**/*",
|
||||
"types/**/*"
|
||||
]
|
||||
}
|
||||
|
||||
16
types/augmentations.d.ts
vendored
16
types/augmentations.d.ts
vendored
@@ -1,13 +1,13 @@
|
||||
// eslint-disable @typescript-eslint/no-explicit-any
|
||||
import { Fixture } from "ethereum-waffle";
|
||||
import { Fixture } from "ethereum-waffle"
|
||||
|
||||
import { Signers } from "./";
|
||||
import { Greeter } from "../typechain/Greeter";
|
||||
import { Signers } from "./"
|
||||
import { Greeter } from "../typechain/Greeter"
|
||||
|
||||
declare module "mocha" {
|
||||
export interface Context {
|
||||
greeter: Greeter;
|
||||
loadFixture: <T>(fixture: Fixture<T>) => Promise<T>;
|
||||
signers: Signers;
|
||||
}
|
||||
export interface Context {
|
||||
greeter: Greeter
|
||||
loadFixture: <T>(fixture: Fixture<T>) => Promise<T>
|
||||
signers: Signers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address";
|
||||
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"
|
||||
|
||||
export interface Signers {
|
||||
admin: SignerWithAddress;
|
||||
admin: SignerWithAddress
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user