Adding first proof of concept dapp indexer
This commit is contained in:
parent
2cc5bb2cb5
commit
0a2c9680fc
26
README.md
26
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).
|
## The Dapp Indexer has the following features:
|
||||||
- **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.
|
|
||||||
|
|
||||||
## 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
|
## Usage
|
||||||
|
|
||||||
|
@ -27,12 +29,6 @@ $ forge build
|
||||||
$ forge test
|
$ forge test
|
||||||
```
|
```
|
||||||
|
|
||||||
### Format
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ forge fmt
|
|
||||||
```
|
|
||||||
|
|
||||||
### Gas Snapshots
|
### Gas Snapshots
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
19
env.example
19
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"
|
PK0="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
|
||||||
PK1="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
|
PK1="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
|
||||||
PK2="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
|
PK2="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
|
||||||
|
@ -19,5 +35,4 @@ bafybeiepujtyev5ett75mxd5eazjlqor7loibey5exbmoal6teivnrrkwi"
|
||||||
|
|
||||||
# https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=Private%20key#environment-configuration
|
# https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=Private%20key#environment-configuration
|
||||||
# GOERLI_RPC_URL=
|
# GOERLI_RPC_URL=
|
||||||
# PRIVATE_KEY=
|
|
||||||
# ETHERSCAN_API_KEY=
|
# ETHERSCAN_API_KEY=
|
||||||
|
|
|
@ -3,4 +3,11 @@ src = "src"
|
||||||
out = "out"
|
out = "out"
|
||||||
libs = ["lib"]
|
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
|
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
|
||||||
|
|
|
@ -7,19 +7,21 @@ import { DappIndexer} from "src/DappIndexer.sol";
|
||||||
contract DappIndexerScript is Script {
|
contract DappIndexerScript is Script {
|
||||||
DappIndexer public dappIdxr;
|
DappIndexer public dappIdxr;
|
||||||
string[] public dappsURI;
|
string[] public dappsURI;
|
||||||
|
address public owner;
|
||||||
|
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
dappIdxr = new DappIndexer(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266,
|
|
||||||
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
|
|
||||||
console2.log("The Dapps Indexer contract address is: ", address(dappIdxr));
|
|
||||||
dappsURI = vm.envString("dapps", ' ');
|
dappsURI = vm.envString("dapps", ' ');
|
||||||
|
owner = vm.envAddress("ACC0");
|
||||||
}
|
}
|
||||||
|
|
||||||
// run is the entry point
|
// run is the entry point
|
||||||
function run() public {
|
function run() public {
|
||||||
|
uint256 deployerPrivateKey = vm.envUint("PK0");
|
||||||
// startBroadcast and stopBraodcast will let us execute transactions anything between them
|
// 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
|
// 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 CID1;
|
||||||
bytes32 CID2;
|
bytes32 CID2;
|
||||||
|
@ -28,6 +30,8 @@ contract DappIndexerScript is Script {
|
||||||
|
|
||||||
// Add Dapp
|
// Add Dapp
|
||||||
console2.log("-----Adding Dapp-----");
|
console2.log("-----Adding Dapp-----");
|
||||||
|
console2.log("Dapp Name is:");
|
||||||
|
console2.logBytes32(bytes32("Dapp01"));
|
||||||
console2.log("Bytes32 first:");
|
console2.log("Bytes32 first:");
|
||||||
console2.logBytes32(CID1);
|
console2.logBytes32(CID1);
|
||||||
console2.log("Bytes32 second:");
|
console2.log("Bytes32 second:");
|
||||||
|
@ -37,7 +41,7 @@ contract DappIndexerScript is Script {
|
||||||
|
|
||||||
// retrive Dapp
|
// retrive Dapp
|
||||||
console2.log("-----retriving 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.log("Bytes32 first:");
|
||||||
console2.logBytes32(dapp1.CID1);
|
console2.logBytes32(dapp1.CID1);
|
||||||
console2.log("Bytes32 second:");
|
console2.log("Bytes32 second:");
|
||||||
|
@ -65,7 +69,7 @@ contract DappIndexerScript is Script {
|
||||||
|
|
||||||
function stringToBytes32Pair(string memory source) public pure returns (bytes32 part1, bytes32 part2) {
|
function stringToBytes32Pair(string memory source) public pure returns (bytes32 part1, bytes32 part2) {
|
||||||
bytes memory sourceBytes = bytes(source);
|
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 {
|
assembly {
|
||||||
// Load the first 32 bytes of the string data
|
// Load the first 32 bytes of the string data
|
||||||
|
|
|
@ -31,7 +31,7 @@ contract DappIndexer is AccessControl {
|
||||||
delete dapps[dapp_name];
|
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];
|
return dapps[dapp_name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ contract DappIndexerTest is Test {
|
||||||
(CID1, CID2) = stringToBytes32Pair(dappsURI[0]);
|
(CID1, CID2) = stringToBytes32Pair(dappsURI[0]);
|
||||||
|
|
||||||
// Add Dapp
|
// Add Dapp
|
||||||
|
console2.log("Dapp Name is:");
|
||||||
|
console2.logBytes32(bytes32("Dapp01"));
|
||||||
console2.log("Bytes32 first:");
|
console2.log("Bytes32 first:");
|
||||||
console2.logBytes32(CID1);
|
console2.logBytes32(CID1);
|
||||||
console2.log("Bytes32 second:");
|
console2.log("Bytes32 second:");
|
||||||
|
@ -27,7 +29,7 @@ contract DappIndexerTest is Test {
|
||||||
console2.log(Bytes32PairToString(CID1, CID2));
|
console2.log(Bytes32PairToString(CID1, CID2));
|
||||||
dappIdxr.addDapp(bytes32("Dapp01"), DappIndexer.PackedCID(CID1, CID2));
|
dappIdxr.addDapp(bytes32("Dapp01"), DappIndexer.PackedCID(CID1, CID2));
|
||||||
// retrive Dapp
|
// retrive Dapp
|
||||||
DappIndexer.PackedCID memory dapp1 = dappIdxr.getCID(bytes32("Dapp01"));
|
DappIndexer.PackedCID memory dapp1 = dappIdxr.getDapp(bytes32("Dapp01"));
|
||||||
assertEq(CID1, dapp1.CID1);
|
assertEq(CID1, dapp1.CID1);
|
||||||
assertEq(CID2, dapp1.CID2);
|
assertEq(CID2, dapp1.CID2);
|
||||||
string memory retrivedDappURI = Bytes32PairToString(dapp1.CID1, dapp1.CID2);
|
string memory retrivedDappURI = Bytes32PairToString(dapp1.CID1, dapp1.CID2);
|
||||||
|
|
|
@ -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);
|
||||||
|
// }
|
Loading…
Reference in New Issue