style: update lint configuration

This commit is contained in:
cedoor
2021-08-26 16:59:56 +02:00
parent b2cca77245
commit 42d0cfe422
25 changed files with 624 additions and 614 deletions

View File

@@ -1,3 +0,0 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
};

3
.commitlintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": ["@commitlint/config-conventional"]
}

View File

@@ -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
View 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"]
}
}

View File

@@ -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: _

View File

@@ -1,6 +0,0 @@
{
"./**/*.{js,json,md,sol,ts}": [
"prettier --write",
"eslint --fix"
]
}

6
.lintstagedrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"**/*.{js,json,md,sol,ts}": [
"prettier --config ./.prettierrc.json --write",
"eslint --config ./.eslintrc.json --fix"
]
}

View File

@@ -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
View File

@@ -0,0 +1,5 @@
{
"semi": false,
"arrowParens": "always",
"trailingComma": "none"
}

View File

@@ -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"]
}

View File

@@ -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 }]
}
}

View File

@@ -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"
}
```

View File

@@ -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 accounts reputation based on publicly available data.

View File

@@ -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

View File

@@ -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

View File

@@ -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"
}
}

View File

@@ -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())
}
})

View File

@@ -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()
})

View File

@@ -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}`)
})

View File

@@ -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`)
})

View File

@@ -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")
})
})

View File

@@ -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"
)
})
})

View File

@@ -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/**/*"
]
}

View File

@@ -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
}
}

View File

@@ -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
}