diff --git a/README.md b/README.md index 9265b45..dc33141 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,19 @@ -## Foundry +## Dapp Indexer -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** +** The Dapp Indexer is a simple smart contract which stores an IPFS CID from a dapp based on a key name** -Foundry consists of: +The goal is to use this as an alternative for ssl to web3 to verify its the correct content/version/asset. -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. +## The Dapp Indexer has the following features: -## Documentation +- [x] Roll management so that it can be integrated into a Dapp or Roles. +- [x] Low Gas Consumption +- [x] Keep it as simple as posible. + +## ToDo and wanted features: +- [ ] Create an event for metadata information about the CID. +- [ ] Support other type of hashes or structure storage -https://book.getfoundry.sh/ ## Usage @@ -27,12 +29,6 @@ $ forge build $ forge test ``` -### Format - -```shell -$ forge fmt -``` - ### Gas Snapshots ```shell diff --git a/env.example b/env.example index 83529ee..29c4bb3 100644 --- a/env.example +++ b/env.example @@ -1,4 +1,20 @@ -# Foundry default testing private keys +# Deploy +PROVIDER_URL="HTTP://127.0.0.1:8545" +PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + +# Anvil Accounts +ACC0="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +ACC1="0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +ACC2="0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" +ACC3="0x90F79bf6EB2c4f870365E785982E1f101E93b906" +ACC4="0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65" +ACC5="0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" +ACC6="0x976EA74026E726554dB657fA54763abd0C3a0aa9" +ACC7="0x14dC79964da2C08b23698B3D3cc7Ca32193d9955" +ACC8="0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f" +ACC9="0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" + +# Anvil Private Keys PK0="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" PK1="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" PK2="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a" @@ -19,5 +35,4 @@ bafybeiepujtyev5ett75mxd5eazjlqor7loibey5exbmoal6teivnrrkwi" # https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=Private%20key#environment-configuration # GOERLI_RPC_URL= -# PRIVATE_KEY= # ETHERSCAN_API_KEY= diff --git a/foundry.toml b/foundry.toml index 25b918f..b9fe5b5 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,4 +3,11 @@ src = "src" out = "out" libs = ["lib"] +[rpc_endpoints] +sepolia = "${PROVIDER_URL}" +#sepolia = "${SEPOLIA_RPC_URL}" + +#[etherscan] +#sepolia = { key = "${ETHERSCAN_API_KEY}" } + # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/script/DappIndexer.s.sol b/script/DappIndexer.s.sol index 9a68f8a..c96cc4d 100644 --- a/script/DappIndexer.s.sol +++ b/script/DappIndexer.s.sol @@ -7,19 +7,21 @@ import { DappIndexer} from "src/DappIndexer.sol"; contract DappIndexerScript is Script { DappIndexer public dappIdxr; string[] public dappsURI; + address public owner; function setUp() public { - dappIdxr = new DappIndexer(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, - 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266); - console2.log("The Dapps Indexer contract address is: ", address(dappIdxr)); dappsURI = vm.envString("dapps", ' '); + owner = vm.envAddress("ACC0"); } // run is the entry point function run() public { + uint256 deployerPrivateKey = vm.envUint("PK0"); // startBroadcast and stopBraodcast will let us execute transactions anything between them - vm.startBroadcast(); + vm.startBroadcast(deployerPrivateKey); // here we just need to deploy a new contractc + dappIdxr = new DappIndexer(owner, owner); + console2.log("The Dapps Indexer contract address is: ", address(dappIdxr)); bytes32 CID1; bytes32 CID2; @@ -28,6 +30,8 @@ contract DappIndexerScript is Script { // Add Dapp console2.log("-----Adding Dapp-----"); + console2.log("Dapp Name is:"); + console2.logBytes32(bytes32("Dapp01")); console2.log("Bytes32 first:"); console2.logBytes32(CID1); console2.log("Bytes32 second:"); @@ -37,7 +41,7 @@ contract DappIndexerScript is Script { // retrive Dapp console2.log("-----retriving Dapp-----"); - DappIndexer.PackedCID memory dapp1 = dappIdxr.getCID(bytes32("Dapp01")); + DappIndexer.PackedCID memory dapp1 = dappIdxr.getDapp(bytes32("Dapp01")); console2.log("Bytes32 first:"); console2.logBytes32(dapp1.CID1); console2.log("Bytes32 second:"); @@ -65,7 +69,7 @@ contract DappIndexerScript is Script { function stringToBytes32Pair(string memory source) public pure returns (bytes32 part1, bytes32 part2) { bytes memory sourceBytes = bytes(source); - require(sourceBytes.length <= 64, "String must be less than or equal to 64 bytes"); + require(sourceBytes.length == 59, "URI string must equal to 59 bytes"); assembly { // Load the first 32 bytes of the string data diff --git a/src/DappIndexer.sol b/src/DappIndexer.sol index 9888e39..31f07ab 100644 --- a/src/DappIndexer.sol +++ b/src/DappIndexer.sol @@ -31,7 +31,7 @@ contract DappIndexer is AccessControl { delete dapps[dapp_name]; } - function getCID(bytes32 dapp_name) external view returns (PackedCID memory){ + function getDapp(bytes32 dapp_name) external view returns (PackedCID memory){ return dapps[dapp_name]; } } diff --git a/test/DappIndexer.t.sol b/test/DappIndexer.t.sol index 8b604cf..0c067af 100644 --- a/test/DappIndexer.t.sol +++ b/test/DappIndexer.t.sol @@ -20,6 +20,8 @@ contract DappIndexerTest is Test { (CID1, CID2) = stringToBytes32Pair(dappsURI[0]); // Add Dapp + console2.log("Dapp Name is:"); + console2.logBytes32(bytes32("Dapp01")); console2.log("Bytes32 first:"); console2.logBytes32(CID1); console2.log("Bytes32 second:"); @@ -27,7 +29,7 @@ contract DappIndexerTest is Test { console2.log(Bytes32PairToString(CID1, CID2)); dappIdxr.addDapp(bytes32("Dapp01"), DappIndexer.PackedCID(CID1, CID2)); // retrive Dapp - DappIndexer.PackedCID memory dapp1 = dappIdxr.getCID(bytes32("Dapp01")); + DappIndexer.PackedCID memory dapp1 = dappIdxr.getDapp(bytes32("Dapp01")); assertEq(CID1, dapp1.CID1); assertEq(CID2, dapp1.CID2); string memory retrivedDappURI = Bytes32PairToString(dapp1.CID1, dapp1.CID2); diff --git a/test/DappIndexer.t.sol.back b/test/DappIndexer.t.sol.back new file mode 100644 index 0000000..76d25d2 --- /dev/null +++ b/test/DappIndexer.t.sol.back @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.23; + +import { Test, console2 } from "forge-std/Test.sol"; +import { DappIndexer } from "src/DappIndexer.sol"; + +contract DappIndexerTest is Test { + DappIndexer public dappIdxr; + string[] public dappsURI; + + function setUp() public { + dappIdxr = new DappIndexer(address(this), address(this)); + dappsURI = vm.envString("dapps", ' '); + } + + function testAddDapp() public { + bytes32 CID1; + bytes32 CID2; + + //(CID1, CID2) = stringToBytes32Pair(dappsURI[0]); + string memory dapp= "bafkreibc6p3y36yjmeqqnttqfrpb2yttxa6aonoywxwdxl7nqym4jj3jwa"; + (CID1, CID2) = stringToBytes32Pair(dapp); + + // Add Dapp + console2.log("Bytes32 first:"); + console2.logBytes32(CID1); + console2.log("Bytes32 second:"); + console2.logBytes32(CID2); + console2.log(Bytes32PairToString(CID1, CID2)); + dappIdxr.addDapp(bytes32("Dapp01"), DappIndexer.PackedCID(CID1, CID2)); + // retrive Dapp + DappIndexer.PackedCID memory dapp1 = dappIdxr.getCID(bytes32("Dapp01")); + assertEq(CID1, dapp1.CID1); + assertEq(CID2, dapp1.CID2); + assertEq(dappsURI[0], Bytes32PairToString(dapp1.CID1, dapp1.CID2)); + } + + function Bytes32PairToString(bytes32 part1, bytes32 part2) public pure returns (string memory) { + // Concatenate the two bytes32 variables + bytes memory concatenatedBytes = abi.encodePacked(part1, part2); + + // Convert the concatenated bytes to a string + string memory str = string(concatenatedBytes); + + return str; + } + + function stringToBytes32Pair(string memory source) public pure returns (bytes32 part1, bytes32 part2) { + bytes memory sourceBytes = bytes(source); + require(sourceBytes.length == 59, "Source string must be 59 bytes"); + + assembly { + // Load the first 32 bytes of the string data + part1 := mload(add(sourceBytes, 32)) + // Load the next 32 bytes of the string data, then shift right by 3 bytes (24 bits) to remove unwanted bytes + part2 := mload(add(sourceBytes, 64)) + part2 := shl(24, part2) // Shift left to remove the last 5 bytes + part2 := shr(24, part2) // Shift right to align back to the least significant bits + } + } + //function stringToBytes32Pair(string memory source) public pure returns (bytes32 part1, bytes32 part2) { + // bytes memory sourceBytes = bytes(source); + // require(sourceBytes.length == 59, "URI string must equal to 59 bytes"); + + // assembly { + // // Load the first 32 bytes of the string data + // part1 := mload(add(sourceBytes, 32)) + // // Load the second 32 bytes of the string data + // part2 := mload(add(sourceBytes, 58)) + // } + //} +} +// function stringToBytes32Pair(string calldata str) external pure returns(bytes32 part1, bytes32 part2) { +// bytes memory sourceBytes = bytes(str); +// require(sourceBytes.length == 59, "Source string must be 59 bytes"); +// part1 = bytes(str[0:32]); +// part2 = bytes(str[32:59]); +// +// return (part1, part2); +// }