项目作者: MiraAnisBahou

项目描述 :
A decentralized house listing service; where houses are listed on OpenSea. (Each house is a token).
高级语言: Solidity
项目地址: git://github.com/MiraAnisBahou/Udacity-BlockchainDeveloperCourse-Capstone.git


Important Notes:

  • In order to run my tests, open a terminal and start ganache-cli, then on another terminal make sure that you are in capstone\blockchain-capstone\eth-contracts, then type truffle test.
  • In case you want to deploy my contract on the Rinkeby TestNetwork, make sure to put your Metamask mnemonic and infura key in the truffle-config.js file.

  • In order to deploy my contracts on the Rinkeby Test Network, I used truffle migrate —reset —network rinkeby.

  • SolnSquareVerifier Contract Address: 0xd66312317870A4861Eb86A7dCe959906ceDB9B95

  • SolnSquareVerifier Contract Transaction Hash: 0x61445a56f25ec37b71c3aa253a874ccaf5091c5f035bb1814d075b9a2d504db5
  • SquareVerifier Contract Address: 0x464681Dc97B393405c849b58cB6814bAaf77CFe3
  • SquareVerifier Contract Transaction Hash: 0x44b292f5a47579239223d0ccb3c1e58b82724887d8f43b189ab7361edc0fd71b

  • SolnSquareVerifier Contract ABI:
    [
    {
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “addrOfVerifier”,
    “type”: “address”
    }
    ],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “constructor”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “owner”,
    “type”: “address”
    },
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “approved”,
    “type”: “address”
    },
    {
    “indexed”: true,
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “Approval”,
    “type”: “event”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “owner”,
    “type”: “address”
    },
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “operator”,
    “type”: “address”
    },
    {
    “indexed”: false,
    “internalType”: “bool”,
    “name”: “approved”,
    “type”: “bool”
    }
    ],
    “name”: “ApprovalForAll”,
    “type”: “event”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: false,
    “internalType”: “address”,
    “name”: “person”,
    “type”: “address”
    }
    ],
    “name”: “Paused”,
    “type”: “event”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “from”,
    “type”: “address”
    },
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “indexed”: true,
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “Transfer”,
    “type”: “event”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: false,
    “internalType”: “address”,
    “name”: “person”,
    “type”: “address”
    }
    ],
    “name”: “Unpaused”,
    “type”: “event”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “oldOwnerAddress”,
    “type”: “address”
    },
    {
    “indexed”: true,
    “internalType”: “address”,
    “name”: “newOwnerAddress”,
    “type”: “address”
    }
    ],
    “name”: “ownershipTransferred”,
    “type”: “event”
    },
    {
    “anonymous”: false,
    “inputs”: [
    {
    “indexed”: false,
    “internalType”: “address”,
    “name”: “from”,
    “type”: “address”
    },
    {
    “indexed”: false,
    “internalType”: “uint256”,
    “name”: “index1”,
    “type”: “uint256”
    }
    ],
    “name”: “solutionAdded”,
    “type”: “event”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “bytes32”,
    “name”: “_myid”,
    “type”: “bytes32”
    },
    {
    “internalType”: “string”,
    “name”: “_result”,
    “type”: “string”
    }
    ],
    “name”: “callback”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “bytes32”,
    “name”: “_myid”,
    “type”: “bytes32”
    },
    {
    “internalType”: “string”,
    “name”: “_result”,
    “type”: “string”
    },
    {
    “internalType”: “bytes”,
    “name”: “_proof”,
    “type”: “bytes”
    }
    ],
    “name”: “
    callback”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “approve”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “owner”,
    “type”: “address”
    }
    ],
    “name”: “balanceOf”,
    “outputs”: [
    {
    “internalType”: “uint256”,
    “name”: “”,
    “type”: “uint256”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “baseTokenURI”,
    “outputs”: [
    {
    “internalType”: “string”,
    “name”: “”,
    “type”: “string”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “getApproved”,
    “outputs”: [
    {
    “internalType”: “address”,
    “name”: “”,
    “type”: “address”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “owner”,
    “type”: “address”
    },
    {
    “internalType”: “address”,
    “name”: “operator”,
    “type”: “address”
    }
    ],
    “name”: “isApprovedForAll”,
    “outputs”: [
    {
    “internalType”: “bool”,
    “name”: “”,
    “type”: “bool”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “mint”,
    “outputs”: [
    {
    “internalType”: “bool”,
    “name”: “”,
    “type”: “bool”
    }
    ],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “name”,
    “outputs”: [
    {
    “internalType”: “string”,
    “name”: “”,
    “type”: “string”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “owner”,
    “outputs”: [
    {
    “internalType”: “address”,
    “name”: “”,
    “type”: “address”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “ownerOf”,
    “outputs”: [
    {
    “internalType”: “address”,
    “name”: “”,
    “type”: “address”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “from”,
    “type”: “address”
    },
    {
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “safeTransferFrom”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “from”,
    “type”: “address”
    },
    {
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    },
    {
    “internalType”: “bytes”,
    “name”: “_data”,
    “type”: “bytes”
    }
    ],
    “name”: “safeTransferFrom”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “internalType”: “bool”,
    “name”: “approved”,
    “type”: “bool”
    }
    ],
    “name”: “setApprovalForAll”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “bool”,
    “name”: “pause”,
    “type”: “bool”
    }
    ],
    “name”: “setPaused”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “squareVerifier”,
    “outputs”: [
    {
    “internalType”: “contract SquareVerifier”,
    “name”: “”,
    “type”: “address”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “bytes4”,
    “name”: “interfaceId”,
    “type”: “bytes4”
    }
    ],
    “name”: “supportsInterface”,
    “outputs”: [
    {
    “internalType”: “bool”,
    “name”: “”,
    “type”: “bool”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “symbol”,
    “outputs”: [
    {
    “internalType”: “string”,
    “name”: “”,
    “type”: “string”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “uint256”,
    “name”: “index”,
    “type”: “uint256”
    }
    ],
    “name”: “tokenByIndex”,
    “outputs”: [
    {
    “internalType”: “uint256”,
    “name”: “”,
    “type”: “uint256”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “owner”,
    “type”: “address”
    },
    {
    “internalType”: “uint256”,
    “name”: “index”,
    “type”: “uint256”
    }
    ],
    “name”: “tokenOfOwnerByIndex”,
    “outputs”: [
    {
    “internalType”: “uint256”,
    “name”: “”,
    “type”: “uint256”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “tokenURI”,
    “outputs”: [
    {
    “internalType”: “string”,
    “name”: “”,
    “type”: “string”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “totalSupply”,
    “outputs”: [
    {
    “internalType”: “uint256”,
    “name”: “”,
    “type”: “uint256”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “from”,
    “type”: “address”
    },
    {
    “internalType”: “address”,
    “name”: “to”,
    “type”: “address”
    },
    {
    “internalType”: “uint256”,
    “name”: “tokenId”,
    “type”: “uint256”
    }
    ],
    “name”: “transferFrom”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “address”,
    “name”: “newOwner”,
    “type”: “address”
    }
    ],
    “name”: “transferOwnership”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “uint256”,
    “name”: “index1”,
    “type”: “uint256”
    },
    {
    “internalType”: “address”,
    “name”: “address1”,
    “type”: “address”
    },
    {
    “internalType”: “uint256[2]”,
    “name”: “A”,
    “type”: “uint256[2]”
    },
    {
    “internalType”: “uint256[2][2]”,
    “name”: “B”,
    “type”: “uint256[2][2]”
    },
    {
    “internalType”: “uint256[2]”,
    “name”: “C”,
    “type”: “uint256[2]”
    },
    {
    “internalType”: “uint256[2]”,
    “name”: “INPUT”,
    “type”: “uint256[2]”
    }
    ],
    “name”: “addSolution”,
    “outputs”: [],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    },
    {
    “constant”: true,
    “inputs”: [],
    “name”: “getSolutionsCount”,
    “outputs”: [
    {
    “internalType”: “uint256”,
    “name”: “”,
    “type”: “uint256”
    }
    ],
    “payable”: false,
    “stateMutability”: “view”,
    “type”: “function”
    },
    {
    “constant”: false,
    “inputs”: [
    {
    “internalType”: “uint256[2]”,
    “name”: “A”,
    “type”: “uint256[2]”
    },
    {
    “internalType”: “uint256[2][2]”,
    “name”: “B”,
    “type”: “uint256[2][2]”
    },
    {
    “internalType”: “uint256[2]”,
    “name”: “C”,
    “type”: “uint256[2]”
    },
    {
    “internalType”: “uint256[2]”,
    “name”: “INPUT”,
    “type”: “uint256[2]”
    },
    {
    “internalType”: “uint256”,
    “name”: “ID”,
    “type”: “uint256”
    }
    ],
    “name”: “tokenMint”,
    “outputs”: [
    {
    “internalType”: “bool”,
    “name”: “”,
    “type”: “bool”
    }
    ],
    “payable”: false,
    “stateMutability”: “nonpayable”,
    “type”: “function”
    }
    ]

Tokens:

  • After deploying the contracts on the Rinkeby TestNetwork, I used MyEtherWallet to mint 10 tokens, to mint tokens, I used the ABI and contract address of SolnSquareVerifier Contract that were listed above, I made sure to connect my MetaMask account with MyEtherWallet and OpenSea. Below are the transaction hashes and the links for the 10 tokens:

  • Original Owner of the tokens: 0xB8DDbc2D6635dE3d2da292A9a4D59cb97D8458f6

Shown below is a screenshot of putting token with ID: 1 on sale and buying it afterwards (same procedure was followed to put the rest of the tokens on sale and to buy them):



mira putting token with the ID of 1 on sale (the 3 screenshots below): (mira is the owner in this stage)


Sell


forSale


forSale(cont'd)



mira2 purchasing token with the ID of 1 (the 3 screenshots below): (mira2 is now the owner)


buy


buy2


buy3

  • Below are the transaction hashes of the purchase of the 5 tokens:
    Token 1 Purchase Transaction Hash: 0x6fa77c53bcda681e45e620e008125b4d46b62c4de3f06e1df786384fec9c7d6b
    Token 3 Purchase Transaction Hash: 0xaed064c785c2702bf8b23cd3c5c47b845d2bbdeab6ee23f7937b7ddc4a9131a1
    Token 5 Purchase Transaction Hash: 0xf69ef969102443ff25c797589093e39792efe6b2b3e02fc3394f42e5da3ace5a
    Token 7 Purchase Transaction Hash: 0x3e684d4bafedcaa32917478621df70323c3725c73631d743ca53256dcce00094
    Token 10 Purchase Transaction Hash: 0xe6adb915a27b75817eeee65ca9456a75fd00bbf57004299916dbf97c10fc712e

Now, as can be seen, mira owns 5 tokens, and mira2 owns the rest (the 5 tokens that she purchased from mira):

  • mira:


    miraa


    miraa(2)

  • mira2:

    mira2


    mira2(2)

Udacity Notes:

Udacity Blockchain Capstone

The capstone will build upon the knowledge you have gained in the course in order to build a decentralized housing product.

Project Resources