├── .babelrc
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── src
├── frontend
│ ├── contractsData
│ │ ├── EnsName-address.json
│ │ └── EnsName.json
│ └── components
│ │ ├── logo.png
│ │ ├── Loading.js
│ │ ├── App.css
│ │ ├── Navbar.js
│ │ ├── BuyEns.js
│ │ ├── ListItem.js
│ │ ├── App.js
│ │ └── ENSContract.json
├── index.js
├── backend
│ ├── scripts
│ │ └── deploy.js
│ ├── contracts
│ │ └── EnsName.sol
│ └── test
│ │ └── test.js
└── serviceWorker.js
├── .env.example
├── hardhat.config.js
├── .gitignore
├── Readme.md
└── package.json
/.babelrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | {
4 | "presets": [
5 | "@babel/preset-env"
6 | ]
7 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dappuniversity/ENS-Marketplace/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/frontend/contractsData/EnsName-address.json:
--------------------------------------------------------------------------------
1 | {
2 | "address": "0xC174d0bcD0b20F9723Eec70e931cAd9Db9b51dc0"
3 | }
--------------------------------------------------------------------------------
/src/frontend/components/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dappuniversity/ENS-Marketplace/HEAD/src/frontend/components/logo.png
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | ALCHEMY_API_KEY=
2 | INFURA_API_KEY=
3 |
4 | PRIVATE_KEY=
5 |
6 | ETHERSCAN_API_KEY=
7 |
8 |
9 | RINKEBY_RPC=
10 |
11 | POLYGON_MUMBAI_RPC=
12 |
13 | GOERLI_RPC=
14 |
15 | KOVAN_RPC=
16 |
17 | ROPSTEN_RPC=
18 |
19 |
20 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/hardhat.config.js:
--------------------------------------------------------------------------------
1 | require("@nomicfoundation/hardhat-toolbox");
2 | require('dotenv').config()
3 |
4 | module.exports = {
5 | solidity: "0.8.9",
6 | networks: {
7 | ropsten: {
8 | url: process.env.ROPSTEN_RPC,
9 | accounts: [process.env.PRIVATE_KEY]
10 | }
11 | },
12 | paths: {
13 | artifacts: "./src/backend/artifacts",
14 | sources: "./src/backend/contracts",
15 | cache: "./src/backend/cache",
16 | tests: "./src/backend/test"
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/src/frontend/components/Loading.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Loading = ({val}) => {
4 | return (
5 |
6 |
7 |
12 | {val}
13 |
14 |
15 | )
16 | }
17 |
18 | export default Loading
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | node_modules
26 | .env
27 | coverage
28 | coverage.json
29 | typechain
30 |
31 | #Hardhat files
32 | cache
33 | artifacts
34 |
--------------------------------------------------------------------------------
/src/frontend/components/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # ENS Domain marketplace
2 | List and sell your ens domains
3 |
4 | ## Technology Stack & Dependencies
5 |
6 | - Solidity (Writing Smart Contract)
7 | - Javascript (Game interaction)
8 | - [Alchemy](https://www.alchemy.com/) As a node provider
9 | - [NodeJS](https://nodejs.org/en/) To create hardhat project and install dependencis using npm
10 | - [Hardhat](https://hardhat.org/) Develop, test and deploy smart contract
11 |
12 |
13 | ### 1. Clone/Download the Repository
14 |
15 | ### 2. Install Dependencies:
16 | ```
17 | $ npm install
18 | ```
19 |
20 | ### 3. Deploy contracts to Ropsten and Run dapp
21 | - Input your private key and ropsten RPC in .env file
22 | ```
23 | $ npx hardhat compile
24 | ```
25 | ```
26 | $ npm run deploy-ropsten
27 | ```
28 | ```
29 | $ npm start
30 | ```
31 |
32 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import 'bootstrap';
4 | import 'bootstrap/dist/css/bootstrap.min.css';
5 | import App from './frontend/components/App';
6 | import * as serviceWorker from './serviceWorker';
7 | import { BrowserRouter } from 'react-router-dom';
8 |
9 | const root = ReactDOM.createRoot(document.getElementById('root'));
10 | root.render(
11 |
12 |
13 |
14 |
15 |
16 | );
17 |
18 |
19 |
20 | // If you want your app to work offline and load faster, you can change
21 | // unregister() to register() below. Note this comes with some pitfalls.
22 | // Learn more about service workers: https://bit.ly/CRA-PWA
23 | serviceWorker.unregister();
24 |
--------------------------------------------------------------------------------
/src/backend/scripts/deploy.js:
--------------------------------------------------------------------------------
1 | async function main() {
2 |
3 | const [deployer] = await ethers.getSigners();
4 |
5 | console.log("Deploying contracts with the account:", deployer.address);
6 | console.log("Account balance:", (await deployer.getBalance()).toString());
7 |
8 |
9 | // deploy contracts here:
10 | const Contract = await ethers.getContractFactory('EnsName');
11 | const contract = await Contract.deploy();
12 |
13 | console.log("Contract was deployed to Address: ", contract.address);
14 | // For each contract, pass the deployed contract and name to this function to save a copy of the contract ABI and address to the front end.
15 | saveFrontendFiles(contract, 'EnsName');
16 | }
17 |
18 | function saveFrontendFiles(contract, name) {
19 | const fs = require("fs");
20 | const contractsDir = __dirname + "/../../frontend/contractsData";
21 |
22 | if (!fs.existsSync(contractsDir)) {
23 | fs.mkdirSync(contractsDir);
24 | }
25 |
26 | fs.writeFileSync(
27 | contractsDir + `/${name}-address.json`,
28 | JSON.stringify({ address: contract.address }, undefined, 2)
29 | );
30 |
31 | const contractArtifact = artifacts.readArtifactSync(name);
32 |
33 | fs.writeFileSync(
34 | contractsDir + `/${name}.json`,
35 | JSON.stringify(contractArtifact, null, 2)
36 | );
37 | }
38 |
39 | main()
40 | .then(() => process.exit(0))
41 | .catch(error => {
42 | console.error(error);
43 | process.exit(1);
44 | });
45 |
--------------------------------------------------------------------------------
/src/backend/contracts/EnsName.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.7;
3 |
4 | import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
5 |
6 | contract EnsName {
7 | uint256 public itemCount;
8 |
9 | struct Item{
10 | uint256 itemId;
11 | string name;
12 | uint256 tokenId;
13 | uint256 price;
14 | bool listed;
15 | address payable seller;
16 | }
17 |
18 | mapping(uint256 => Item) public items;
19 | IERC721 public immutable ensContract;
20 |
21 | constructor (){
22 | ensContract = IERC721(0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85);
23 | }
24 |
25 | //Function to list the item for sale, approve this contract
26 | function listENS(string memory _name, uint256 _tokenId, uint256 _price) public{
27 | require(_price > 0, "Price should be greater than 0");
28 | itemCount++;
29 | items[itemCount] = Item(
30 | itemCount,
31 | _name,
32 | _tokenId,
33 | _price,
34 | true,
35 | payable(msg.sender)
36 | );
37 | }
38 |
39 | //Function to buy the ENS - ie - transferFrom
40 | function buyENS(uint256 _itemId) public payable{
41 | Item memory eachItem = items[_itemId];
42 | require(msg.value >= eachItem.price, "Price sent is not correct");
43 | require(_itemId > 0 && _itemId <= itemCount, "Wrong itemId");
44 | require(eachItem.listed == true, "This item is has not been listed for sale");
45 | ensContract.transferFrom(eachItem.seller, msg.sender, eachItem.tokenId);
46 | eachItem.listed = false;
47 | (bool sent, ) = eachItem.seller.call{value: msg.value}("");
48 | require(sent, "Failed to send Ether");
49 | }
50 |
51 | receive() external payable{}
52 |
53 | }
--------------------------------------------------------------------------------
/src/frontend/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | const Navbar = ({logo, connectWallet, account, loading}) => {
5 | return (
6 |
44 | );
45 | };
46 |
47 | export default Navbar;
48 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "make-web3-dapp",
3 | "keywords": [
4 | "web3",
5 | "create-web3-dapp",
6 | "hardhat",
7 | "ethers",
8 | "solidity",
9 | "ethereum",
10 | "dapp"
11 | ],
12 | "dependencies": {
13 | "@babel/preset-react": "^7.18.6",
14 | "@nomicfoundation/hardhat-toolbox": "^1.0.2",
15 | "@openzeppelin/contracts": "^4.7.2",
16 | "@popperjs/core": "^2.11.5",
17 | "@testing-library/jest-dom": "^5.16.4",
18 | "@testing-library/react": "^13.3.0",
19 | "@testing-library/user-event": "^14.2.5",
20 | "alchemy-sdk": "^2.0.1",
21 | "bootstrap": "^5.1.3",
22 | "dotenv": "^16.0.1",
23 | "ethers": "^5.6.9",
24 | "hardhat": "^2.10.1",
25 | "jquery": "^3.6.0",
26 | "popper.js": "^1.16.1",
27 | "react": "^18.2.0",
28 | "react-dom": "^18.2.0",
29 | "react-router-dom": "^6.3.0",
30 | "react-scripts": "5.0.1",
31 | "web-vitals": "^2.1.4"
32 | },
33 | "scripts": {
34 | "deploy": "npx hardhat run src/backend/scripts/deploy.js",
35 | "deploy-ropsten": "npx hardhat run src/backend/scripts/deploy.js --network ropsten",
36 | "start": "react-scripts start",
37 | "build": "react-scripts build",
38 | "test": "react-scripts test",
39 | "eject": "react-scripts eject"
40 | },
41 | "eslintConfig": {
42 | "extends": [
43 | "react-app",
44 | "react-app/jest"
45 | ]
46 | },
47 | "browserslist": {
48 | "production": [
49 | ">0.2%",
50 | "not dead",
51 | "not op_mini all"
52 | ],
53 | "development": [
54 | "last 1 chrome version",
55 | "last 1 firefox version",
56 | "last 1 safari version"
57 | ]
58 | },
59 | "devDependencies": {
60 | "@babel/preset-env": "^7.18.9",
61 | "@nomicfoundation/hardhat-chai-matchers": "^1.0.2",
62 | "@nomicfoundation/hardhat-network-helpers": "^1.0.3",
63 | "@nomiclabs/hardhat-ethers": "^2.1.0",
64 | "@nomiclabs/hardhat-etherscan": "^3.1.0",
65 | "@typechain/ethers-v5": "^10.1.0",
66 | "@typechain/hardhat": "^6.1.2",
67 | "@types/chai": "^4.3.3",
68 | "@types/mocha": "^9.1.1",
69 | "chai": "^4.3.6",
70 | "hardhat-gas-reporter": "^1.0.8",
71 | "solidity-coverage": "^0.7.21",
72 | "ts-node": "^10.9.1",
73 | "typechain": "^8.1.0",
74 | "typescript": "^4.7.4"
75 | },
76 | "bin": {
77 | "make-web3-dapp": "./bin/generate-app.js"
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/frontend/components/BuyEns.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import Loading from './Loading';
3 |
4 | const BuyEns = ({ marketplace, ENSContract }) => {
5 | const [allListings, setAllListings] = useState([]);
6 | const [loading, setLoading] = useState(false);
7 | const [buyLoading, setBuyLoading] = useState(false);
8 |
9 | useEffect(() => {
10 | if (marketplace !== '') {
11 | allListing();
12 | }
13 | }, [marketplace]);
14 |
15 | const allListing = async () => {
16 | setLoading(true);
17 | try {
18 | const itemCount = await marketplace.itemCount();
19 | let items = [];
20 | for (let i = 1; i <= itemCount; i++) {
21 | const item = await marketplace.items(i);
22 |
23 | if (item.listed) {
24 | const itemId = item.itemId.toString();
25 | const price = item.price.toString();
26 | //add all these to an array and save in state
27 | items.push({
28 | price: price,
29 | name: item.name,
30 | itemId: itemId,
31 | seller: item.seller,
32 | });
33 | }
34 | }
35 | setLoading(false);
36 | // console.log(items);
37 | setAllListings(items);
38 | } catch (error) {
39 | setLoading(false);
40 | console.log(error);
41 | }
42 | };
43 |
44 | const buyListing = async (item) => {
45 | setBuyLoading(true)
46 | try {
47 | const tx = await marketplace.buyENS(item.itemId, {
48 | value: item.price,
49 | });
50 | await tx.wait();
51 | alert('Congrats! You have bought the ENS', item.name);
52 | setBuyLoading(false);
53 | allListing();
54 | } catch (error) {
55 | setBuyLoading(false);
56 | console.log(error);
57 | }
58 | };
59 |
60 | return (
61 |
62 |
Explore and Buy ENS
63 | {loading ? (
64 |
65 | ) : allListings.length === 0 ? (
66 |
There are currently no ENS for Sale
67 | ) : (
68 |
69 | {allListings.map((item, i) => (
70 |
71 |
72 |
73 |
{item.name}
74 |
75 | Price: {item.price / 10 ** 18} ETH
76 |
77 |
94 |
95 |
96 |
97 | )
98 | )}
99 |
100 | )}
101 |
102 | );
103 | };
104 |
105 | export default BuyEns;
106 |
--------------------------------------------------------------------------------
/src/frontend/components/ListItem.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { Alchemy, Network } from 'alchemy-sdk';
3 | import { ethers } from 'ethers';
4 | import Loading from './Loading';
5 |
6 | const ListItem = ({ EnsNameAddress, marketplace, ENSContract, account }) => {
7 | const [ensNames, setEnsNames] = useState([]);
8 | const [price, setPrice] = useState(null);
9 | const [loading, setLoading] = useState(false);
10 | const [loadPage, setLoadPage] = useState(false);
11 |
12 | useEffect(() => {
13 | if (account != null) {
14 | getAllENS();
15 | }
16 | }, [account]);
17 |
18 | const getAllENS = async () => {
19 | setLoadPage(true);
20 | const config = {
21 | apiKey: process.env.ALCHEMY_API,
22 | network: Network.ETH_ROPSTEN,
23 | };
24 |
25 | const alchemy = new Alchemy(config);
26 |
27 | const ensContractAddress = '0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85';
28 | const ens = await alchemy.nft.getNftsForOwner(account, {
29 | contractAddresses: [ensContractAddress],
30 | });
31 |
32 | setEnsNames(ens.ownedNfts);
33 | console.log(ens.ownedNfts);
34 | setLoadPage(false);
35 | };
36 |
37 | const listForSale = async (tokId, ensName) => {
38 | setLoading(true);
39 | try {
40 | const tx = await ENSContract.setApprovalForAll(
41 | EnsNameAddress.address,
42 | true
43 | );
44 | await tx.wait();
45 | let priceInEth = ethers.utils.parseEther(price.toString());
46 | const tx2 = await marketplace.listENS(ensName, tokId, priceInEth);
47 | await tx2.wait();
48 | alert('Awesome! You have now Listed your Item for Sale!');
49 | setLoading(false);
50 | } catch (err) {
51 | setLoading(false);
52 | console.log(err);
53 | }
54 | };
55 |
56 | return (
57 |
58 | {loadPage ? (
59 |
60 | ) : (
61 |
62 |
You Own the Following ENS Domains:
63 |
64 | {ensNames.length === 0 ? (
65 |
66 |
Sorry You do Not Own any ENS Domains!
67 |
68 | ) : loading ? (
69 |
70 | ) : (
71 | ensNames.map((na, i) => (
72 |
73 |
79 | setPrice(e.target.value)}
83 | placeholder='Enter the Price in ETH at which you want to List'
84 | required
85 | />
86 |
94 |
95 | ))
96 | )}
97 |
98 | )}
99 |
100 | );
101 | };
102 |
103 | export default ListItem;
104 |
105 | {
106 | /*
107 | */
108 | }
109 |
--------------------------------------------------------------------------------
/src/frontend/components/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import logo from './logo.png';
3 | import EnsNameAbi from '../contractsData/EnsName.json'
4 | import EnsNameAddress from '../contractsData/EnsName-address.json'
5 | import ensAbi from './ENSContract.json'
6 | import React, { useEffect, useState } from 'react';
7 | import Navbar from './Navbar';
8 | import { ethers } from 'ethers';
9 | import ListItem from './ListItem';
10 | import { Route, Routes } from 'react-router-dom';
11 | import BuyEns from './BuyEns';
12 |
13 | const App = () => {
14 |
15 |
16 |
17 |
18 | const [account, setAccount] = useState(null);
19 | const [loading, setLoading] = useState(false);
20 | const [marketplace, setMarketplace] = useState('');
21 | const [ENSContract, setENSContract] = useState('');
22 |
23 |
24 | const ENSContractAddress = "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85";
25 |
26 | useEffect(() => {
27 | checkIfWalletIsConnected();
28 |
29 | window.ethereum.on('chainChanged', (chainId) => {
30 | window.location.reload();
31 | })
32 |
33 | window.ethereum.on('accountsChanged', async function (accounts) {
34 | setAccount(accounts[0])
35 | await checkIfWalletIsConnected();
36 | window.location.reload();
37 | })
38 | }, []);
39 |
40 |
41 |
42 |
43 | const checkIfWalletIsConnected = async () => {
44 | try {
45 | setLoading(true)
46 | if (!window.ethereum) {
47 | alert('No Web3 Provider Detected. Kindly Install Metamask');
48 | } else {
49 | const accounts = await window.ethereum.request({
50 | method: 'eth_accounts',
51 | });
52 | if (accounts.length !== 0) {
53 | setAccount(accounts[0]);
54 | loadContracts();
55 | } else {
56 | console.log('Please Connect Your Wallet');
57 | }
58 | }
59 | } catch (err) {
60 | setLoading(false);
61 | console.log(err);
62 | }
63 | };
64 |
65 | const connectWallet = async () => {
66 | try {
67 | if (!window.ethereum) {
68 | alert('No Web3 Provider Detected. Kindly Install Metamask');
69 | } else {
70 | setLoading(true);
71 | const accounts = await window.ethereum.request({
72 | method: 'eth_requestAccounts',
73 | });
74 | setAccount(accounts[0]);
75 | loadContracts();
76 | }
77 | setLoading(false);
78 | } catch (err) {
79 | setLoading(false);
80 | console.log(err);
81 | }
82 | };
83 |
84 | //loading contracts
85 | const loadContracts = async () => {
86 | try {
87 | const provider = new ethers.providers.Web3Provider(window.ethereum);
88 | const signer = provider.getSigner();
89 | const mp = new ethers.Contract(
90 | EnsNameAddress.address,
91 | EnsNameAbi.abi,
92 | signer
93 | );
94 | setMarketplace(mp);
95 | const ensCont = new ethers.Contract(ENSContractAddress, ensAbi.abi, signer);
96 | setENSContract(ensCont);
97 |
98 | // console.log(await signer.provider.getCode(marketplace))
99 |
100 | console.log('Contracts Loaded!');
101 | setLoading(false);
102 | } catch (err) {
103 | setLoading(false);
104 | console.log(err);
105 | }
106 | };
107 |
108 |
109 | return (
110 |
111 |
112 |
113 |
114 | }>
115 | }>
116 |
117 |
118 |
119 |
120 | );
121 | };
122 |
123 | export default App;
124 |
--------------------------------------------------------------------------------
/src/backend/test/test.js:
--------------------------------------------------------------------------------
1 | const {
2 | time,
3 | loadFixture,
4 | } = require("@nomicfoundation/hardhat-network-helpers");
5 | const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
6 | const { expect } = require("chai");
7 |
8 | describe("Lock", function () {
9 | // We define a fixture to reuse the same setup in every test.
10 | // We use loadFixture to run this setup once, snapshot that state,
11 | // and reset Hardhat Network to that snapshopt in every test.
12 | async function deployOneYearLockFixture() {
13 | const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
14 | const ONE_GWEI = 1_000_000_000;
15 |
16 | const lockedAmount = ONE_GWEI;
17 | const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS;
18 |
19 | // Contracts are deployed using the first signer/account by default
20 | const [owner, otherAccount] = await ethers.getSigners();
21 |
22 | const Lock = await ethers.getContractFactory("Lock");
23 | const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
24 |
25 | return { lock, unlockTime, lockedAmount, owner, otherAccount };
26 | }
27 |
28 | describe("Deployment", function () {
29 | it("Should set the right unlockTime", async function () {
30 | const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
31 |
32 | expect(await lock.unlockTime()).to.equal(unlockTime);
33 | });
34 |
35 | it("Should set the right owner", async function () {
36 | const { lock, owner } = await loadFixture(deployOneYearLockFixture);
37 |
38 | expect(await lock.owner()).to.equal(owner.address);
39 | });
40 |
41 | it("Should receive and store the funds to lock", async function () {
42 | const { lock, lockedAmount } = await loadFixture(
43 | deployOneYearLockFixture
44 | );
45 |
46 | expect(await ethers.provider.getBalance(lock.address)).to.equal(
47 | lockedAmount
48 | );
49 | });
50 |
51 | it("Should fail if the unlockTime is not in the future", async function () {
52 | // We don't use the fixture here because we want a different deployment
53 | const latestTime = await time.latest();
54 | const Lock = await ethers.getContractFactory("Lock");
55 | await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
56 | "Unlock time should be in the future"
57 | );
58 | });
59 | });
60 |
61 | describe("Withdrawals", function () {
62 | describe("Validations", function () {
63 | it("Should revert with the right error if called too soon", async function () {
64 | const { lock } = await loadFixture(deployOneYearLockFixture);
65 |
66 | await expect(lock.withdraw()).to.be.revertedWith(
67 | "You can't withdraw yet"
68 | );
69 | });
70 |
71 | it("Should revert with the right error if called from another account", async function () {
72 | const { lock, unlockTime, otherAccount } = await loadFixture(
73 | deployOneYearLockFixture
74 | );
75 |
76 | // We can increase the time in Hardhat Network
77 | await time.increaseTo(unlockTime);
78 |
79 | // We use lock.connect() to send a transaction from another account
80 | await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith(
81 | "You aren't the owner"
82 | );
83 | });
84 |
85 | it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () {
86 | const { lock, unlockTime } = await loadFixture(
87 | deployOneYearLockFixture
88 | );
89 |
90 | // Transactions are sent using the first signer by default
91 | await time.increaseTo(unlockTime);
92 |
93 | await expect(lock.withdraw()).not.to.be.reverted;
94 | });
95 | });
96 |
97 | describe("Events", function () {
98 | it("Should emit an event on withdrawals", async function () {
99 | const { lock, unlockTime, lockedAmount } = await loadFixture(
100 | deployOneYearLockFixture
101 | );
102 |
103 | await time.increaseTo(unlockTime);
104 |
105 | await expect(lock.withdraw())
106 | .to.emit(lock, "Withdrawal")
107 | .withArgs(lockedAmount, anyValue); // We accept any value as `when` arg
108 | });
109 | });
110 |
111 | describe("Transfers", function () {
112 | it("Should transfer the funds to the owner", async function () {
113 | const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
114 | deployOneYearLockFixture
115 | );
116 |
117 | await time.increaseTo(unlockTime);
118 |
119 | await expect(lock.withdraw()).to.changeEtherBalances(
120 | [owner, lock],
121 | [lockedAmount, -lockedAmount]
122 | );
123 | });
124 | });
125 | });
126 | });
127 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/frontend/components/ENSContract.json:
--------------------------------------------------------------------------------
1 | {
2 | "_format": "hh-sol-artifact-1",
3 | "contractName": "EnsName",
4 | "abi": [
5 | {
6 | "inputs": [
7 | { "internalType": "contract ENS", "name": "_ens", "type": "address" },
8 | { "internalType": "bytes32", "name": "_baseNode", "type": "bytes32" }
9 | ],
10 | "payable": false,
11 | "stateMutability": "nonpayable",
12 | "type": "constructor"
13 | },
14 | {
15 | "anonymous": false,
16 | "inputs": [
17 | {
18 | "indexed": true,
19 | "internalType": "address",
20 | "name": "owner",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": true,
25 | "internalType": "address",
26 | "name": "approved",
27 | "type": "address"
28 | },
29 | {
30 | "indexed": true,
31 | "internalType": "uint256",
32 | "name": "tokenId",
33 | "type": "uint256"
34 | }
35 | ],
36 | "name": "Approval",
37 | "type": "event"
38 | },
39 | {
40 | "anonymous": false,
41 | "inputs": [
42 | {
43 | "indexed": true,
44 | "internalType": "address",
45 | "name": "owner",
46 | "type": "address"
47 | },
48 | {
49 | "indexed": true,
50 | "internalType": "address",
51 | "name": "operator",
52 | "type": "address"
53 | },
54 | {
55 | "indexed": false,
56 | "internalType": "bool",
57 | "name": "approved",
58 | "type": "bool"
59 | }
60 | ],
61 | "name": "ApprovalForAll",
62 | "type": "event"
63 | },
64 | {
65 | "anonymous": false,
66 | "inputs": [
67 | {
68 | "indexed": true,
69 | "internalType": "address",
70 | "name": "controller",
71 | "type": "address"
72 | }
73 | ],
74 | "name": "ControllerAdded",
75 | "type": "event"
76 | },
77 | {
78 | "anonymous": false,
79 | "inputs": [
80 | {
81 | "indexed": true,
82 | "internalType": "address",
83 | "name": "controller",
84 | "type": "address"
85 | }
86 | ],
87 | "name": "ControllerRemoved",
88 | "type": "event"
89 | },
90 | {
91 | "anonymous": false,
92 | "inputs": [
93 | {
94 | "indexed": true,
95 | "internalType": "uint256",
96 | "name": "id",
97 | "type": "uint256"
98 | },
99 | {
100 | "indexed": true,
101 | "internalType": "address",
102 | "name": "owner",
103 | "type": "address"
104 | },
105 | {
106 | "indexed": false,
107 | "internalType": "uint256",
108 | "name": "expires",
109 | "type": "uint256"
110 | }
111 | ],
112 | "name": "NameMigrated",
113 | "type": "event"
114 | },
115 | {
116 | "anonymous": false,
117 | "inputs": [
118 | {
119 | "indexed": true,
120 | "internalType": "uint256",
121 | "name": "id",
122 | "type": "uint256"
123 | },
124 | {
125 | "indexed": true,
126 | "internalType": "address",
127 | "name": "owner",
128 | "type": "address"
129 | },
130 | {
131 | "indexed": false,
132 | "internalType": "uint256",
133 | "name": "expires",
134 | "type": "uint256"
135 | }
136 | ],
137 | "name": "NameRegistered",
138 | "type": "event"
139 | },
140 | {
141 | "anonymous": false,
142 | "inputs": [
143 | {
144 | "indexed": true,
145 | "internalType": "uint256",
146 | "name": "id",
147 | "type": "uint256"
148 | },
149 | {
150 | "indexed": false,
151 | "internalType": "uint256",
152 | "name": "expires",
153 | "type": "uint256"
154 | }
155 | ],
156 | "name": "NameRenewed",
157 | "type": "event"
158 | },
159 | {
160 | "anonymous": false,
161 | "inputs": [
162 | {
163 | "indexed": true,
164 | "internalType": "address",
165 | "name": "previousOwner",
166 | "type": "address"
167 | },
168 | {
169 | "indexed": true,
170 | "internalType": "address",
171 | "name": "newOwner",
172 | "type": "address"
173 | }
174 | ],
175 | "name": "OwnershipTransferred",
176 | "type": "event"
177 | },
178 | {
179 | "anonymous": false,
180 | "inputs": [
181 | {
182 | "indexed": true,
183 | "internalType": "address",
184 | "name": "from",
185 | "type": "address"
186 | },
187 | {
188 | "indexed": true,
189 | "internalType": "address",
190 | "name": "to",
191 | "type": "address"
192 | },
193 | {
194 | "indexed": true,
195 | "internalType": "uint256",
196 | "name": "tokenId",
197 | "type": "uint256"
198 | }
199 | ],
200 | "name": "Transfer",
201 | "type": "event"
202 | },
203 | {
204 | "constant": true,
205 | "inputs": [],
206 | "name": "GRACE_PERIOD",
207 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
208 | "payable": false,
209 | "stateMutability": "view",
210 | "type": "function"
211 | },
212 | {
213 | "constant": false,
214 | "inputs": [
215 | { "internalType": "address", "name": "controller", "type": "address" }
216 | ],
217 | "name": "addController",
218 | "outputs": [],
219 | "payable": false,
220 | "stateMutability": "nonpayable",
221 | "type": "function"
222 | },
223 | {
224 | "constant": false,
225 | "inputs": [
226 | { "internalType": "address", "name": "to", "type": "address" },
227 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
228 | ],
229 | "name": "approve",
230 | "outputs": [],
231 | "payable": false,
232 | "stateMutability": "nonpayable",
233 | "type": "function"
234 | },
235 | {
236 | "constant": true,
237 | "inputs": [
238 | { "internalType": "uint256", "name": "id", "type": "uint256" }
239 | ],
240 | "name": "available",
241 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
242 | "payable": false,
243 | "stateMutability": "view",
244 | "type": "function"
245 | },
246 | {
247 | "constant": true,
248 | "inputs": [
249 | { "internalType": "address", "name": "owner", "type": "address" }
250 | ],
251 | "name": "balanceOf",
252 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
253 | "payable": false,
254 | "stateMutability": "view",
255 | "type": "function"
256 | },
257 | {
258 | "constant": true,
259 | "inputs": [],
260 | "name": "baseNode",
261 | "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }],
262 | "payable": false,
263 | "stateMutability": "view",
264 | "type": "function"
265 | },
266 | {
267 | "constant": true,
268 | "inputs": [{ "internalType": "address", "name": "", "type": "address" }],
269 | "name": "controllers",
270 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
271 | "payable": false,
272 | "stateMutability": "view",
273 | "type": "function"
274 | },
275 | {
276 | "constant": true,
277 | "inputs": [],
278 | "name": "ens",
279 | "outputs": [
280 | { "internalType": "contract ENS", "name": "", "type": "address" }
281 | ],
282 | "payable": false,
283 | "stateMutability": "view",
284 | "type": "function"
285 | },
286 | {
287 | "constant": true,
288 | "inputs": [
289 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
290 | ],
291 | "name": "getApproved",
292 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
293 | "payable": false,
294 | "stateMutability": "view",
295 | "type": "function"
296 | },
297 | {
298 | "constant": true,
299 | "inputs": [
300 | { "internalType": "address", "name": "owner", "type": "address" },
301 | { "internalType": "address", "name": "operator", "type": "address" }
302 | ],
303 | "name": "isApprovedForAll",
304 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
305 | "payable": false,
306 | "stateMutability": "view",
307 | "type": "function"
308 | },
309 | {
310 | "constant": true,
311 | "inputs": [],
312 | "name": "isOwner",
313 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
314 | "payable": false,
315 | "stateMutability": "view",
316 | "type": "function"
317 | },
318 | {
319 | "constant": true,
320 | "inputs": [
321 | { "internalType": "uint256", "name": "id", "type": "uint256" }
322 | ],
323 | "name": "nameExpires",
324 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
325 | "payable": false,
326 | "stateMutability": "view",
327 | "type": "function"
328 | },
329 | {
330 | "constant": true,
331 | "inputs": [],
332 | "name": "owner",
333 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
334 | "payable": false,
335 | "stateMutability": "view",
336 | "type": "function"
337 | },
338 | {
339 | "constant": true,
340 | "inputs": [
341 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
342 | ],
343 | "name": "ownerOf",
344 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
345 | "payable": false,
346 | "stateMutability": "view",
347 | "type": "function"
348 | },
349 | {
350 | "constant": false,
351 | "inputs": [
352 | { "internalType": "uint256", "name": "id", "type": "uint256" },
353 | { "internalType": "address", "name": "owner", "type": "address" }
354 | ],
355 | "name": "reclaim",
356 | "outputs": [],
357 | "payable": false,
358 | "stateMutability": "nonpayable",
359 | "type": "function"
360 | },
361 | {
362 | "constant": false,
363 | "inputs": [
364 | { "internalType": "uint256", "name": "id", "type": "uint256" },
365 | { "internalType": "address", "name": "owner", "type": "address" },
366 | { "internalType": "uint256", "name": "duration", "type": "uint256" }
367 | ],
368 | "name": "register",
369 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
370 | "payable": false,
371 | "stateMutability": "nonpayable",
372 | "type": "function"
373 | },
374 | {
375 | "constant": false,
376 | "inputs": [
377 | { "internalType": "uint256", "name": "id", "type": "uint256" },
378 | { "internalType": "address", "name": "owner", "type": "address" },
379 | { "internalType": "uint256", "name": "duration", "type": "uint256" }
380 | ],
381 | "name": "registerOnly",
382 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
383 | "payable": false,
384 | "stateMutability": "nonpayable",
385 | "type": "function"
386 | },
387 | {
388 | "constant": false,
389 | "inputs": [
390 | { "internalType": "address", "name": "controller", "type": "address" }
391 | ],
392 | "name": "removeController",
393 | "outputs": [],
394 | "payable": false,
395 | "stateMutability": "nonpayable",
396 | "type": "function"
397 | },
398 | {
399 | "constant": false,
400 | "inputs": [
401 | { "internalType": "uint256", "name": "id", "type": "uint256" },
402 | { "internalType": "uint256", "name": "duration", "type": "uint256" }
403 | ],
404 | "name": "renew",
405 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
406 | "payable": false,
407 | "stateMutability": "nonpayable",
408 | "type": "function"
409 | },
410 | {
411 | "constant": false,
412 | "inputs": [],
413 | "name": "renounceOwnership",
414 | "outputs": [],
415 | "payable": false,
416 | "stateMutability": "nonpayable",
417 | "type": "function"
418 | },
419 | {
420 | "constant": false,
421 | "inputs": [
422 | { "internalType": "address", "name": "from", "type": "address" },
423 | { "internalType": "address", "name": "to", "type": "address" },
424 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
425 | ],
426 | "name": "safeTransferFrom",
427 | "outputs": [],
428 | "payable": false,
429 | "stateMutability": "nonpayable",
430 | "type": "function"
431 | },
432 | {
433 | "constant": false,
434 | "inputs": [
435 | { "internalType": "address", "name": "from", "type": "address" },
436 | { "internalType": "address", "name": "to", "type": "address" },
437 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
438 | { "internalType": "bytes", "name": "_data", "type": "bytes" }
439 | ],
440 | "name": "safeTransferFrom",
441 | "outputs": [],
442 | "payable": false,
443 | "stateMutability": "nonpayable",
444 | "type": "function"
445 | },
446 | {
447 | "constant": false,
448 | "inputs": [
449 | { "internalType": "address", "name": "to", "type": "address" },
450 | { "internalType": "bool", "name": "approved", "type": "bool" }
451 | ],
452 | "name": "setApprovalForAll",
453 | "outputs": [],
454 | "payable": false,
455 | "stateMutability": "nonpayable",
456 | "type": "function"
457 | },
458 | {
459 | "constant": false,
460 | "inputs": [
461 | { "internalType": "address", "name": "resolver", "type": "address" }
462 | ],
463 | "name": "setResolver",
464 | "outputs": [],
465 | "payable": false,
466 | "stateMutability": "nonpayable",
467 | "type": "function"
468 | },
469 | {
470 | "constant": true,
471 | "inputs": [
472 | { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
473 | ],
474 | "name": "supportsInterface",
475 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
476 | "payable": false,
477 | "stateMutability": "view",
478 | "type": "function"
479 | },
480 | {
481 | "constant": false,
482 | "inputs": [
483 | { "internalType": "address", "name": "from", "type": "address" },
484 | { "internalType": "address", "name": "to", "type": "address" },
485 | { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
486 | ],
487 | "name": "transferFrom",
488 | "outputs": [],
489 | "payable": false,
490 | "stateMutability": "nonpayable",
491 | "type": "function"
492 | },
493 | {
494 | "constant": false,
495 | "inputs": [
496 | { "internalType": "address", "name": "newOwner", "type": "address" }
497 | ],
498 | "name": "transferOwnership",
499 | "outputs": [],
500 | "payable": false,
501 | "stateMutability": "nonpayable",
502 | "type": "function"
503 | }
504 | ]
505 | }
506 |
--------------------------------------------------------------------------------
/src/frontend/contractsData/EnsName.json:
--------------------------------------------------------------------------------
1 | {
2 | "_format": "hh-sol-artifact-1",
3 | "contractName": "EnsName",
4 | "sourceName": "src/backend/contracts/EnsName.sol",
5 | "abi": [
6 | {
7 | "inputs": [],
8 | "stateMutability": "nonpayable",
9 | "type": "constructor"
10 | },
11 | {
12 | "inputs": [
13 | {
14 | "internalType": "uint256",
15 | "name": "_itemId",
16 | "type": "uint256"
17 | }
18 | ],
19 | "name": "buyENS",
20 | "outputs": [],
21 | "stateMutability": "payable",
22 | "type": "function"
23 | },
24 | {
25 | "inputs": [],
26 | "name": "ensContract",
27 | "outputs": [
28 | {
29 | "internalType": "contract IERC721",
30 | "name": "",
31 | "type": "address"
32 | }
33 | ],
34 | "stateMutability": "view",
35 | "type": "function"
36 | },
37 | {
38 | "inputs": [],
39 | "name": "itemCount",
40 | "outputs": [
41 | {
42 | "internalType": "uint256",
43 | "name": "",
44 | "type": "uint256"
45 | }
46 | ],
47 | "stateMutability": "view",
48 | "type": "function"
49 | },
50 | {
51 | "inputs": [
52 | {
53 | "internalType": "uint256",
54 | "name": "",
55 | "type": "uint256"
56 | }
57 | ],
58 | "name": "items",
59 | "outputs": [
60 | {
61 | "internalType": "uint256",
62 | "name": "itemId",
63 | "type": "uint256"
64 | },
65 | {
66 | "internalType": "string",
67 | "name": "name",
68 | "type": "string"
69 | },
70 | {
71 | "internalType": "uint256",
72 | "name": "tokenId",
73 | "type": "uint256"
74 | },
75 | {
76 | "internalType": "uint256",
77 | "name": "price",
78 | "type": "uint256"
79 | },
80 | {
81 | "internalType": "bool",
82 | "name": "listed",
83 | "type": "bool"
84 | },
85 | {
86 | "internalType": "address payable",
87 | "name": "seller",
88 | "type": "address"
89 | }
90 | ],
91 | "stateMutability": "view",
92 | "type": "function"
93 | },
94 | {
95 | "inputs": [
96 | {
97 | "internalType": "string",
98 | "name": "_name",
99 | "type": "string"
100 | },
101 | {
102 | "internalType": "uint256",
103 | "name": "_tokenId",
104 | "type": "uint256"
105 | },
106 | {
107 | "internalType": "uint256",
108 | "name": "_price",
109 | "type": "uint256"
110 | }
111 | ],
112 | "name": "listENS",
113 | "outputs": [],
114 | "stateMutability": "nonpayable",
115 | "type": "function"
116 | },
117 | {
118 | "stateMutability": "payable",
119 | "type": "receive"
120 | }
121 | ],
122 | "bytecode": "0x60a060405234801561001057600080fd5b507357f1887a8bf19b14fc0df6fd9b2acc9af147ea8573ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505060805161100461007b6000396000818161029901526105da01526110046000f3fe60806040526004361061004e5760003560e01c80634783de501461005a5780636881e763146100835780636bfb0d01146100ae578063bfb231d2146100d9578063f3eee3851461011b57610055565b3661005557005b600080fd5b34801561006657600080fd5b50610081600480360381019061007c9190610968565b610137565b005b34801561008f57600080fd5b50610098610297565b6040516100a59190610a56565b60405180910390f35b3480156100ba57600080fd5b506100c36102bb565b6040516100d09190610a80565b60405180910390f35b3480156100e557600080fd5b5061010060048036038101906100fb9190610a9b565b6102c1565b60405161011296959493929190610b8c565b60405180910390f35b61013560048036038101906101309190610a9b565b6103b2565b005b6000811161017a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017190610c40565b60405180910390fd5b60008081548092919061018c90610c8f565b91905055506040518060c0016040528060005481526020018481526020018381526020018281526020016001151581526020013373ffffffffffffffffffffffffffffffffffffffff168152506001600080548152602001908152602001600020600082015181600001556020820151816001019080519060200190610213929190610735565b50604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60005481565b60016020528060005260406000206000915090508060000154908060010180546102ea90610d07565b80601f016020809104026020016040519081016040528092919081815260200182805461031690610d07565b80156103635780601f1061033857610100808354040283529160200191610363565b820191906000526020600020905b81548152906001019060200180831161034657829003601f168201915b5050505050908060020154908060030154908060040160009054906101000a900460ff16908060040160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905086565b6000600160008381526020019081526020016000206040518060c0016040529081600082015481526020016001820180546103ec90610d07565b80601f016020809104026020016040519081016040528092919081815260200182805461041890610d07565b80156104655780601f1061043a57610100808354040283529160200191610465565b820191906000526020600020905b81548152906001019060200180831161044857829003601f168201915b5050505050815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff161515151581526020016004820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250509050806060015134101561053c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053390610d85565b60405180910390fd5b60008211801561054e57506000548211155b61058d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058490610df1565b60405180910390fd5b6001151581608001511515146105d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105cf90610e83565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166323b872dd8260a001513384604001516040518463ffffffff1660e01b815260040161063d93929190610ee5565b600060405180830381600087803b15801561065757600080fd5b505af115801561066b573d6000803e3d6000fd5b50505050600081608001901515908115158152505060008160a0015173ffffffffffffffffffffffffffffffffffffffff16346040516106aa90610f4d565b60006040518083038185875af1925050503d80600081146106e7576040519150601f19603f3d011682016040523d82523d6000602084013e6106ec565b606091505b5050905080610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072790610fae565b60405180910390fd5b505050565b82805461074190610d07565b90600052602060002090601f01602090048101928261076357600085556107aa565b82601f1061077c57805160ff19168380011785556107aa565b828001600101855582156107aa579182015b828111156107a957825182559160200191906001019061078e565b5b5090506107b791906107bb565b5090565b5b808211156107d45760008160009055506001016107bc565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61083f826107f6565b810181811067ffffffffffffffff8211171561085e5761085d610807565b5b80604052505050565b60006108716107d8565b905061087d8282610836565b919050565b600067ffffffffffffffff82111561089d5761089c610807565b5b6108a6826107f6565b9050602081019050919050565b82818337600083830152505050565b60006108d56108d084610882565b610867565b9050828152602081018484840111156108f1576108f06107f1565b5b6108fc8482856108b3565b509392505050565b600082601f830112610919576109186107ec565b5b81356109298482602086016108c2565b91505092915050565b6000819050919050565b61094581610932565b811461095057600080fd5b50565b6000813590506109628161093c565b92915050565b600080600060608486031215610981576109806107e2565b5b600084013567ffffffffffffffff81111561099f5761099e6107e7565b5b6109ab86828701610904565b93505060206109bc86828701610953565b92505060406109cd86828701610953565b9150509250925092565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610a1c610a17610a12846109d7565b6109f7565b6109d7565b9050919050565b6000610a2e82610a01565b9050919050565b6000610a4082610a23565b9050919050565b610a5081610a35565b82525050565b6000602082019050610a6b6000830184610a47565b92915050565b610a7a81610932565b82525050565b6000602082019050610a956000830184610a71565b92915050565b600060208284031215610ab157610ab06107e2565b5b6000610abf84828501610953565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610b02578082015181840152602081019050610ae7565b83811115610b11576000848401525b50505050565b6000610b2282610ac8565b610b2c8185610ad3565b9350610b3c818560208601610ae4565b610b45816107f6565b840191505092915050565b60008115159050919050565b610b6581610b50565b82525050565b6000610b76826109d7565b9050919050565b610b8681610b6b565b82525050565b600060c082019050610ba16000830189610a71565b8181036020830152610bb38188610b17565b9050610bc26040830187610a71565b610bcf6060830186610a71565b610bdc6080830185610b5c565b610be960a0830184610b7d565b979650505050505050565b7f50726963652073686f756c642062652067726561746572207468616e20300000600082015250565b6000610c2a601e83610ad3565b9150610c3582610bf4565b602082019050919050565b60006020820190508181036000830152610c5981610c1d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610c9a82610932565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610ccd57610ccc610c60565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610d1f57607f821691505b60208210811415610d3357610d32610cd8565b5b50919050565b7f50726963652073656e74206973206e6f7420636f727265637400000000000000600082015250565b6000610d6f601983610ad3565b9150610d7a82610d39565b602082019050919050565b60006020820190508181036000830152610d9e81610d62565b9050919050565b7f57726f6e67206974656d49640000000000000000000000000000000000000000600082015250565b6000610ddb600c83610ad3565b9150610de682610da5565b602082019050919050565b60006020820190508181036000830152610e0a81610dce565b9050919050565b7f54686973206974656d20697320686173206e6f74206265656e206c697374656460008201527f20666f722073616c650000000000000000000000000000000000000000000000602082015250565b6000610e6d602983610ad3565b9150610e7882610e11565b604082019050919050565b60006020820190508181036000830152610e9c81610e60565b9050919050565b6000610eae82610a23565b9050919050565b610ebe81610ea3565b82525050565b6000610ecf826109d7565b9050919050565b610edf81610ec4565b82525050565b6000606082019050610efa6000830186610eb5565b610f076020830185610ed6565b610f146040830184610a71565b949350505050565b600081905092915050565b50565b6000610f37600083610f1c565b9150610f4282610f27565b600082019050919050565b6000610f5882610f2a565b9150819050919050565b7f4661696c656420746f2073656e64204574686572000000000000000000000000600082015250565b6000610f98601483610ad3565b9150610fa382610f62565b602082019050919050565b60006020820190508181036000830152610fc781610f8b565b905091905056fea264697066735822122035ab2381eb274c7683087087db95cf6b903e0179982cf52dae6308eb8a7f16fa64736f6c63430008090033",
123 | "deployedBytecode": "0x60806040526004361061004e5760003560e01c80634783de501461005a5780636881e763146100835780636bfb0d01146100ae578063bfb231d2146100d9578063f3eee3851461011b57610055565b3661005557005b600080fd5b34801561006657600080fd5b50610081600480360381019061007c9190610968565b610137565b005b34801561008f57600080fd5b50610098610297565b6040516100a59190610a56565b60405180910390f35b3480156100ba57600080fd5b506100c36102bb565b6040516100d09190610a80565b60405180910390f35b3480156100e557600080fd5b5061010060048036038101906100fb9190610a9b565b6102c1565b60405161011296959493929190610b8c565b60405180910390f35b61013560048036038101906101309190610a9b565b6103b2565b005b6000811161017a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017190610c40565b60405180910390fd5b60008081548092919061018c90610c8f565b91905055506040518060c0016040528060005481526020018481526020018381526020018281526020016001151581526020013373ffffffffffffffffffffffffffffffffffffffff168152506001600080548152602001908152602001600020600082015181600001556020820151816001019080519060200190610213929190610735565b50604082015181600201556060820151816003015560808201518160040160006101000a81548160ff02191690831515021790555060a08201518160040160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60005481565b60016020528060005260406000206000915090508060000154908060010180546102ea90610d07565b80601f016020809104026020016040519081016040528092919081815260200182805461031690610d07565b80156103635780601f1061033857610100808354040283529160200191610363565b820191906000526020600020905b81548152906001019060200180831161034657829003601f168201915b5050505050908060020154908060030154908060040160009054906101000a900460ff16908060040160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905086565b6000600160008381526020019081526020016000206040518060c0016040529081600082015481526020016001820180546103ec90610d07565b80601f016020809104026020016040519081016040528092919081815260200182805461041890610d07565b80156104655780601f1061043a57610100808354040283529160200191610465565b820191906000526020600020905b81548152906001019060200180831161044857829003601f168201915b5050505050815260200160028201548152602001600382015481526020016004820160009054906101000a900460ff161515151581526020016004820160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250509050806060015134101561053c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053390610d85565b60405180910390fd5b60008211801561054e57506000548211155b61058d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161058490610df1565b60405180910390fd5b6001151581608001511515146105d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105cf90610e83565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166323b872dd8260a001513384604001516040518463ffffffff1660e01b815260040161063d93929190610ee5565b600060405180830381600087803b15801561065757600080fd5b505af115801561066b573d6000803e3d6000fd5b50505050600081608001901515908115158152505060008160a0015173ffffffffffffffffffffffffffffffffffffffff16346040516106aa90610f4d565b60006040518083038185875af1925050503d80600081146106e7576040519150601f19603f3d011682016040523d82523d6000602084013e6106ec565b606091505b5050905080610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072790610fae565b60405180910390fd5b505050565b82805461074190610d07565b90600052602060002090601f01602090048101928261076357600085556107aa565b82601f1061077c57805160ff19168380011785556107aa565b828001600101855582156107aa579182015b828111156107a957825182559160200191906001019061078e565b5b5090506107b791906107bb565b5090565b5b808211156107d45760008160009055506001016107bc565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61083f826107f6565b810181811067ffffffffffffffff8211171561085e5761085d610807565b5b80604052505050565b60006108716107d8565b905061087d8282610836565b919050565b600067ffffffffffffffff82111561089d5761089c610807565b5b6108a6826107f6565b9050602081019050919050565b82818337600083830152505050565b60006108d56108d084610882565b610867565b9050828152602081018484840111156108f1576108f06107f1565b5b6108fc8482856108b3565b509392505050565b600082601f830112610919576109186107ec565b5b81356109298482602086016108c2565b91505092915050565b6000819050919050565b61094581610932565b811461095057600080fd5b50565b6000813590506109628161093c565b92915050565b600080600060608486031215610981576109806107e2565b5b600084013567ffffffffffffffff81111561099f5761099e6107e7565b5b6109ab86828701610904565b93505060206109bc86828701610953565b92505060406109cd86828701610953565b9150509250925092565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610a1c610a17610a12846109d7565b6109f7565b6109d7565b9050919050565b6000610a2e82610a01565b9050919050565b6000610a4082610a23565b9050919050565b610a5081610a35565b82525050565b6000602082019050610a6b6000830184610a47565b92915050565b610a7a81610932565b82525050565b6000602082019050610a956000830184610a71565b92915050565b600060208284031215610ab157610ab06107e2565b5b6000610abf84828501610953565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610b02578082015181840152602081019050610ae7565b83811115610b11576000848401525b50505050565b6000610b2282610ac8565b610b2c8185610ad3565b9350610b3c818560208601610ae4565b610b45816107f6565b840191505092915050565b60008115159050919050565b610b6581610b50565b82525050565b6000610b76826109d7565b9050919050565b610b8681610b6b565b82525050565b600060c082019050610ba16000830189610a71565b8181036020830152610bb38188610b17565b9050610bc26040830187610a71565b610bcf6060830186610a71565b610bdc6080830185610b5c565b610be960a0830184610b7d565b979650505050505050565b7f50726963652073686f756c642062652067726561746572207468616e20300000600082015250565b6000610c2a601e83610ad3565b9150610c3582610bf4565b602082019050919050565b60006020820190508181036000830152610c5981610c1d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610c9a82610932565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610ccd57610ccc610c60565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680610d1f57607f821691505b60208210811415610d3357610d32610cd8565b5b50919050565b7f50726963652073656e74206973206e6f7420636f727265637400000000000000600082015250565b6000610d6f601983610ad3565b9150610d7a82610d39565b602082019050919050565b60006020820190508181036000830152610d9e81610d62565b9050919050565b7f57726f6e67206974656d49640000000000000000000000000000000000000000600082015250565b6000610ddb600c83610ad3565b9150610de682610da5565b602082019050919050565b60006020820190508181036000830152610e0a81610dce565b9050919050565b7f54686973206974656d20697320686173206e6f74206265656e206c697374656460008201527f20666f722073616c650000000000000000000000000000000000000000000000602082015250565b6000610e6d602983610ad3565b9150610e7882610e11565b604082019050919050565b60006020820190508181036000830152610e9c81610e60565b9050919050565b6000610eae82610a23565b9050919050565b610ebe81610ea3565b82525050565b6000610ecf826109d7565b9050919050565b610edf81610ec4565b82525050565b6000606082019050610efa6000830186610eb5565b610f076020830185610ed6565b610f146040830184610a71565b949350505050565b600081905092915050565b50565b6000610f37600083610f1c565b9150610f4282610f27565b600082019050919050565b6000610f5882610f2a565b9150819050919050565b7f4661696c656420746f2073656e64204574686572000000000000000000000000600082015250565b6000610f98601483610ad3565b9150610fa382610f62565b602082019050919050565b60006020820190508181036000830152610fc781610f8b565b905091905056fea264697066735822122035ab2381eb274c7683087087db95cf6b903e0179982cf52dae6308eb8a7f16fa64736f6c63430008090033",
124 | "linkReferences": {},
125 | "deployedLinkReferences": {}
126 | }
--------------------------------------------------------------------------------