From ea87a2bc18ca6533f1be58de429cb8a130bdbc9b Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 16:48:50 +0530 Subject: [PATCH 1/8] Cat page Added --- web/src/app/[cat]/InteractionClient.tsx | 210 ++++++++++++++++++++++++ web/src/app/[cat]/page.tsx | 15 ++ 2 files changed, 225 insertions(+) create mode 100644 web/src/app/[cat]/InteractionClient.tsx create mode 100644 web/src/app/[cat]/page.tsx diff --git a/web/src/app/[cat]/InteractionClient.tsx b/web/src/app/[cat]/InteractionClient.tsx new file mode 100644 index 00000000..032320b3 --- /dev/null +++ b/web/src/app/[cat]/InteractionClient.tsx @@ -0,0 +1,210 @@ +'use client' + +import React, { useEffect, useState } from "react"; +import { Info } from "lucide-react"; +import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; +import { useAccount } from "wagmi"; +import { getPublicClient } from "@wagmi/core"; +import { config } from "@/utils/config"; +import { useSearchParams } from "next/navigation"; +import CONTRIBUTION_ACCOUNTING_TOKEN_ABI from "@/contractsABI/ContributionAccountingTokenABI"; + +interface TokenDetailsState { + tokenName: string; + tokenSymbol: string; + maxSupply: number; + thresholdSupply: number; + maxExpansionRate: number; + transactionHash: string; + timestamp: string; +} + +export default function InteractionClient() { + + const searchParams = useSearchParams(); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + const [tokenAddress, setTokenAddress] = useState<`0x${string}`>("0x0"); + const [chainId, setChainId] = useState(0); + + const [tokenDetails, setTokenDetails] = useState({ + tokenName: "", + tokenSymbol: "", + maxSupply: 0, + thresholdSupply: 0, + maxExpansionRate: 0, + transactionHash: "", + timestamp: "", + }); + + // Get vault address and chainId from URL parameters + useEffect(() => { + const vault = searchParams.get("vault"); + const chain = searchParams.get("chainId"); + + if (vault && chain) { + setTokenAddress(vault as `0x${string}`); + setChainId(Number(chain)); + } + }, [searchParams]); + + const getTokenDetails = async () => { + if (!tokenAddress || !chainId) { + setError("Invalid token address or chain ID"); + return; + } + + try { + setIsLoading(true); + setError(null); + + const publicClient = getPublicClient(config as any, { chainId }); + + if (!publicClient) { + throw new Error(`No public client available for chain ${chainId}`); + } + + // Replace CONTRIBUTION_ACCOUNTING_TOKEN_ABI with your actual token contract ABI + const [name, symbol, maxSupply, threshold, expansionRate] = + (await Promise.all([ + publicClient.readContract({ + address: tokenAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "name", + }), + publicClient.readContract({ + address: tokenAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "symbol", + }), + publicClient.readContract({ + address: tokenAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "maxSupply", + }), + publicClient.readContract({ + address: tokenAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "thresholdSupply", + }), + publicClient.readContract({ + address: tokenAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "maxExpansionRate", + }), + ])) as [string, string, bigint, bigint, bigint]; + + setTokenDetails({ + tokenName: name, + tokenSymbol: symbol, + maxSupply: Number(maxSupply) / 10 ** 18, + thresholdSupply: Number(threshold) / 10 ** 18, + maxExpansionRate: Number(expansionRate) / 100, + transactionHash: tokenAddress, + timestamp: new Date().toISOString(), + }); + } catch (error) { + console.error("Error fetching token details:", error); + setError("Failed to fetch token details"); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + if (tokenAddress && chainId) { + getTokenDetails(); + } + }, [tokenAddress, chainId]); + + if (isLoading) { + return ( +
+
+ Loading token details... +
+
+ ); + } + + if (error) { + return ( +
+
{error}
+
+ ); + } + + return ( +
+ + + +
+ + Token Information +
+
+
+ +
+
+
+
+ Token Name +
+
+ {tokenDetails.tokenName} +
+
+
+
+ Token Symbol +
+
+ {tokenDetails.tokenSymbol} +
+
+
+
+ Max Supply +
+
+ {tokenDetails.maxSupply} +
+
+
+
+
+
+ Threshold Supply +
+
+ {tokenDetails.thresholdSupply} +
+
+
+
+ Max Expansion Rate +
+
+ {tokenDetails.maxExpansionRate}% +
+
+
+
+
+
+ Transaction Hash +
+
+ {tokenDetails.transactionHash} +
+
+
+
+
+ ); +}; + diff --git a/web/src/app/[cat]/page.tsx b/web/src/app/[cat]/page.tsx new file mode 100644 index 00000000..902bf64b --- /dev/null +++ b/web/src/app/[cat]/page.tsx @@ -0,0 +1,15 @@ +import { notFound } from "next/navigation"; +import InteractionClient from "./InteractionClient"; +import { Suspense } from "react"; + +export async function generateStaticParams() { + return [{ cat: "c" }]; +} + +export default function VaultPage() { + return ( + + + + ); +} From 176fc3d88f48fc6d48df171096bc2e93805addc0 Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 16:50:32 +0530 Subject: [PATCH 2/8] CAT FActory modified to add getCATAddress --- contracts/CATFactory.sol | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/CATFactory.sol b/contracts/CATFactory.sol index 73fb5010..6c0ee169 100644 --- a/contracts/CATFactory.sol +++ b/contracts/CATFactory.sol @@ -2,14 +2,14 @@ pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/Ownable.sol"; -import "./ContributionAccountingToken.sol"; // Ensure this import points to your CAT contract file +import "./ContributionAccountingToken.sol"; contract CATFactory is Ownable { uint256 private _nextTokenId; // Mapping from owner address to token addresses - mapping(address => address[]) public administerableTokens; // Now public - mapping(address => address[]) public mintableTokens; // Now public + mapping(address => address[]) public administerableTokens; + mapping(address => address[]) public mintableTokens; // Event emitted when a new CAT is created event CATCreated(address indexed owner, address catAddress, uint256 tokenId); @@ -66,4 +66,8 @@ contract CATFactory is Ownable { function totalCATs() public view returns (uint256) { return _nextTokenId; } + + function getCATAddresses(address _creator) external view returns (address[] memory) { + return administerableTokens[_creator]; + } } From 4b0210ad87f0ff22149bcad74d51cce86c25771e Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 16:51:49 +0530 Subject: [PATCH 3/8] Home page, Cat create form, My CATs page --- web/src/app/create/page.tsx | 190 ++++++++++++++++++++++++---------- web/src/app/my-cats/page.tsx | 195 +++++++++++++++++++++++++---------- web/src/app/page.tsx | 152 ++++++++++++++++++++------- 3 files changed, 389 insertions(+), 148 deletions(-) diff --git a/web/src/app/create/page.tsx b/web/src/app/create/page.tsx index 0fdf9c9a..e4ca4327 100644 --- a/web/src/app/create/page.tsx +++ b/web/src/app/create/page.tsx @@ -5,10 +5,22 @@ import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; -import { useWallet } from "@/hooks/WalletConnectProvider"; -import ConnectWallet from "@/components/ConnectWallet"; +import { ConnectButton } from "@rainbow-me/rainbowkit"; import toast from "react-hot-toast"; import { useRouter } from "next/navigation"; +import { ClowderVaultFactories } from "@/utils/address"; +import { useAccount } from "wagmi"; +import { config } from "@/utils/config"; +import { writeContract } from "@wagmi/core"; +import { CAT_FACTORY_ABI } from "@/contractsABI/CatFactoryABI"; +import { + Card, + CardContent, + CardHeader, + CardTitle, + CardDescription, +} from "../../components/ui/card"; +import { Info } from "lucide-react"; interface DeployContractProps { tokenName: string; @@ -19,11 +31,41 @@ interface DeployContractProps { } const fields = [ - { id: "tokenName", label: "Token Name", type: "text" }, - { id: "tokenSymbol", label: "Token Symbol", type: "text" }, - { id: "maxSupply", label: "Maximum Supply", type: "number" }, - { id: "thresholdSupply", label: "Threshold Supply", type: "number" }, - { id: "maxExpansionRate", label: "Maximum Expansion Rate (%)", type: "number" }, + { + id: "tokenName", + label: "Token Name", + type: "text", + placeholder: "My Token", + description: "The name of your token", + }, + { + id: "tokenSymbol", + label: "Token Symbol", + type: "text", + placeholder: "TKN", + description: "A short identifier for your token (2-4 characters)", + }, + { + id: "maxSupply", + label: "Maximum Supply", + type: "number", + placeholder: "1000000", + description: "The maximum number of tokens that can exist", + }, + { + id: "thresholdSupply", + label: "Threshold Supply", + type: "number", + placeholder: "500000", + description: "The supply threshold that triggers expansion", + }, + { + id: "maxExpansionRate", + label: "Maximum Expansion Rate", + type: "number", + placeholder: "5", + description: "Maximum percentage the supply can expand (1-100)", + }, ]; export default function CreateCAT() { @@ -34,17 +76,16 @@ export default function CreateCAT() { thresholdSupply: "", maxExpansionRate: "", }); + const [isDeploying, setIsDeploying] = useState(false); - const { address, catsContractFactoryInstance } = useWallet(); + const { address } = useAccount(); const router = useRouter(); - // Retrieve transaction history from localStorage const getTransactionHistory = () => { const history = localStorage.getItem("transactionHistory"); return history ? JSON.parse(history) : []; }; - // Save transaction to localStorage const saveTransaction = (txDetails: object) => { const history = getTransactionHistory(); history.push(txDetails); @@ -53,43 +94,52 @@ export default function CreateCAT() { const deployContract = async () => { try { - if (!catsContractFactoryInstance) { + setIsDeploying(true); + const chainId = config.state.chainId; + if (!ClowderVaultFactories[chainId]) { toast.error("Contract factory instance not available"); return; } - const { maxSupply, thresholdSupply, maxExpansionRate, tokenName, tokenSymbol } = formData; + const { + maxSupply, + thresholdSupply, + maxExpansionRate, + tokenName, + tokenSymbol, + } = formData; - // Send the transaction to deploy the contract - const tx = await catsContractFactoryInstance.methods - .createCAT( + const tx = await writeContract(config as any, { + address: ClowderVaultFactories[chainId], + abi: CAT_FACTORY_ABI, + functionName: "createCAT", + args: [ parseInt(maxSupply), parseInt(thresholdSupply), maxExpansionRate.toString(), tokenName, - tokenSymbol - ) - .send({ from: address, gas: 3000000, gasPrice: 10000000000 }); + tokenSymbol, + ], + }); - // Prepare transaction details to store const txDetails = { tokenName, tokenSymbol, maxSupply, thresholdSupply, maxExpansionRate, - transactionHash: tx.transactionHash, + transactionHash: tx, timestamp: new Date().toISOString(), }; - // Save transaction details in localStorage saveTransaction(txDetails); - - toast.success("CAT contract deployed!"); - console.log("Deployment successful:", tx); + toast.success("CAT contract deployed successfully!"); + router.push("/my-cats"); } catch (error) { console.error("Error deploying CAT:", error); - toast.error("Error deploying CAT"); + toast.error("Failed to deploy CAT contract"); + } finally { + setIsDeploying(false); } }; @@ -103,41 +153,71 @@ export default function CreateCAT() { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); await deployContract(); - router.push("/my-cats"); }; return ( -
-
-

Create CAT

- {!address ? ( - - ) : ( -
- {fields.map(({ id, label, type }) => ( -
- - +
+
+ + + + Create CAT + + + Deploy a new Contribution Accounting Token + + + + {!address ? ( +
+

+ Connect your wallet to create a new CAT +

+
- ))} - - - )} + ) : ( +
+ {fields.map( + ({ id, label, type, placeholder, description }) => ( +
+
+ +
+ + + {description} + +
+
+ +
+ ) + )} +
+ +
+
+ )} +
+
diff --git a/web/src/app/my-cats/page.tsx b/web/src/app/my-cats/page.tsx index 196cd5b6..dd5e33c7 100644 --- a/web/src/app/my-cats/page.tsx +++ b/web/src/app/my-cats/page.tsx @@ -2,76 +2,163 @@ import { useCallback, useEffect, useState } from "react"; import Layout from "@/components/Layout"; -import { CatsProps } from "@/types/cats"; import Link from "next/link"; -import { useWallet } from "@/hooks/WalletConnectProvider"; +import { useAccount } from "wagmi"; +import { ClowderVaultFactories } from "@/utils/address"; +import { config } from "@/utils/config"; +import { getPublicClient } from "@wagmi/core"; +import { CAT_FACTORY_ABI } from "@/contractsABI/CatFactoryABI"; import detectEthereumProvider from "@metamask/detect-provider"; import Web3 from "web3"; import CONTRIBUTION_ACCOUNTING_TOKEN_ABI from "@/contractsABI/ContributionAccountingTokenABI"; +interface CatDetails { + chainId: string; + address: `0x${string}`; + tokenName: string; + tokenSymbol: string; +} + export default function MyCATsPage() { - const [ownedCATs, setOwnedCATs] = useState(null); - const { address, catsContractFactoryInstance, isLoading } = useWallet(); - - const getOwnedCATs = useCallback(async () => { - if (!catsContractFactoryInstance) return []; - const cats = await catsContractFactoryInstance.methods - .getOwnedCATs(address) - .call(); - return cats; - }, [catsContractFactoryInstance, address]); - - const getCatDetails = async (catAddress: string) => { - const provider = await detectEthereumProvider(); - if (provider) { - const web3 = new Web3(provider as unknown as Web3["givenProvider"]); - const catsContractInstance = new web3.eth.Contract( - CONTRIBUTION_ACCOUNTING_TOKEN_ABI, - catAddress + const [ownedCATs, setOwnedCATs] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const { address } = useAccount(); + + const fetchCATsFromAllChains = async () => { + try { + setIsLoading(true); + setError(null); + let allCATs: CatDetails[] = []; + + const chainPromises = Object.entries(ClowderVaultFactories).map( + ([chainId, factoryAddress]) => + fetchCATsForChain(chainId, factoryAddress) ); - const tokenName = await catsContractInstance.methods.tokenName().call(); - const tokenSymbol = await catsContractInstance.methods.tokenSymbol().call(); - return { address: catAddress, tokenName, tokenSymbol }; - } else { - throw new Error("Ethereum provider not found"); + + const results = await Promise.all(chainPromises); + allCATs = results.flat().filter((cat): cat is CatDetails => cat !== null); + + setOwnedCATs(allCATs); + } catch (error) { + console.error("Error fetching CATs:", error); + setError("Failed to fetch CATs. Please try again later."); + } finally { + setIsLoading(false); } }; - useEffect(() => { - const fetchOwnedCATs = async () => { - const catAddresses = await getOwnedCATs(); - const catDetailsPromises = catAddresses.map((catAddress: string) => - getCatDetails(catAddress) - ); - const cats = await Promise.all(catDetailsPromises); - setOwnedCATs(cats); - }; + const fetchCATsForChain = async ( + chainId: string, + factoryAddress: string + ): Promise => { + try { + const publicClient = getPublicClient(config as any, { + chainId: parseInt(chainId), + }); + + if (!publicClient || !address) { + console.error(`No public client available for chain ${chainId}`); + return []; + } + + console.log(chainId); + console.log(factoryAddress); + + const catAddresses = (await publicClient.readContract({ + address: factoryAddress as `0x${string}`, + abi: CAT_FACTORY_ABI, + functionName: "getVaultAddresses", + args: [address as `0x${string}`], + })) as `0x${string}`[]; - if (address && !isLoading) { - fetchOwnedCATs(); + console.log(catAddresses) + + const provider = await detectEthereumProvider(); + if (!provider) { + throw new Error("Ethereum provider not found"); + } + + const web3 = new Web3(provider as unknown as Web3["givenProvider"]); + + const catPromises = catAddresses.map(async (catAddress) => { + try { + const [tokenName, tokenSymbol] = await Promise.all([ + publicClient.readContract({ + address: catAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "tokenName", + }) as Promise, + publicClient.readContract({ + address: catAddress, + abi: CONTRIBUTION_ACCOUNTING_TOKEN_ABI, + functionName: "tokenSymbol", + }) as Promise, + ]); + + console.log(tokenName, tokenSymbol) + + return { + chainId, + address: catAddress, + tokenName: tokenName || "", + tokenSymbol: tokenSymbol || "", + }; + } catch (error) { + console.error( + `Error fetching CAT ${catAddress} on chain ${chainId}:`, + error + ); + return null; + } + }); + + const results = await Promise.all(catPromises); + return results.filter((cat): cat is CatDetails => cat !== null); + } catch (error) { + console.error(`Error fetching CATs for chain ${chainId}:`, error); + return []; + } + }; + + useEffect(() => { + if (address) { + fetchCATsFromAllChains(); } - }, [address, isLoading, getOwnedCATs]); + }, [address]); return ( -
-

My CATs

- {ownedCATs && ownedCATs.length > 0 ? ( -
    - {ownedCATs.map((cat) => ( -
  • - +
    +

    My CATs

    + {isLoading ? ( +

    Loading your CATs...

    + ) : error ? ( +

    {error}

    + ) : ownedCATs?.length ? ( +
      + {ownedCATs.map((cat) => ( +
    • - {cat.tokenName || cat.address} ({cat.tokenSymbol}) - -
    • - ))} -
    - ) : ( -

    You don't own any CATs yet.

    - )} + + {cat.tokenName || cat.address} ({cat.tokenSymbol}) + + (Chain: {cat.chainId}) + + +
  • + ))} +
+ ) : ( +

You don't own any CATs yet.

+ )} +
); diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index 5caa71ea..724d385f 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -7,8 +7,7 @@ import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { useRouter } from "next/navigation"; -import { useWallet } from "@/hooks/WalletConnectProvider"; -import ConnectWallet from "@/components/ConnectWallet"; +import { ConnectButton } from "@rainbow-me/rainbowkit"; import Service_1 from "../images/Service_1.png"; import Service_2 from "../images/Service_2.png"; import Service_3 from "../images/Service_3.png"; @@ -16,6 +15,14 @@ import catLight from "../images/Light_cat.png"; import catDark from "../images/Dark_cat.png"; import { useTheme } from "next-themes"; import { faGithub, faDiscord, faTwitter, faTelegram } from "@fortawesome/free-brands-svg-icons"; +import { useAccount } from "wagmi"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; const services = [ { image: Service_1, alt: "Semi-Transferable", description: "Semi-Transferable" }, @@ -23,6 +30,11 @@ const services = [ { image: Service_3, alt: "Simple to Mint", description: "Simple to Mint" }, ]; +const supportedChains = [ + { id: "534351", name: "Scroll Sepolia" }, + { id: "5115", name: "Citrea" }, +]; + const contact_links = [ { href: "https://github.com/StabilityNexus", icon: faGithub }, { href: "https://discord.gg/YzDKeEfWtS", icon: faDiscord }, @@ -35,9 +47,10 @@ export default function Home() { const [isThemeReady, setIsThemeReady] = useState(false); const [catAddress, setCatAddress] = useState(""); const [showPopup, setShowPopup] = useState(false); - const [isWalletConnected, setIsWalletConnected] = useState(false); // Track wallet connection state + const [isWalletConnected, setIsWalletConnected] = useState(''); // Track wallet connection state const router = useRouter(); - const { address } = useWallet(); + const { address } = useAccount(); + const [selectedChain, setSelectedChain] = useState(""); const handleUseCAT = () => { if (catAddress.trim()) { @@ -52,7 +65,7 @@ export default function Home() { }, [resolvedTheme]); useEffect(() => { - setIsWalletConnected(!!address); // Update wallet connection state when address changes + setIsWalletConnected(address as `0x${string}`); // Update wallet connection state when address changes }, [address]); if (!isThemeReady) return null; @@ -65,12 +78,18 @@ export default function Home() {
{/* Heading for Desktop */}

- Welcome to Clowder + Welcome to{" "} + + Clowder +

{/* Heading for Mobile */}

- Welcome to Clowder + Welcome to{" "} + + Clowder +

@@ -92,42 +111,86 @@ export default function Home() { ))}
{!isWalletConnected ? ( - - ) : ( -
- - - - {showPopup && ( -
-
-

Enter CAT Address

- setCatAddress(e.target.value)} - className="mb-4" - style={{ width: "100%" }} - /> -
- - + + ) : ( +
+ + + + {showPopup && ( +
+
+

+ Enter CAT Details +

+ +
+
+ + setCatAddress(e.target.value)} + className="w-full" + /> +
+ +
+ +
-
- )} -
- )} +
+ + +
+
+
+ )} +
+ )} {/* Services Section */}
-

+

Why CATs?

@@ -149,12 +212,15 @@ export default function Home() {
))}
- {/* Contact Us Section */}
-

+

About Us

@@ -165,7 +231,15 @@ export default function Home() { The Stable Order
within the Stability Nexus.

-
+

Contact us through:

From 22a038cc6e19dc3af83f82e34ac8c1479af3080b Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 16:52:55 +0530 Subject: [PATCH 4/8] UI changes --- web/src/app/layout.tsx | 25 +- web/src/components/Avatar.tsx | 7 +- web/src/components/Footer.tsx | 82 +++++- web/src/components/Layout.tsx | 47 +++- web/src/components/Navbar.tsx | 251 +++++++++--------- .../ThemeProvider.tsx} | 6 +- 6 files changed, 247 insertions(+), 171 deletions(-) rename web/src/{components/theme-provider.tsx => hooks/ThemeProvider.tsx} (85%) diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx index 83cc5d60..53971afd 100644 --- a/web/src/app/layout.tsx +++ b/web/src/app/layout.tsx @@ -3,8 +3,9 @@ import localFont from "next/font/local"; import "./globals.css"; import { CatsProvider } from "@/hooks/CatsProvider"; import { WalletConnectProvider } from "@/hooks/WalletConnectProvider"; -import { ThemeProvider } from "@/components/theme-provider"; +import { ThemeProvider } from "@/hooks/ThemeProvider"; import { Toaster } from "react-hot-toast"; +import { WalletProvider } from "@/hooks/WalletProvider"; const geistSans = localFont({ src: "./fonts/GeistVF.woff", @@ -24,14 +25,17 @@ const bebasNueue = localFont({ export const metadata: Metadata = { title: "Clowder - Contribution Accounting Tokens (CATs)", - description: "Clowder helps you track contributions to your projects with Contribution Accounting Tokens (CATs). Secure, semi-transferable, and easy to mint.", - keywords: "Clowder, Contribution Accounting Tokens, CATs, secure, mint tokens, projects, community, Stability Nexus", + description: + "Clowder helps you track contributions to your projects with Contribution Accounting Tokens (CATs). Secure, semi-transferable, and easy to mint.", + keywords: + "Clowder, Contribution Accounting Tokens, CATs, secure, mint tokens, projects, community, Stability Nexus", robots: "index, follow", openGraph: { type: "website", url: "https://clowder.stability.nexus/", title: "Clowder - Contribution Accounting Tokens (CATs)", - description: "Track contributions to your projects with Contribution Accounting Tokens (CATs) on Clowder. Simple to mint, secure against inflation.", + description: + "Track contributions to your projects with Contribution Accounting Tokens (CATs) on Clowder. Simple to mint, secure against inflation.", images: [ { url: "https://stability.nexus/logos/clowder.png", @@ -45,11 +49,16 @@ export const metadata: Metadata = { card: "summary_large_image", site: "@StabilityNexus", title: "Clowder - Contribution Accounting Tokens (CATs)", - description: "Track contributions to your projects using Contribution Accounting Tokens (CATs) on Clowder. Simple to mint, secure against inflation.", + description: + "Track contributions to your projects using Contribution Accounting Tokens (CATs) on Clowder. Simple to mint, secure against inflation.", }, }; -export default function RootLayout({ children }: { children: React.ReactNode; }) { +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { return ( - + {children} - + diff --git a/web/src/components/Avatar.tsx b/web/src/components/Avatar.tsx index b5b4a072..f1680410 100644 --- a/web/src/components/Avatar.tsx +++ b/web/src/components/Avatar.tsx @@ -3,6 +3,7 @@ import React from "react"; import { useWallet } from "@/hooks/WalletConnectProvider"; import Image from "next/image"; +import { useAccount } from "wagmi"; function generateAvatar(walletAddress: string): string { const baseUrl = "https://api.dicebear.com/6.x/identicon/svg"; @@ -10,14 +11,14 @@ function generateAvatar(walletAddress: string): string { } const Avatar = () => { - const { address } = useWallet(); // Replace with your wallet context or connection logic + const { address } = useAccount(); // Replace with your wallet context or connection logic - if (!address) { + if (address === '0x0') { return

Please connect your wallet to see your avatar.

; } // Generate the avatar URL - const avatarUrl = generateAvatar(address); + const avatarUrl = generateAvatar(address as `0x${string}`); return (
diff --git a/web/src/components/Footer.tsx b/web/src/components/Footer.tsx index 0896c86e..95af245d 100644 --- a/web/src/components/Footer.tsx +++ b/web/src/components/Footer.tsx @@ -1,14 +1,68 @@ -import React from "react"; - -const Footer = () => { - return ( -
-

- © - The Stable Order. All rights reserved. -

-
- ); -}; - -export default Footer; +import { + faGithub, + faDiscord, + faTelegram, + faTwitter, +} from "@fortawesome/free-brands-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import Image from "next/image"; +import Link from "next/link"; +import logo from "../images/logo.png"; + +const contact_links = [ + { href: "https://github.com/StabilityNexus", icon: faGithub }, + { href: "https://discord.gg/YzDKeEfWtS", icon: faDiscord }, + { href: "https://t.me/StabilityNexus", icon: faTelegram }, + { href: "https://x.com/StabilityNexus", icon: faTwitter }, +]; + +export default function Footer() { + return ( +
+
+ {/* Logo Section */} +
+ + Stability Nexus Logo + +
+ + {/* Text Section */} +
+ © + The Stable Order. All rights reserved. +
+ + {/* Social Links Section */} +
+ {contact_links.map(({ href, icon }, index) => ( + + + + ))} +
+
+
+ ); +} diff --git a/web/src/components/Layout.tsx b/web/src/components/Layout.tsx index 8297f557..90f94fd1 100644 --- a/web/src/components/Layout.tsx +++ b/web/src/components/Layout.tsx @@ -1,22 +1,43 @@ -import Head from "next/head"; -import React from "react"; +import "@rainbow-me/rainbowkit/styles.css"; +// import "./globals.css"; +import { Metadata } from "next"; +import { Inter } from "next/font/google"; +import { ThemeProvider } from "../hooks/ThemeProvider"; +// import MetamaskProvider from '@/providers' import Navbar from "./Navbar"; -import Footer from "./Footer"; +import Footer from "@/components/Footer"; +import { WalletProvider } from "../hooks/WalletProvider"; -export default function Layout({ children }: { children: React.ReactNode }) { +const inter = Inter({ subsets: ["latin"] }); +export const metadata: Metadata = { + title: "HodlCoin", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { return (
- - Clowder - - - - -
{children}
-
+ + + +
+ {children} +
+
+ +
); } diff --git a/web/src/components/Navbar.tsx b/web/src/components/Navbar.tsx index 86c685ef..e216c884 100644 --- a/web/src/components/Navbar.tsx +++ b/web/src/components/Navbar.tsx @@ -3,150 +3,145 @@ import Link from "next/link"; import React, { useState, useEffect } from "react"; import Image from "next/image"; -import ConnectWallet from "./ConnectWallet"; import logo_light from "../images/logo_light.png"; import logo_dark from "../images/logo_dark.png"; import { useTheme } from "next-themes"; import { ModeToggle } from "../components/darkModeToggle"; import Avatar from "./Avatar"; -import { useWallet } from "@/hooks/WalletConnectProvider"; +// import { useWallet } from "@/hooks/WalletConnectProvider"; import { Menu, X } from "lucide-react"; +import { ConnectButton } from "@rainbow-me/rainbowkit"; +import { useAccount } from "wagmi"; const Navbar = () => { - const { address } = useWallet(); - const { resolvedTheme } = useTheme(); // Use resolvedTheme for accurate theme detection - const [isThemeReady, setIsThemeReady] = useState(false); // Track theme readiness - const [isMenuOpen, setIsMenuOpen] = useState(false); // State to toggle menu + const { address } = useAccount(); + const { resolvedTheme } = useTheme(); + const [isThemeReady, setIsThemeReady] = useState(false); + const [isMenuOpen, setIsMenuOpen] = useState(false); - useEffect(() => { - // Ensure theme is ready before rendering - if (resolvedTheme) { - setIsThemeReady(true); - } - }, [resolvedTheme]); + useEffect(() => { + if (resolvedTheme) { + setIsThemeReady(true); + } + }, [resolvedTheme]); - // Avoid rendering the navbar until the theme is resolved - if (!isThemeReady) return null; + if (!isThemeReady) return null; - return ( -
-
- {/* Logo and Text */} -
- -
- Clowder -

- LOWDER -

-
- -
+ return ( +
+
+ {/* Logo and Text */} +
+ +
+ Clowder +

+ LOWDER +

+
+ +
- {/* Hamburger Menu and ModeToggle for Small Screens */} -
- - -
+ {/* Hamburger Menu and ModeToggle for Small Screens */} +
+ + +
- {/* Mobile Navigation Links */} - {isMenuOpen && ( -
- -
+ {/* Mobile Navigation Links */} + {isMenuOpen && ( +
+ +
+ )} - {/* Desktop Navigation Links */} - + {/* Desktop Navigation Links */} + - {/* Connect Wallet and Light/Dark Toggle for Desktop */} -
- {address ? ( -
- - - - -
- ) : ( - - )} - -
-
-
- ); + {/* */} +
+
+ ); }; export default Navbar; diff --git a/web/src/components/theme-provider.tsx b/web/src/hooks/ThemeProvider.tsx similarity index 85% rename from web/src/components/theme-provider.tsx rename to web/src/hooks/ThemeProvider.tsx index 5f919284..0947bf51 100644 --- a/web/src/components/theme-provider.tsx +++ b/web/src/hooks/ThemeProvider.tsx @@ -17,11 +17,7 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) { } return ( - + {children} ); From d4746e105ff98ec170a1febf38d8675a16ce212e Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 16:58:41 +0530 Subject: [PATCH 5/8] Changes in wallet connection and added citrea testnet --- web/src/components/CitreaTestnet.tsx | 13 +++ web/src/hooks/WalletConnectProvider.tsx | 141 ------------------------ web/src/hooks/WalletProvider.tsx | 31 ++++++ web/src/types/address.ts | 3 - web/src/types/walletContext.ts | 2 +- web/src/utils/address.ts | 6 + web/src/utils/config.tsx | 29 +++++ 7 files changed, 80 insertions(+), 145 deletions(-) create mode 100644 web/src/components/CitreaTestnet.tsx delete mode 100644 web/src/hooks/WalletConnectProvider.tsx create mode 100644 web/src/hooks/WalletProvider.tsx delete mode 100644 web/src/types/address.ts create mode 100644 web/src/utils/address.ts create mode 100644 web/src/utils/config.tsx diff --git a/web/src/components/CitreaTestnet.tsx b/web/src/components/CitreaTestnet.tsx new file mode 100644 index 00000000..2c36ef31 --- /dev/null +++ b/web/src/components/CitreaTestnet.tsx @@ -0,0 +1,13 @@ +import { defineChain } from "viem"; + +export const citreaTestnet = defineChain({ + id: 5115, + name: "Citrea Testnet", + nativeCurrency: { name: "cBTC", symbol: "cBTC", decimals: 18 }, + rpcUrls: { + default: { http: ["https://rpc.testnet.citrea.xyz"] }, + }, + blockExplorers: { + default: { name: "citrea", url: "https://explorer.testnet.citrea.xyz" }, + }, +}); diff --git a/web/src/hooks/WalletConnectProvider.tsx b/web/src/hooks/WalletConnectProvider.tsx deleted file mode 100644 index 2c5848f7..00000000 --- a/web/src/hooks/WalletConnectProvider.tsx +++ /dev/null @@ -1,141 +0,0 @@ -"use client"; - -import { WalletContextProps } from "@/types/walletContext"; -import detectEthereumProvider from "@metamask/detect-provider"; -import React, { createContext, useState, useEffect } from "react"; -import CAT_FACTORY_ABI from "../contractsABI/CatFactoryABI.js"; -import { CATS_FACTORY_ADDRESS } from "../constants.js"; -import Web3 from "web3"; - -const WalletContext = createContext({ - address: "", - isLoading: false, - balance: "", - connect: () => { }, - disconnect: () => { }, - catsContractInstance: null, - catsContractFactoryInstance: null, -}); - -export function WalletConnectProvider({ - children, -}: React.PropsWithChildren) { - const [address, setAddress] = useState(""); - const [isLoading, setIsLoading] = useState(false); - const [balance, setBalance] = useState(""); - const [web3, setWeb3] = useState(null); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const [catsContractInstance] = useState(null); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const [catsContractFactoryInstance, setCatsContractFactoryInstance] = useState(null); - - const initContracts = async () => { - if (!web3) return; - const catsContractFactoryInstance = new web3.eth.Contract( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - CAT_FACTORY_ABI as any, - CATS_FACTORY_ADDRESS - ); - setCatsContractFactoryInstance(catsContractFactoryInstance); - localStorage.setItem("contract", "catsContractFactoryInstance"); - }; - - useEffect(() => { - if (!web3) return; - initContracts(); - }, [isLoading]); - - useEffect(() => { - const init = async () => { - const provider = await detectEthereumProvider(); - if (provider) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const web3Instance = new Web3(provider as any); - setWeb3(web3Instance); - - // Try to load address from localStorage on page load - const savedAddress = localStorage.getItem("walletAddress"); - if (savedAddress) { - setAddress(savedAddress); - const savedBalance = localStorage.getItem("walletBalance"); - if (savedBalance) setBalance(savedBalance); - } - - // Listen for account changes - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (provider as any).on("accountsChanged", async (accounts: string[]) => { - if (accounts.length > 0) { - setAddress(accounts[0]); - const balance = await web3Instance.eth.getBalance(accounts[0]); - const balanceInEther = web3Instance.utils.fromWei(balance, "ether"); - setBalance(balanceInEther); - localStorage.setItem("walletAddress", accounts[0]); - localStorage.setItem("walletBalance", balanceInEther); - } else { - setAddress(""); - setBalance(""); - localStorage.removeItem("walletAddress"); - localStorage.removeItem("walletBalance"); - } - }); - } else { - console.error("Please install MetaMask!"); - } - }; - init(); - }, []); - - const connect = async () => { - if (!web3) return; - setIsLoading(true); - try { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const accounts = await (web3.currentProvider as any).request({ - method: "eth_requestAccounts", - }); - setAddress(accounts[0]); - const balance = await web3.eth.getBalance(accounts[0]); - const balanceInEther = web3.utils.fromWei(balance, "ether"); - setBalance(balanceInEther); - - // Save to localStorage - localStorage.setItem("walletAddress", accounts[0]); - localStorage.setItem("walletBalance", balanceInEther); - } catch (error) { - console.error("Error connecting to MetaMask:", error); - } finally { - setIsLoading(false); - } - }; - - const disconnect = () => { - setAddress(""); - setBalance(""); - localStorage.removeItem("walletAddress"); - localStorage.removeItem("walletBalance"); - }; - - return ( - - {children} - - ); -} - -export function useWallet() { - try { - return React.useContext(WalletContext); - } catch (e) { - throw new Error("useWallet must be used within a WalletConnectProvider"); - } -} diff --git a/web/src/hooks/WalletProvider.tsx b/web/src/hooks/WalletProvider.tsx new file mode 100644 index 00000000..93fe591a --- /dev/null +++ b/web/src/hooks/WalletProvider.tsx @@ -0,0 +1,31 @@ +"use client"; + +import React, { ReactNode } from "react"; +import { config } from "@/utils/config"; +import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { WagmiProvider } from "wagmi"; +import { scrollSepolia } from "wagmi/chains"; + +// Create a client +const queryClient = new QueryClient(); + +export function WalletProvider({ children }: { children: ReactNode }) { + return ( + + + + {children} + + + + ); +} diff --git a/web/src/types/address.ts b/web/src/types/address.ts deleted file mode 100644 index 1283c5a9..00000000 --- a/web/src/types/address.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface AddressProps { - address: string; -} \ No newline at end of file diff --git a/web/src/types/walletContext.ts b/web/src/types/walletContext.ts index ff1377fa..0c782d98 100644 --- a/web/src/types/walletContext.ts +++ b/web/src/types/walletContext.ts @@ -8,4 +8,4 @@ export interface WalletContextProps { catsContractInstance?: any; // eslint-disable-next-line @typescript-eslint/no-explicit-any catsContractFactoryInstance?: any; -} \ No newline at end of file +} diff --git a/web/src/utils/address.ts b/web/src/utils/address.ts new file mode 100644 index 00000000..c35416da --- /dev/null +++ b/web/src/utils/address.ts @@ -0,0 +1,6 @@ +export const ClowderVaultFactories = { + 534351: "0xff1be271440b76d3064556422f4458bed5bbb4b5", + 5115: "0xf899F1b8c710bC4Bc2462cE1B65265760921b2ca", +} as { + [key: number]: `0x${string}`; +}; diff --git a/web/src/utils/config.tsx b/web/src/utils/config.tsx new file mode 100644 index 00000000..c115b5a3 --- /dev/null +++ b/web/src/utils/config.tsx @@ -0,0 +1,29 @@ +import { + arbitrum, + base, + mainnet, + optimism, + polygon, + scrollSepolia, + sepolia, +} from "wagmi/chains"; +import { + getDefaultConfig, + RainbowKitProvider, + darkTheme, + Chain, +} from "@rainbow-me/rainbowkit"; +import * as chains from "wagmi/chains"; +import { citreaTestnet } from "@/components/CitreaTestnet"; + +// const AllChains: readonly [Chain, ...Chain[]] = [ +// ...(Object.values(chains) as Chain[]), +// // citreaTestnet, +// ] as unknown as readonly [Chain, ...Chain[]]; + +export const config = getDefaultConfig({ + appName: "clowder", + projectId: process.env.NEXT_PUBLIC_PROJECT_ID ?? "", + chains: [scrollSepolia, polygon, mainnet, citreaTestnet], + ssr: true, +}); From 251ba35a715b4bbf811ddacddd73caea4110948f Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 17:04:29 +0530 Subject: [PATCH 6/8] UI components added --- web/src/components/ui/card.tsx | 86 +++++++++++++++++ web/src/components/ui/dialog.tsx | 123 ++++++++++++++++++++++++ web/src/components/ui/select.tsx | 156 +++++++++++++++++++++++++++++++ web/src/images/logo.png | Bin 0 -> 42777 bytes 4 files changed, 365 insertions(+) create mode 100644 web/src/components/ui/card.tsx create mode 100644 web/src/components/ui/dialog.tsx create mode 100644 web/src/components/ui/select.tsx create mode 100644 web/src/images/logo.png diff --git a/web/src/components/ui/card.tsx b/web/src/components/ui/card.tsx new file mode 100644 index 00000000..75934036 --- /dev/null +++ b/web/src/components/ui/card.tsx @@ -0,0 +1,86 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +Card.displayName = "Card"; + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardHeader.displayName = "CardHeader"; + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +CardTitle.displayName = "CardTitle"; + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardDescription.displayName = "CardDescription"; + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardContent.displayName = "CardContent"; + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardFooter.displayName = "CardFooter"; + +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardDescription, + CardContent, +}; diff --git a/web/src/components/ui/dialog.tsx b/web/src/components/ui/dialog.tsx new file mode 100644 index 00000000..44dafe17 --- /dev/null +++ b/web/src/components/ui/dialog.tsx @@ -0,0 +1,123 @@ +// components/ui/dialog.tsx +"use client"; + +import * as React from "react"; +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { X } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = "DialogHeader"; + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = "DialogFooter"; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx new file mode 100644 index 00000000..2368407e --- /dev/null +++ b/web/src/components/ui/select.tsx @@ -0,0 +1,156 @@ +import { useState, useRef, useEffect } from "react"; +import { ChevronDown, ChevronUp } from "lucide-react"; +import { cn } from "@/lib/utils"; +import React from "react"; + +interface SelectProps { + value: string; + onValueChange: (value: string) => void; + children: React.ReactNode; +} + +interface SelectTriggerProps { + children: React.ReactNode; + className?: string; +} + +interface SelectContentProps { + children: React.ReactNode; + className?: string; +} + +interface SelectItemProps { + value: string; + children: React.ReactNode; + className?: string; +} + +interface SelectValueProps { + placeholder?: string; +} + +export const Select = ({ value, onValueChange, children }: SelectProps) => { + const [isOpen, setIsOpen] = useState(false); + const selectRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + selectRef.current && + !selectRef.current.contains(event.target as Node) + ) { + setIsOpen(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + // Create context to pass down state and handlers + const contextValue = { + isOpen, + setIsOpen, + value, + onValueChange, + }; + + return ( +
+ + {children} + +
+ ); +}; + +// Create context +const SelectContext = React.createContext<{ + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; + value: string; + onValueChange: (value: string) => void; +} | null>(null); + +// Custom hook to use Select context +const useSelectContext = () => { + const context = React.useContext(SelectContext); + if (!context) { + throw new Error("Select components must be used within a Select component"); + } + return context; +}; + +export const SelectTrigger = ({ children, className }: SelectTriggerProps) => { + const { isOpen, setIsOpen } = useSelectContext(); + + return ( +
setIsOpen(!isOpen)} + > + {children} + {isOpen ? ( + + ) : ( + + )} +
+ ); +}; + +export const SelectContent = ({ children, className }: SelectContentProps) => { + const { isOpen } = useSelectContext(); + + if (!isOpen) return null; + + return ( +
+
{children}
+
+ ); +}; + +export const SelectItem = ({ + value: itemValue, + children, + className, +}: SelectItemProps) => { + const { value, onValueChange, setIsOpen } = useSelectContext(); + const isSelected = value === itemValue; + + const handleClick = () => { + onValueChange(itemValue); + setIsOpen(false); + }; + + return ( +
+ {children} +
+ ); +}; + +export const SelectValue = ({ + placeholder = "Select an option", +}: SelectValueProps) => { + const { value } = useSelectContext(); + return {value || placeholder}; +}; diff --git a/web/src/images/logo.png b/web/src/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..affadf5f2c211b9a28a40aac8bfc1ad61756a502 GIT binary patch literal 42777 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 literal 0 HcmV?d00001 From 68c1742a7e12cbc727c94c3e7bddf97ffe439843 Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 17:50:29 +0530 Subject: [PATCH 7/8] factory abi changes, env variables --- .gitmodules | 3 + web/.env.examples | 1 + web/src/contractsABI/CatFactoryABI.js | 197 -------- web/src/contractsABI/CatFactoryABI.ts | 621 ++++++++++++++++++++++++++ 4 files changed, 625 insertions(+), 197 deletions(-) create mode 100644 .gitmodules create mode 100644 web/.env.examples delete mode 100644 web/src/contractsABI/CatFactoryABI.js create mode 100644 web/src/contractsABI/CatFactoryABI.ts diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..140ea9ee --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/openzeppelin-contracts"] + path = lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/web/.env.examples b/web/.env.examples new file mode 100644 index 00000000..3fa16368 --- /dev/null +++ b/web/.env.examples @@ -0,0 +1 @@ +NEXT_PUBLIC_PROJECT_ID=2c8ea0e714279107a73b8e52561345a6 \ No newline at end of file diff --git a/web/src/contractsABI/CatFactoryABI.js b/web/src/contractsABI/CatFactoryABI.js deleted file mode 100644 index b97f4fca..00000000 --- a/web/src/contractsABI/CatFactoryABI.js +++ /dev/null @@ -1,197 +0,0 @@ -const CAT_FACTORY_ABI = [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "catAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "CATCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxSupply", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "thresholdSupply", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxExpansionRate", - "type": "uint256" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "createCAT", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "getOwnedCATs", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "catAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "grantMinterRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalCATs", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] - -export default CAT_FACTORY_ABI; \ No newline at end of file diff --git a/web/src/contractsABI/CatFactoryABI.ts b/web/src/contractsABI/CatFactoryABI.ts new file mode 100644 index 00000000..65fe850f --- /dev/null +++ b/web/src/contractsABI/CatFactoryABI.ts @@ -0,0 +1,621 @@ +const CAT_FACTORY = { + "abi": [ + { "type": "constructor", "inputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "administerableTokens", + "inputs": [ + { "name": "", "type": "address", "internalType": "address" }, + { "name": "", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "createCAT", + "inputs": [ + { "name": "maxSupply", "type": "uint256", "internalType": "uint256" }, + { + "name": "thresholdSupply", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxExpansionRate", + "type": "uint256", + "internalType": "uint256" + }, + { "name": "name", "type": "string", "internalType": "string" }, + { "name": "symbol", "type": "string", "internalType": "string" } + ], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getVaultAddresses", + "inputs": [ + { "name": "_creator", "type": "address", "internalType": "address" } + ], + "outputs": [ + { "name": "", "type": "address[]", "internalType": "address[]" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantMinterRole", + "inputs": [ + { "name": "catAddress", "type": "address", "internalType": "address" }, + { "name": "minter", "type": "address", "internalType": "address" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "mintableTokens", + "inputs": [ + { "name": "", "type": "address", "internalType": "address" }, + { "name": "", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "totalCATs", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { "name": "newOwner", "type": "address", "internalType": "address" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "CATCreated", + "inputs": [ + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "catAddress", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "tokenId", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "OwnableInvalidOwner", + "inputs": [ + { "name": "owner", "type": "address", "internalType": "address" } + ] + }, + { + "type": "error", + "name": "OwnableUnauthorizedAccount", + "inputs": [ + { "name": "account", "type": "address", "internalType": "address" } + ] + } + ], + "bytecode": { + "object": "0x6080604052348015600e575f5ffd5b503380603357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b603a81603f565b50608e565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6126be8061009b5f395ff3fe608060405234801561000f575f5ffd5b5060043610610090575f3560e01c8063695ee8de11610063578063695ee8de146100fd578063715018a61461011d5780638da5cb5b14610125578063c76fdf6814610135578063f2fde38b14610148575f5ffd5b8063247db5dd1461009457806325c71938146100aa5780633385ab9c146100bf578063387e8311146100ea575b5f5ffd5b6001546040519081526020015b60405180910390f35b6100bd6100b836600461048c565b61015b565b005b6100d26100cd3660046104bd565b6101f9565b6040516001600160a01b0390911681526020016100a1565b6100d26100f83660046104bd565b61022d565b61011061010b3660046104e5565b610246565b6040516100a19190610505565b6100bd6102b9565b5f546001600160a01b03166100d2565b6100d26101433660046105ef565b6102cc565b6100bd6101563660046104e5565b6103a7565b6101636103e9565b604051633dd1eb6160e01b81526001600160a01b038281166004830152831690633dd1eb61906024015f604051808303815f87803b1580156101a3575f5ffd5b505af11580156101b5573d5f5f3e3d5ffd5b505050506001600160a01b039081165f9081526003602090815260408220805460018101825590835291200180546001600160a01b03191692909116919091179055565b6002602052815f5260405f208181548110610212575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6003602052815f5260405f208181548110610212575f80fd5b6001600160a01b0381165f908152600260209081526040918290208054835181840281018401909452808452606093928301828280156102ad57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161028f575b50505050509050919050565b6102c16103e9565b6102ca5f610415565b565b5f5f3387878787876040516102e090610464565b6102ef9695949392919061069d565b604051809103905ff080158015610308573d5f5f3e3d5ffd5b50335f8181526002602090815260408083208054600180820183559185529383902090930180546001600160a01b0319166001600160a01b038716908117909155925481519384529183019190915292935083927f054189e2ad79e5c2d10e8da115126520634a6a9b369a130345025ae1ddeafe92910160405180910390a260018054905f610396836106ee565b909155509098975050505050505050565b6103af6103e9565b6001600160a01b0381166103dd57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6103e681610415565b50565b5f546001600160a01b031633146102ca5760405163118cdaa760e01b81523360048201526024016103d4565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611f768061071383390190565b80356001600160a01b0381168114610487575f5ffd5b919050565b5f5f6040838503121561049d575f5ffd5b6104a683610471565b91506104b460208401610471565b90509250929050565b5f5f604083850312156104ce575f5ffd5b6104d783610471565b946020939093013593505050565b5f602082840312156104f5575f5ffd5b6104fe82610471565b9392505050565b602080825282518282018190525f918401906040840190835b818110156105455783516001600160a01b031683526020938401939092019160010161051e565b509095945050505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610573575f5ffd5b813567ffffffffffffffff81111561058d5761058d610550565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156105bc576105bc610550565b6040528181528382016020018510156105d3575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f5f60a08688031215610603575f5ffd5b853594506020860135935060408601359250606086013567ffffffffffffffff81111561062e575f5ffd5b61063a88828901610564565b925050608086013567ffffffffffffffff811115610656575f5ffd5b61066288828901610564565b9150509295509295909350565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60018060a01b038716815285602082015284604082015283606082015260c060808201525f6106cf60c083018561066f565b82810360a08401526106e1818561066f565b9998505050505050505050565b5f6001820161070b57634e487b7160e01b5f52601160045260245ffd5b506001019056fe610180604052600c805460ff1916600117905573355e559bca86346b82d58be0460d661db481e05e61016052348015610036575f5ffd5b50604051611f76380380611f7683398101604081905261005591610370565b6040805180820190915260018152603160f81b6020820152829081908184600361007f8382610492565b50600461008c8282610492565b5061009c915083905060056101b0565b610120526100ab8160066101b0565b61014052815160208084019190912060e052815190820120610100524660a05261013760e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c0525061014b5f876101e2565b506101767f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6876101e2565b506009859055600a849055600b839055600e6101928382610492565b50600f61019f8282610492565b505042600d55506105a49350505050565b5f6020835110156101cb576101c48361028d565b90506101dc565b816101d68482610492565b5060ff90505b92915050565b5f8281526008602090815260408083206001600160a01b038516845290915281205460ff16610286575f8381526008602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561023e3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016101dc565b505f6101dc565b5f5f829050601f815111156102c0578260405163305a27a960e01b81526004016102b7919061054c565b60405180910390fd5b80516102cb82610581565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126102f6575f5ffd5b81516001600160401b0381111561030f5761030f6102d3565b604051601f8201601f19908116603f011681016001600160401b038111828210171561033d5761033d6102d3565b604052818152838201602001851015610354575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f5f5f5f60c08789031215610385575f5ffd5b86516001600160a01b038116811461039b575f5ffd5b6020880151604089015160608a015160808b0151939950919750955093506001600160401b038111156103cc575f5ffd5b6103d889828a016102e7565b60a089015190935090506001600160401b038111156103f5575f5ffd5b61040189828a016102e7565b9150509295509295509295565b600181811c9082168061042257607f821691505b60208210810361044057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561048d57805f5260205f20601f840160051c8101602085101561046b5750805b601f840160051c820191505b8181101561048a575f8155600101610477565b50505b505050565b81516001600160401b038111156104ab576104ab6102d3565b6104bf816104b9845461040e565b84610446565b6020601f8211600181146104f1575f83156104da5750848201515b5f19600385901b1c1916600184901b17845561048a565b5f84815260208120601f198516915b828110156105205787850151825560209485019460019092019101610500565b508482101561053d57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80516020808301519190811015610440575f1960209190910360031b1b16919050565b60805160a05160c05160e051610100516101205161014051610160516119706106065f395f81816103d8015261077301525f610ffd01525f610fd001525f610eda01525f610eb201525f610e0d01525f610e3701525f610e6101526119705ff3fe608060405234801561000f575f5ffd5b5060043610610229575f3560e01c8063735328021161012a57806395d89b41116100b4578063d547741f11610079578063d547741f14610493578063d5abeb01146104a6578063dd62ed3e146104af578063e488ede8146104e7578063e6ad10e1146104fa575f5ffd5b806395d89b4114610451578063a217fddf146103b1578063a9059cbb14610459578063d505accf1461046c578063d53913931461047f575f5ffd5b806381fb8b06116100fa57806381fb8b06146103d357806383de3e6a1461041257806384b0196e1461041a5780638e80ff5d1461043557806391d148541461043e575f5ffd5b8063735328021461039e57806375b238fc146103b15780637b61c320146103b85780637ecebe00146103c0575f5ffd5b80633644e515116101b657806355233b481161017b57806355233b481461034957806369e2f0fb146103525780636c02a931146103655780636c8597fc1461036d57806370a0823114610376575f5ffd5b80633644e515146102fb57806336568abe146103035780633dd1eb611461031657806340c10f191461032957806348709a931461033c575f5ffd5b806318160ddd116101fc57806318160ddd1461029257806323b872dd146102a4578063248a9ca3146102b75780632f2ff15d146102d9578063313ce567146102ec575f5ffd5b806301ffc9a71461022d57806306fdde03146102555780630914d4da1461026a578063095ea7b31461027f575b5f5ffd5b61024061023b3660046115ee565b610503565b60405190151581526020015b60405180910390f35b61025d610539565b60405161024c919061164a565b61027d61027836600461165c565b6105c9565b005b61024061028d36600461168e565b610655565b6002545b60405190815260200161024c565b6102406102b23660046116b6565b61066c565b6102966102c536600461165c565b5f9081526008602052604090206001015490565b61027d6102e73660046116f0565b61068f565b6040516012815260200161024c565b6102966106b9565b61027d6103113660046116f0565b6106c7565b61027d61032436600461171a565b6106ff565b61027d61033736600461168e565b610724565b600c546102409060ff1681565b610296600b5481565b61027d61036036600461171a565b6108a3565b61025d6108c4565b6102966101f481565b61029661038436600461171a565b6001600160a01b03165f9081526020819052604090205490565b61027d6103ac36600461165c565b610950565b6102965f81565b61025d6109cd565b6102966103ce36600461171a565b6109da565b6103fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161024c565b61027d6109f7565b610422610a0e565b60405161024c9796959493929190611733565b610296600d5481565b61024061044c3660046116f0565b610a50565b61025d610a7a565b61024061046736600461168e565b610a89565b61027d61047a3660046117c9565b610a96565b6102965f51602061191b5f395f51905f5281565b61027d6104a13660046116f0565b610bcc565b61029660095481565b6102966104bd366004611836565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b61027d6104f536600461165c565b610bf0565b610296600a5481565b5f6001600160e01b03198216637965db0b60e01b148061053357506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600380546105489061185e565b80601f01602080910402602001604051908101604052809291908181526020018280546105749061185e565b80156105bf5780601f10610596576101008083540402835291602001916105bf565b820191905f5260205f20905b8154815290600101906020018083116105a257829003601f168201915b5050505050905090565b5f6105d381610c83565b600a54821061064f5760405162461bcd60e51b815260206004820152603f60248201527f4e6577207468726573686f6c6420737570706c79206d757374206265206c657360448201527f73207468616e2063757272656e74207468726573686f6c6420737570706c790060648201526084015b60405180910390fd5b50600a55565b5f33610662818585610c90565b5060019392505050565b5f33610679858285610c9d565b610684858585610d13565b506001949350505050565b5f828152600860205260409020600101546106a981610c83565b6106b38383610d70565b50505050565b5f6106c2610e01565b905090565b6001600160a01b03811633146106f05760405163334bd91960e11b815260040160405180910390fd5b6106fa8282610f2a565b505050565b5f61070981610c83565b6107205f51602061191b5f395f51905f528361068f565b5050565b5f51602061191b5f395f51905f5261073b81610c83565b5f61074560025490565b90505f620186a06107586101f4866118aa565b61076291906118c1565b905061076e8585610f95565b6107987f000000000000000000000000000000000000000000000000000000000000000082610f95565b42600d55600954816107aa86856118e0565b6107b491906118e0565b11156107fb5760405162461bcd60e51b815260206004820152601660248201527545786365656473206d6178696d756d20737570706c7960501b6044820152606401610646565b600a54821061089c575f600d544261081391906118f3565b90505f63bbf81e0082600b548661082a91906118aa565b61083491906118aa565b61083e91906118c1565b90508061084b84886118e0565b11156108995760405162461bcd60e51b815260206004820152601e60248201527f45786365656473206d6178696d756d20657870616e73696f6e207261746500006044820152606401610646565b50505b5050505050565b5f6108ad81610c83565b6107205f51602061191b5f395f51905f5283610bcc565b600e80546108d19061185e565b80601f01602080910402602001604051908101604052809291908181526020018280546108fd9061185e565b80156109485780601f1061091f57610100808354040283529160200191610948565b820191905f5260205f20905b81548152906001019060200180831161092b57829003601f168201915b505050505081565b5f61095a81610c83565b60095482106109c75760405162461bcd60e51b815260206004820152603360248201527f4e6577206d617820737570706c79206d757374206265206c657373207468616e6044820152722063757272656e74206d617820737570706c7960681b6064820152608401610646565b50600955565b600f80546108d19061185e565b6001600160a01b0381165f90815260076020526040812054610533565b5f610a0181610c83565b50600c805460ff19169055565b5f6060805f5f5f6060610a1f610fc9565b610a27610ff6565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f9182526008602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600480546105489061185e565b5f33610662818585610d13565b83421115610aba5760405163313c898160e11b815260048101859052602401610646565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610b058c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f610b5f82611023565b90505f610b6e8287878761104f565b9050896001600160a01b0316816001600160a01b031614610bb5576040516325c0072360e11b81526001600160a01b0380831660048301528b166024820152604401610646565b610bc08a8a8a610c90565b50505050505050505050565b5f82815260086020526040902060010154610be681610c83565b6106b38383610f2a565b5f610bfa81610c83565b600b548210610c7d5760405162461bcd60e51b815260206004820152604360248201527f4e6577206d617820657870616e73696f6e2072617465206d757374206265206c60448201527f657373207468616e2063757272656e74206d617820657870616e73696f6e207260648201526261746560e81b608482015260a401610646565b50600b55565b610c8d813361107b565b50565b6106fa83838360016110b4565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106b35781811015610d0557604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610646565b6106b384848484035f6110b4565b6001600160a01b038316610d3c57604051634b637e8f60e11b81525f6004820152602401610646565b6001600160a01b038216610d655760405163ec442f0560e01b81525f6004820152602401610646565b6106fa838383611186565b5f610d7b8383610a50565b610dfa575f8381526008602090815260408083206001600160a01b03861684529091529020805460ff19166001179055610db23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610533565b505f610533565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015610e5957507f000000000000000000000000000000000000000000000000000000000000000046145b15610e8357507f000000000000000000000000000000000000000000000000000000000000000090565b6106c2604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f610f358383610a50565b15610dfa575f8381526008602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610533565b6001600160a01b038216610fbe5760405163ec442f0560e01b81525f6004820152602401610646565b6107205f8383611186565b60606106c27f0000000000000000000000000000000000000000000000000000000000000000600561123b565b60606106c27f0000000000000000000000000000000000000000000000000000000000000000600661123b565b5f61053361102f610e01565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f5f61105f888888886112e4565b92509250925061106f82826113ac565b50909695505050505050565b6110858282610a50565b6107205760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610646565b6001600160a01b0384166110dd5760405163e602df0560e01b81525f6004820152602401610646565b6001600160a01b03831661110657604051634a1406b160e11b81525f6004820152602401610646565b6001600160a01b038085165f90815260016020908152604080832093871683529290522082905580156106b357826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161117891815260200190565b60405180910390a350505050565b600c5460ff1615611230576001600160a01b03831615806111ae57506001600160a01b038216155b806111ce57506001600160a01b0382165f90815260208190526040812054115b6112305760405162461bcd60e51b815260206004820152602d60248201527f5472616e73666572207265737472696374656420746f206578697374696e672060448201526c746f6b656e20686f6c6465727360981b6064820152608401610646565b6106fa838383611464565b606060ff83146112555761124e8361158a565b9050610533565b8180546112619061185e565b80601f016020809104026020016040519081016040528092919081815260200182805461128d9061185e565b80156112d85780601f106112af576101008083540402835291602001916112d8565b820191905f5260205f20905b8154815290600101906020018083116112bb57829003601f168201915b50505050509050610533565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561131d57505f915060039050826113a2565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561136e573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661139957505f9250600191508290506113a2565b92505f91508190505b9450945094915050565b5f8260038111156113bf576113bf611906565b036113c8575050565b60018260038111156113dc576113dc611906565b036113fa5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561140e5761140e611906565b0361142f5760405163fce698f760e01b815260048101829052602401610646565b600382600381111561144357611443611906565b03610720576040516335e2f38360e21b815260048101829052602401610646565b6001600160a01b03831661148e578060025f82825461148391906118e0565b909155506114fe9050565b6001600160a01b0383165f90815260208190526040902054818110156114e05760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610646565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661151a57600280548290039055611538565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161157d91815260200190565b60405180910390a3505050565b60605f611596836115c7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f81111561053357604051632cd44ac360e21b815260040160405180910390fd5b5f602082840312156115fe575f5ffd5b81356001600160e01b031981168114611615575f5ffd5b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611615602083018461161c565b5f6020828403121561166c575f5ffd5b5035919050565b80356001600160a01b0381168114611689575f5ffd5b919050565b5f5f6040838503121561169f575f5ffd5b6116a883611673565b946020939093013593505050565b5f5f5f606084860312156116c8575f5ffd5b6116d184611673565b92506116df60208501611673565b929592945050506040919091013590565b5f5f60408385031215611701575f5ffd5b8235915061171160208401611673565b90509250929050565b5f6020828403121561172a575f5ffd5b61161582611673565b60ff60f81b8816815260e060208201525f61175160e083018961161c565b8281036040840152611763818961161c565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b818110156117b857835183526020938401939092019160010161179a565b50909b9a5050505050505050505050565b5f5f5f5f5f5f5f60e0888a0312156117df575f5ffd5b6117e888611673565b96506117f660208901611673565b95506040880135945060608801359350608088013560ff81168114611819575f5ffd5b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215611847575f5ffd5b61185083611673565b915061171160208401611673565b600181811c9082168061187257607f821691505b60208210810361189057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761053357610533611896565b5f826118db57634e487b7160e01b5f52601260045260245ffd5b500490565b8082018082111561053357610533611896565b8181038181111561053357610533611896565b634e487b7160e01b5f52602160045260245ffdfe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220b48d06dfe162a9b2ed0088f3f19fe7610c0a09b89b526efd5ce65a8f1329fc8064736f6c634300081c0033a264697066735822122029caf5f3cba9971fbe382374d529fff168aaddfc7939a62f336d7d7d6049f59d64736f6c634300081c0033", + "sourceMap": "157:2369:0:-:0;;;535:36;;;;;;;;;-1:-1:-1;557:10:0;;1269:95:4;;1322:31;;-1:-1:-1;;;1322:31:4;;1350:1;1322:31;;;160:51:26;133:18;;1322:31:4;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;157:2369:0;;2912:187:4;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:4;;;-1:-1:-1;;;;;;3020:17:4;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;14:203:26:-;157:2369:0;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x608060405234801561000f575f5ffd5b5060043610610090575f3560e01c8063695ee8de11610063578063695ee8de146100fd578063715018a61461011d5780638da5cb5b14610125578063c76fdf6814610135578063f2fde38b14610148575f5ffd5b8063247db5dd1461009457806325c71938146100aa5780633385ab9c146100bf578063387e8311146100ea575b5f5ffd5b6001546040519081526020015b60405180910390f35b6100bd6100b836600461048c565b61015b565b005b6100d26100cd3660046104bd565b6101f9565b6040516001600160a01b0390911681526020016100a1565b6100d26100f83660046104bd565b61022d565b61011061010b3660046104e5565b610246565b6040516100a19190610505565b6100bd6102b9565b5f546001600160a01b03166100d2565b6100d26101433660046105ef565b6102cc565b6100bd6101563660046104e5565b6103a7565b6101636103e9565b604051633dd1eb6160e01b81526001600160a01b038281166004830152831690633dd1eb61906024015f604051808303815f87803b1580156101a3575f5ffd5b505af11580156101b5573d5f5f3e3d5ffd5b505050506001600160a01b039081165f9081526003602090815260408220805460018101825590835291200180546001600160a01b03191692909116919091179055565b6002602052815f5260405f208181548110610212575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6003602052815f5260405f208181548110610212575f80fd5b6001600160a01b0381165f908152600260209081526040918290208054835181840281018401909452808452606093928301828280156102ad57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161028f575b50505050509050919050565b6102c16103e9565b6102ca5f610415565b565b5f5f3387878787876040516102e090610464565b6102ef9695949392919061069d565b604051809103905ff080158015610308573d5f5f3e3d5ffd5b50335f8181526002602090815260408083208054600180820183559185529383902090930180546001600160a01b0319166001600160a01b038716908117909155925481519384529183019190915292935083927f054189e2ad79e5c2d10e8da115126520634a6a9b369a130345025ae1ddeafe92910160405180910390a260018054905f610396836106ee565b909155509098975050505050505050565b6103af6103e9565b6001600160a01b0381166103dd57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6103e681610415565b50565b5f546001600160a01b031633146102ca5760405163118cdaa760e01b81523360048201526024016103d4565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611f768061071383390190565b80356001600160a01b0381168114610487575f5ffd5b919050565b5f5f6040838503121561049d575f5ffd5b6104a683610471565b91506104b460208401610471565b90509250929050565b5f5f604083850312156104ce575f5ffd5b6104d783610471565b946020939093013593505050565b5f602082840312156104f5575f5ffd5b6104fe82610471565b9392505050565b602080825282518282018190525f918401906040840190835b818110156105455783516001600160a01b031683526020938401939092019160010161051e565b509095945050505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610573575f5ffd5b813567ffffffffffffffff81111561058d5761058d610550565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156105bc576105bc610550565b6040528181528382016020018510156105d3575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f5f60a08688031215610603575f5ffd5b853594506020860135935060408601359250606086013567ffffffffffffffff81111561062e575f5ffd5b61063a88828901610564565b925050608086013567ffffffffffffffff811115610656575f5ffd5b61066288828901610564565b9150509295509295909350565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60018060a01b038716815285602082015284604082015283606082015260c060808201525f6106cf60c083018561066f565b82810360a08401526106e1818561066f565b9998505050505050505050565b5f6001820161070b57634e487b7160e01b5f52601160045260245ffd5b506001019056fe610180604052600c805460ff1916600117905573355e559bca86346b82d58be0460d661db481e05e61016052348015610036575f5ffd5b50604051611f76380380611f7683398101604081905261005591610370565b6040805180820190915260018152603160f81b6020820152829081908184600361007f8382610492565b50600461008c8282610492565b5061009c915083905060056101b0565b610120526100ab8160066101b0565b61014052815160208084019190912060e052815190820120610100524660a05261013760e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c0525061014b5f876101e2565b506101767f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6876101e2565b506009859055600a849055600b839055600e6101928382610492565b50600f61019f8282610492565b505042600d55506105a49350505050565b5f6020835110156101cb576101c48361028d565b90506101dc565b816101d68482610492565b5060ff90505b92915050565b5f8281526008602090815260408083206001600160a01b038516845290915281205460ff16610286575f8381526008602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561023e3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016101dc565b505f6101dc565b5f5f829050601f815111156102c0578260405163305a27a960e01b81526004016102b7919061054c565b60405180910390fd5b80516102cb82610581565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126102f6575f5ffd5b81516001600160401b0381111561030f5761030f6102d3565b604051601f8201601f19908116603f011681016001600160401b038111828210171561033d5761033d6102d3565b604052818152838201602001851015610354575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f5f5f5f60c08789031215610385575f5ffd5b86516001600160a01b038116811461039b575f5ffd5b6020880151604089015160608a015160808b0151939950919750955093506001600160401b038111156103cc575f5ffd5b6103d889828a016102e7565b60a089015190935090506001600160401b038111156103f5575f5ffd5b61040189828a016102e7565b9150509295509295509295565b600181811c9082168061042257607f821691505b60208210810361044057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561048d57805f5260205f20601f840160051c8101602085101561046b5750805b601f840160051c820191505b8181101561048a575f8155600101610477565b50505b505050565b81516001600160401b038111156104ab576104ab6102d3565b6104bf816104b9845461040e565b84610446565b6020601f8211600181146104f1575f83156104da5750848201515b5f19600385901b1c1916600184901b17845561048a565b5f84815260208120601f198516915b828110156105205787850151825560209485019460019092019101610500565b508482101561053d57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80516020808301519190811015610440575f1960209190910360031b1b16919050565b60805160a05160c05160e051610100516101205161014051610160516119706106065f395f81816103d8015261077301525f610ffd01525f610fd001525f610eda01525f610eb201525f610e0d01525f610e3701525f610e6101526119705ff3fe608060405234801561000f575f5ffd5b5060043610610229575f3560e01c8063735328021161012a57806395d89b41116100b4578063d547741f11610079578063d547741f14610493578063d5abeb01146104a6578063dd62ed3e146104af578063e488ede8146104e7578063e6ad10e1146104fa575f5ffd5b806395d89b4114610451578063a217fddf146103b1578063a9059cbb14610459578063d505accf1461046c578063d53913931461047f575f5ffd5b806381fb8b06116100fa57806381fb8b06146103d357806383de3e6a1461041257806384b0196e1461041a5780638e80ff5d1461043557806391d148541461043e575f5ffd5b8063735328021461039e57806375b238fc146103b15780637b61c320146103b85780637ecebe00146103c0575f5ffd5b80633644e515116101b657806355233b481161017b57806355233b481461034957806369e2f0fb146103525780636c02a931146103655780636c8597fc1461036d57806370a0823114610376575f5ffd5b80633644e515146102fb57806336568abe146103035780633dd1eb611461031657806340c10f191461032957806348709a931461033c575f5ffd5b806318160ddd116101fc57806318160ddd1461029257806323b872dd146102a4578063248a9ca3146102b75780632f2ff15d146102d9578063313ce567146102ec575f5ffd5b806301ffc9a71461022d57806306fdde03146102555780630914d4da1461026a578063095ea7b31461027f575b5f5ffd5b61024061023b3660046115ee565b610503565b60405190151581526020015b60405180910390f35b61025d610539565b60405161024c919061164a565b61027d61027836600461165c565b6105c9565b005b61024061028d36600461168e565b610655565b6002545b60405190815260200161024c565b6102406102b23660046116b6565b61066c565b6102966102c536600461165c565b5f9081526008602052604090206001015490565b61027d6102e73660046116f0565b61068f565b6040516012815260200161024c565b6102966106b9565b61027d6103113660046116f0565b6106c7565b61027d61032436600461171a565b6106ff565b61027d61033736600461168e565b610724565b600c546102409060ff1681565b610296600b5481565b61027d61036036600461171a565b6108a3565b61025d6108c4565b6102966101f481565b61029661038436600461171a565b6001600160a01b03165f9081526020819052604090205490565b61027d6103ac36600461165c565b610950565b6102965f81565b61025d6109cd565b6102966103ce36600461171a565b6109da565b6103fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161024c565b61027d6109f7565b610422610a0e565b60405161024c9796959493929190611733565b610296600d5481565b61024061044c3660046116f0565b610a50565b61025d610a7a565b61024061046736600461168e565b610a89565b61027d61047a3660046117c9565b610a96565b6102965f51602061191b5f395f51905f5281565b61027d6104a13660046116f0565b610bcc565b61029660095481565b6102966104bd366004611836565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b61027d6104f536600461165c565b610bf0565b610296600a5481565b5f6001600160e01b03198216637965db0b60e01b148061053357506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600380546105489061185e565b80601f01602080910402602001604051908101604052809291908181526020018280546105749061185e565b80156105bf5780601f10610596576101008083540402835291602001916105bf565b820191905f5260205f20905b8154815290600101906020018083116105a257829003601f168201915b5050505050905090565b5f6105d381610c83565b600a54821061064f5760405162461bcd60e51b815260206004820152603f60248201527f4e6577207468726573686f6c6420737570706c79206d757374206265206c657360448201527f73207468616e2063757272656e74207468726573686f6c6420737570706c790060648201526084015b60405180910390fd5b50600a55565b5f33610662818585610c90565b5060019392505050565b5f33610679858285610c9d565b610684858585610d13565b506001949350505050565b5f828152600860205260409020600101546106a981610c83565b6106b38383610d70565b50505050565b5f6106c2610e01565b905090565b6001600160a01b03811633146106f05760405163334bd91960e11b815260040160405180910390fd5b6106fa8282610f2a565b505050565b5f61070981610c83565b6107205f51602061191b5f395f51905f528361068f565b5050565b5f51602061191b5f395f51905f5261073b81610c83565b5f61074560025490565b90505f620186a06107586101f4866118aa565b61076291906118c1565b905061076e8585610f95565b6107987f000000000000000000000000000000000000000000000000000000000000000082610f95565b42600d55600954816107aa86856118e0565b6107b491906118e0565b11156107fb5760405162461bcd60e51b815260206004820152601660248201527545786365656473206d6178696d756d20737570706c7960501b6044820152606401610646565b600a54821061089c575f600d544261081391906118f3565b90505f63bbf81e0082600b548661082a91906118aa565b61083491906118aa565b61083e91906118c1565b90508061084b84886118e0565b11156108995760405162461bcd60e51b815260206004820152601e60248201527f45786365656473206d6178696d756d20657870616e73696f6e207261746500006044820152606401610646565b50505b5050505050565b5f6108ad81610c83565b6107205f51602061191b5f395f51905f5283610bcc565b600e80546108d19061185e565b80601f01602080910402602001604051908101604052809291908181526020018280546108fd9061185e565b80156109485780601f1061091f57610100808354040283529160200191610948565b820191905f5260205f20905b81548152906001019060200180831161092b57829003601f168201915b505050505081565b5f61095a81610c83565b60095482106109c75760405162461bcd60e51b815260206004820152603360248201527f4e6577206d617820737570706c79206d757374206265206c657373207468616e6044820152722063757272656e74206d617820737570706c7960681b6064820152608401610646565b50600955565b600f80546108d19061185e565b6001600160a01b0381165f90815260076020526040812054610533565b5f610a0181610c83565b50600c805460ff19169055565b5f6060805f5f5f6060610a1f610fc9565b610a27610ff6565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f9182526008602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6060600480546105489061185e565b5f33610662818585610d13565b83421115610aba5760405163313c898160e11b815260048101859052602401610646565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888610b058c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f610b5f82611023565b90505f610b6e8287878761104f565b9050896001600160a01b0316816001600160a01b031614610bb5576040516325c0072360e11b81526001600160a01b0380831660048301528b166024820152604401610646565b610bc08a8a8a610c90565b50505050505050505050565b5f82815260086020526040902060010154610be681610c83565b6106b38383610f2a565b5f610bfa81610c83565b600b548210610c7d5760405162461bcd60e51b815260206004820152604360248201527f4e6577206d617820657870616e73696f6e2072617465206d757374206265206c60448201527f657373207468616e2063757272656e74206d617820657870616e73696f6e207260648201526261746560e81b608482015260a401610646565b50600b55565b610c8d813361107b565b50565b6106fa83838360016110b4565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106b35781811015610d0557604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610646565b6106b384848484035f6110b4565b6001600160a01b038316610d3c57604051634b637e8f60e11b81525f6004820152602401610646565b6001600160a01b038216610d655760405163ec442f0560e01b81525f6004820152602401610646565b6106fa838383611186565b5f610d7b8383610a50565b610dfa575f8381526008602090815260408083206001600160a01b03861684529091529020805460ff19166001179055610db23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610533565b505f610533565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015610e5957507f000000000000000000000000000000000000000000000000000000000000000046145b15610e8357507f000000000000000000000000000000000000000000000000000000000000000090565b6106c2604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f610f358383610a50565b15610dfa575f8381526008602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610533565b6001600160a01b038216610fbe5760405163ec442f0560e01b81525f6004820152602401610646565b6107205f8383611186565b60606106c27f0000000000000000000000000000000000000000000000000000000000000000600561123b565b60606106c27f0000000000000000000000000000000000000000000000000000000000000000600661123b565b5f61053361102f610e01565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f5f61105f888888886112e4565b92509250925061106f82826113ac565b50909695505050505050565b6110858282610a50565b6107205760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610646565b6001600160a01b0384166110dd5760405163e602df0560e01b81525f6004820152602401610646565b6001600160a01b03831661110657604051634a1406b160e11b81525f6004820152602401610646565b6001600160a01b038085165f90815260016020908152604080832093871683529290522082905580156106b357826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161117891815260200190565b60405180910390a350505050565b600c5460ff1615611230576001600160a01b03831615806111ae57506001600160a01b038216155b806111ce57506001600160a01b0382165f90815260208190526040812054115b6112305760405162461bcd60e51b815260206004820152602d60248201527f5472616e73666572207265737472696374656420746f206578697374696e672060448201526c746f6b656e20686f6c6465727360981b6064820152608401610646565b6106fa838383611464565b606060ff83146112555761124e8361158a565b9050610533565b8180546112619061185e565b80601f016020809104026020016040519081016040528092919081815260200182805461128d9061185e565b80156112d85780601f106112af576101008083540402835291602001916112d8565b820191905f5260205f20905b8154815290600101906020018083116112bb57829003601f168201915b50505050509050610533565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561131d57505f915060039050826113a2565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561136e573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661139957505f9250600191508290506113a2565b92505f91508190505b9450945094915050565b5f8260038111156113bf576113bf611906565b036113c8575050565b60018260038111156113dc576113dc611906565b036113fa5760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561140e5761140e611906565b0361142f5760405163fce698f760e01b815260048101829052602401610646565b600382600381111561144357611443611906565b03610720576040516335e2f38360e21b815260048101829052602401610646565b6001600160a01b03831661148e578060025f82825461148391906118e0565b909155506114fe9050565b6001600160a01b0383165f90815260208190526040902054818110156114e05760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610646565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661151a57600280548290039055611538565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161157d91815260200190565b60405180910390a3505050565b60605f611596836115c7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f81111561053357604051632cd44ac360e21b815260040160405180910390fd5b5f602082840312156115fe575f5ffd5b81356001600160e01b031981168114611615575f5ffd5b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611615602083018461161c565b5f6020828403121561166c575f5ffd5b5035919050565b80356001600160a01b0381168114611689575f5ffd5b919050565b5f5f6040838503121561169f575f5ffd5b6116a883611673565b946020939093013593505050565b5f5f5f606084860312156116c8575f5ffd5b6116d184611673565b92506116df60208501611673565b929592945050506040919091013590565b5f5f60408385031215611701575f5ffd5b8235915061171160208401611673565b90509250929050565b5f6020828403121561172a575f5ffd5b61161582611673565b60ff60f81b8816815260e060208201525f61175160e083018961161c565b8281036040840152611763818961161c565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b818110156117b857835183526020938401939092019160010161179a565b50909b9a5050505050505050505050565b5f5f5f5f5f5f5f60e0888a0312156117df575f5ffd5b6117e888611673565b96506117f660208901611673565b95506040880135945060608801359350608088013560ff81168114611819575f5ffd5b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215611847575f5ffd5b61185083611673565b915061171160208401611673565b600181811c9082168061187257607f821691505b60208210810361189057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761053357610533611896565b5f826118db57634e487b7160e01b5f52601260045260245ffd5b500490565b8082018082111561053357610533611896565b8181038181111561053357610533611896565b634e487b7160e01b5f52602160045260245ffdfe9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220b48d06dfe162a9b2ed0088f3f19fe7610c0a09b89b526efd5ce65a8f1329fc8064736f6c634300081c0033a264697066735822122029caf5f3cba9971fbe382374d529fff168aaddfc7939a62f336d7d7d6049f59d64736f6c634300081c0033", + "sourceMap": "157:2369:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2291:87;2359:12;;2291:87;;160:25:26;;;148:2;133:18;2291:87:0;;;;;;;;1933:241;;;;;;:::i;:::-;;:::i;:::-;;282:57;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1108:32:26;;;1090:51;;1078:2;1063:18;282:57:0;944:203:26;346:51:0;;;;;;:::i;:::-;;:::i;2384:140::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2293:101:4:-;;;:::i;1638:85::-;1684:7;1710:6;-1:-1:-1;;;;;1710:6:4;1638:85;;1023:705:0;;;;;;:::i;:::-;;:::i;2543:215:4:-;;;;;;:::i;:::-;;:::i;1933:241:0:-;1531:13:4;:11;:13::i;:::-;2021:63:0::1;::::0;-1:-1:-1;;;2021:63:0;;-1:-1:-1;;;;;1108:32:26;;;2021:63:0::1;::::0;::::1;1090:51:26::0;2021:55:0;::::1;::::0;::::1;::::0;1063:18:26;;2021:63:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;;;;;2094:22:0;;::::1;;::::0;;;:14:::1;:22;::::0;;;;;;:39;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;-1:-1:-1;;;;;;2094:39:0::1;::::0;;;::::1;::::0;;;::::1;::::0;;1933:241::o;282:57::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;282:57:0;;-1:-1:-1;282:57:0;;-1:-1:-1;282:57:0:o;346:51::-;;;;;;;;;;;;;;;;;;;;2384:140;-1:-1:-1;;;;;2487:30:0;;;;;;:20;:30;;;;;;;;;2480:37;;;;;;;;;;;;;;;;;2452:16;;2480:37;;;2487:30;2480:37;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2480:37:0;;;;;;;;;;;;;;;;;;;;;;;2384:140;;;:::o;2293:101:4:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;1023:705:0:-;1216:7;1235:34;1317:10;1341:9;1364:15;1393:16;1423:4;1441:6;1272:185;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1535:10:0;1468:18;1514:32;;;:20;:32;;;;;;;;:49;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;1514:49:0;-1:-1:-1;;;;;1514:49:0;;;;;;;;1613:12;;1578:48;;4917:51:26;;;4984:18;;;4977:34;;;;1514:49:0;;-1:-1:-1;1514:49:0;;1578:48;;4890:18:26;1578:48:0;;;;;;;1636:12;:14;;;:12;:14;;;:::i;:::-;;;;-1:-1:-1;1711:10:0;;1023:705;-1:-1:-1;;;;;;;;1023:705:0:o;2543:215:4:-;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:4;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:4;;2700:1:::1;2672:31;::::0;::::1;1090:51:26::0;1063:18;;2672:31:4::1;;;;;;;;2623:91;2723:28;2742:8;2723:18;:28::i;:::-;2543:215:::0;:::o;1796:162::-;1684:7;1710:6;-1:-1:-1;;;;;1710:6:4;735:10:12;1855:23:4;1851:101;;1901:40;;-1:-1:-1;;;1901:40:4;;735:10:12;1901:40:4;;;1090:51:26;1063:18;;1901:40:4;944:203:26;2912:187:4;2985:16;3004:6;;-1:-1:-1;;;;;3020:17:4;;;-1:-1:-1;;;;;;3020:17:4;;;;;;3052:40;;3004:6;;;;;;;3052:40;;2985:16;3052:40;2975:124;2912:187;:::o;-1:-1:-1:-;;;;;;;;:::o;196:173:26:-;264:20;;-1:-1:-1;;;;;313:31:26;;303:42;;293:70;;359:1;356;349:12;293:70;196:173;;;:::o;374:260::-;442:6;450;503:2;491:9;482:7;478:23;474:32;471:52;;;519:1;516;509:12;471:52;542:29;561:9;542:29;:::i;:::-;532:39;;590:38;624:2;613:9;609:18;590:38;:::i;:::-;580:48;;374:260;;;;;:::o;639:300::-;707:6;715;768:2;756:9;747:7;743:23;739:32;736:52;;;784:1;781;774:12;736:52;807:29;826:9;807:29;:::i;:::-;797:39;905:2;890:18;;;;877:32;;-1:-1:-1;;;639:300:26:o;1152:186::-;1211:6;1264:2;1252:9;1243:7;1239:23;1235:32;1232:52;;;1280:1;1277;1270:12;1232:52;1303:29;1322:9;1303:29;:::i;:::-;1293:39;1152:186;-1:-1:-1;;;1152:186:26:o;1343:637::-;1533:2;1545:21;;;1615:13;;1518:18;;;1637:22;;;1485:4;;1716:15;;;1690:2;1675:18;;;1485:4;1759:195;1773:6;1770:1;1767:13;1759:195;;;1838:13;;-1:-1:-1;;;;;1834:39:26;1822:52;;1903:2;1929:15;;;;1894:12;;;;1870:1;1788:9;1759:195;;;-1:-1:-1;1971:3:26;;1343:637;-1:-1:-1;;;;;1343:637:26:o;1985:127::-;2046:10;2041:3;2037:20;2034:1;2027:31;2077:4;2074:1;2067:15;2101:4;2098:1;2091:15;2117:726;2160:5;2213:3;2206:4;2198:6;2194:17;2190:27;2180:55;;2231:1;2228;2221:12;2180:55;2271:6;2258:20;2301:18;2293:6;2290:30;2287:56;;;2323:18;;:::i;:::-;2372:2;2366:9;2464:2;2426:17;;-1:-1:-1;;2422:31:26;;;2455:2;2418:40;2414:54;2402:67;;2499:18;2484:34;;2520:22;;;2481:62;2478:88;;;2546:18;;:::i;:::-;2582:2;2575:22;2606;;;2647:19;;;2668:4;2643:30;2640:39;-1:-1:-1;2637:59:26;;;2692:1;2689;2682:12;2637:59;2756:6;2749:4;2741:6;2737:17;2730:4;2722:6;2718:17;2705:58;2811:1;2783:19;;;2804:4;2779:30;2772:41;;;;2787:6;2117:726;-1:-1:-1;;;2117:726:26:o;2848:894::-;2963:6;2971;2979;2987;2995;3048:3;3036:9;3027:7;3023:23;3019:33;3016:53;;;3065:1;3062;3055:12;3016:53;3110:23;;;-1:-1:-1;3230:2:26;3215:18;;3202:32;;-1:-1:-1;3333:2:26;3318:18;;3305:32;;-1:-1:-1;3414:2:26;3399:18;;3386:32;3441:18;3430:30;;3427:50;;;3473:1;3470;3463:12;3427:50;3496;3538:7;3529:6;3518:9;3514:22;3496:50;:::i;:::-;3486:60;;;3599:3;3588:9;3584:19;3571:33;3629:18;3619:8;3616:32;3613:52;;;3661:1;3658;3651:12;3613:52;3684;3728:7;3717:8;3706:9;3702:24;3684:52;:::i;:::-;3674:62;;;2848:894;;;;;;;;:::o;3747:289::-;3789:3;3827:5;3821:12;3854:6;3849:3;3842:19;3910:6;3903:4;3896:5;3892:16;3885:4;3880:3;3876:14;3870:47;3962:1;3955:4;3946:6;3941:3;3937:16;3933:27;3926:38;4025:4;4018:2;4014:7;4009:2;4001:6;3997:15;3993:29;3988:3;3984:39;3980:50;3973:57;;;3747:289;;;;:::o;4041:697::-;4379:1;4375;4370:3;4366:11;4362:19;4354:6;4350:32;4339:9;4332:51;4419:6;4414:2;4403:9;4399:18;4392:34;4462:6;4457:2;4446:9;4442:18;4435:34;4505:6;4500:2;4489:9;4485:18;4478:34;4549:3;4543;4532:9;4528:19;4521:32;4313:4;4576:46;4617:3;4606:9;4602:19;4594:6;4576:46;:::i;:::-;4671:9;4663:6;4659:22;4653:3;4642:9;4638:19;4631:51;4699:33;4725:6;4717;4699:33;:::i;:::-;4691:41;4041:697;-1:-1:-1;;;;;;;;;4041:697:26:o;5022:232::-;5061:3;5082:17;;;5079:140;;5141:10;5136:3;5132:20;5129:1;5122:31;5176:4;5173:1;5166:15;5204:4;5201:1;5194:15;5079:140;-1:-1:-1;5246:1:26;5235:13;;5022:232::o", + "linkReferences": {} + }, + "methodIdentifiers": { + "administerableTokens(address,uint256)": "3385ab9c", + "createCAT(uint256,uint256,uint256,string,string)": "c76fdf68", + "getVaultAddresses(address)": "695ee8de", + "grantMinterRole(address,address)": "25c71938", + "mintableTokens(address,uint256)": "387e8311", + "owner()": "8da5cb5b", + "renounceOwnership()": "715018a6", + "totalCATs()": "247db5dd", + "transferOwnership(address)": "f2fde38b" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"catAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"CATCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"administerableTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"thresholdSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxExpansionRate\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"createCAT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_creator\",\"type\":\"address\"}],\"name\":\"getVaultAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"catAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"grantMinterRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"mintableTokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalCATs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"createCAT(uint256,uint256,uint256,string,string)\":{\"details\":\"Creates a new CAT contract and assigns it to the caller.\",\"params\":{\"maxExpansionRate\":\"The maximum expansion rate for the new CAT.\",\"maxSupply\":\"The maximum supply for the new CAT.\",\"name\":\"The name of the CAT token.\",\"symbol\":\"The symbol of the CAT token.\",\"thresholdSupply\":\"The threshold supply for the new CAT.\"},\"returns\":{\"_0\":\"The address of the newly created CAT contract.\"}},\"grantMinterRole(address,address)\":{\"details\":\"Grants minter role to an address in the CAT contract.\",\"params\":{\"catAddress\":\"The address of the CAT contract.\",\"minter\":\"The address to grant the minter role.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"totalCATs()\":{\"details\":\"Returns the total number of CATs created.\",\"returns\":{\"_0\":\"The total number of CATs.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/CATFactory.sol\":\"CATFactory\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"contracts/CATFactory.sol\":{\"keccak256\":\"0x01c26f10b7428fc9c9f7372ad8988f082853d97ab51687f867c58203deaec88e\",\"license\":\"AEL\",\"urls\":[\"bzz-raw://eefaa94541e645aeab647cff1a59d9b8cc0f66dc8a6f180c6d0b0e8325abda5f\",\"dweb:/ipfs/QmbsURrhXH6XTq83EDoqm1EfnhKYTWBjivu7gHqTaocJp5\"]},\"contracts/ContributionAccountingToken.sol\":{\"keccak256\":\"0xe9a9f746be738f74f5e2958534fdf563bf017304ffa10d2b518a9650638793f6\",\"license\":\"AEL\",\"urls\":[\"bzz-raw://dcec763f8832e8214e89ab67434f92fbca8eda7f5fbfb13eb7516f0bc243cce4\",\"dweb:/ipfs/QmdkGCk94aX64nhzvUNi1Y4yfACK58hjsHL7iBcpyM1uQR\"]},\"lib/openzeppelin-contracts/contracts/access/AccessControl.sol\":{\"keccak256\":\"0xa0e92d42942f4f57c5be50568dac11e9d00c93efcb458026e18d2d9b9b2e7308\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://46326c0bb1e296b67185e81c918e0b40501b8b6386165855df0a3f3c634b6a80\",\"dweb:/ipfs/QmTwyrDYtsxsk6pymJTK94PnEpzsmkpUxFuzEiakDopy4Z\"]},\"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0xc1c2a7f1563b77050dc6d507db9f4ada5d042c1f6a9ddbffdc49c77cdc0a1606\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fd54abb96a6156d9a761f6fdad1d3004bc48d2d4fce47f40a3f91a7ae83fc3a1\",\"dweb:/ipfs/QmUrFSGkTDJ7WaZ6qPVVe3Gn5uN2viPb7x7QQ35UX4DofX\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol\":{\"keccak256\":\"0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c5c0f29195ad64cbe556da8e257dac8f05f78c53f90323c0d2accf8e6922d33a\",\"dweb:/ipfs/QmQ61TED8uaCZwcbh8KkgRSsCav7x7HbcGHwHts3U4DmUP\"]},\"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://399594cd8bb0143bc9e55e0f1d071d0d8c850a394fb7a319d50edd55d9ed822b\",\"dweb:/ipfs/QmbPZzgtT6LEm9CMqWfagQFwETbV1ztpECBB1DtQHrKiRz\"]},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x6ef9389a2c07bc40d8a7ba48914724ab2c108fac391ce12314f01321813e6368\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b7a5cb39b1e6df68f4dd9a5e76e853d745a74ffb3dfd7df4ae4d2ace6992a171\",\"dweb:/ipfs/QmPbzKR19rdM8X3PLQjsmHRepUKhvoZnedSR63XyGtXZib\"]},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol\":{\"keccak256\":\"0xaa7f0646f49ebe2606eeca169f85c56451bbaeeeb06265fa076a03369a25d1d3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ee931d4e832385765967efe6366dcc6d00d6a2d794f9c66ee38283c03882de9c\",\"dweb:/ipfs/QmR6SkuJGYxpQeLz38rBdghqaWqEPfzUsL9kBoXgEXKtbD\"]},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c13d13304ac79a83ab1c30168967d19e2203342ebbd6a9bbce4db7550522dcbf\",\"dweb:/ipfs/QmeN5jKMN2vw5bhacr6tkg78afbTTZUeaacNHqjWt4Ew1r\"]},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"keccak256\":\"0x27dbc90e5136ffe46c04f7596fc2dbcc3acebd8d504da3d93fdb8496e6de04f6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0ea8b92e4245d75a5579c10f22f118f7b4ba07c57341f181f0b2a85ff8663de3\",\"dweb:/ipfs/Qme3Ss5ByjmkxxkMdLpyu7fQ1PCtjNFH1wEFszt2BZePiG\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Nonces.sol\":{\"keccak256\":\"0x0082767004fca261c332e9ad100868327a863a88ef724e844857128845ab350f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://132dce9686a54e025eb5ba5d2e48208f847a1ec3e60a3e527766d7bf53fb7f9e\",\"dweb:/ipfs/QmXn1a2nUZMpu2z6S88UoTfMVtY2YNh86iGrzJDYmMkKeZ\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol\":{\"keccak256\":\"0x7d94fa0af099a2172eb01f9c8a8a443cbe7e0e43654841563e4e09968efdb549\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://65e38fb76b6add407d4557753ae83dd1268e8261195dbe5c19a580d5ba6e4e9a\",\"dweb:/ipfs/QmTkGSJtaQrqjcyWM4AgemeEmKgtDydKPPVRajsUJRQSrK\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"keccak256\":\"0x44f87e91783e88415bde66f1a63f6c7f0076f2d511548820407d5c95643ac56c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://13a51bc2b23827744dcf5bad10c69e72528cf015a6fe48c93632cdb2c0eb1251\",\"dweb:/ipfs/QmZwPA47Yqgje1qtkdEFEja8ntTahMStYzKf5q3JRnaR7d\"]},\"lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8e25e4bdb7ae1f21d23bfee996e22736fc0ab44cfabedac82a757b1edc5623b9\",\"dweb:/ipfs/QmQdWQvB6JCP9ZMbzi8EvQ1PTETqkcTWrbcVurS7DKpa5n\"]},\"lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"keccak256\":\"0x10eb97d047f8d84fe263a02bb4a656ac6674f6679d74532cc37546289e073a9d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3e41287d40b0c46982f1083d40d32de2761f009c5c51627fe79a7feb0ab1cf5c\",\"dweb:/ipfs/Qme7dbh6HX3ZvUJdbQAcVqXkmyXyfcLiUZRhhon3cU6K8p\"]},\"lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol\":{\"keccak256\":\"0x4515543bc4c78561f6bea83ecfdfc3dead55bd59858287d682045b11de1ae575\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://60601f91440125727244fffd2ba84da7caafecaae0fd887c7ccfec678e02b61e\",\"dweb:/ipfs/QmZnKPBtVDiQS9Dp8gZ4sa3ZeTrWVfqF7yuUd6Y8hwm1Rs\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8084aa71a4cc7d2980972412a88fe4f114869faea3fefa5436431644eb5c0287\",\"dweb:/ipfs/Qmbqfs5dRdPvHVKY8kTaeyc65NdqXRQwRK7h9s5UJEhD1p\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xa00be322d7db5786750ce0ac7e2f5b633ac30a5ed5fa1ced1e74acfc19acecea\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c84e822f87cbdc4082533b626667b6928715bb2b1e8e7eb96954cebb9e38c8d\",\"dweb:/ipfs/QmZmy9dgxLTerBAQDuuHqbL6EpgRxddqgv5KmwpXYVbKz1\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://db5fbb3dddd8b7047465b62575d96231ba8a2774d37fb4737fbf23340fabbb03\",\"dweb:/ipfs/QmVUSvooZKEdEdap619tcJjTLcAuH6QBdZqAzWwnAXZAWJ\"]}},\"version\":1}", + "metadata": { + "compiler": { "version": "0.8.28+commit.7893614a" }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "type": "error", + "name": "OwnableInvalidOwner" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" } + ], + "type": "error", + "name": "OwnableUnauthorizedAccount" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "catAddress", + "type": "address", + "indexed": false + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "CATCreated", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "previousOwner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address", + "indexed": true + } + ], + "type": "event", + "name": "OwnershipTransferred", + "anonymous": false + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function", + "name": "administerableTokens", + "outputs": [ + { "internalType": "address", "name": "", "type": "address" } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "thresholdSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxExpansionRate", + "type": "uint256" + }, + { "internalType": "string", "name": "name", "type": "string" }, + { "internalType": "string", "name": "symbol", "type": "string" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "createCAT", + "outputs": [ + { "internalType": "address", "name": "", "type": "address" } + ] + }, + { + "inputs": [ + { "internalType": "address", "name": "_creator", "type": "address" } + ], + "stateMutability": "view", + "type": "function", + "name": "getVaultAddresses", + "outputs": [ + { "internalType": "address[]", "name": "", "type": "address[]" } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "catAddress", + "type": "address" + }, + { "internalType": "address", "name": "minter", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "grantMinterRole" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function", + "name": "mintableTokens", + "outputs": [ + { "internalType": "address", "name": "", "type": "address" } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "owner", + "outputs": [ + { "internalType": "address", "name": "", "type": "address" } + ] + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "function", + "name": "renounceOwnership" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "totalCATs", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" } + ] + }, + { + "inputs": [ + { "internalType": "address", "name": "newOwner", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferOwnership" + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "createCAT(uint256,uint256,uint256,string,string)": { + "details": "Creates a new CAT contract and assigns it to the caller.", + "params": { + "maxExpansionRate": "The maximum expansion rate for the new CAT.", + "maxSupply": "The maximum supply for the new CAT.", + "name": "The name of the CAT token.", + "symbol": "The symbol of the CAT token.", + "thresholdSupply": "The threshold supply for the new CAT." + }, + "returns": { + "_0": "The address of the newly created CAT contract." + } + }, + "grantMinterRole(address,address)": { + "details": "Grants minter role to an address in the CAT contract.", + "params": { + "catAddress": "The address of the CAT contract.", + "minter": "The address to grant the minter role." + } + }, + "owner()": { "details": "Returns the address of the current owner." }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "totalCATs()": { + "details": "Returns the total number of CATs created.", + "returns": { "_0": "The total number of CATs." } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { "kind": "user", "methods": {}, "version": 1 } + }, + "settings": { + "remappings": [ + "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/", + "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/" + ], + "optimizer": { "enabled": true, "runs": 200 }, + "metadata": { "bytecodeHash": "ipfs" }, + "compilationTarget": { "contracts/CATFactory.sol": "CATFactory" }, + "evmVersion": "cancun", + "libraries": {} + }, + "sources": { + "contracts/CATFactory.sol": { + "keccak256": "0x01c26f10b7428fc9c9f7372ad8988f082853d97ab51687f867c58203deaec88e", + "urls": [ + "bzz-raw://eefaa94541e645aeab647cff1a59d9b8cc0f66dc8a6f180c6d0b0e8325abda5f", + "dweb:/ipfs/QmbsURrhXH6XTq83EDoqm1EfnhKYTWBjivu7gHqTaocJp5" + ], + "license": "AEL" + }, + "contracts/ContributionAccountingToken.sol": { + "keccak256": "0xe9a9f746be738f74f5e2958534fdf563bf017304ffa10d2b518a9650638793f6", + "urls": [ + "bzz-raw://dcec763f8832e8214e89ab67434f92fbca8eda7f5fbfb13eb7516f0bc243cce4", + "dweb:/ipfs/QmdkGCk94aX64nhzvUNi1Y4yfACK58hjsHL7iBcpyM1uQR" + ], + "license": "AEL" + }, + "lib/openzeppelin-contracts/contracts/access/AccessControl.sol": { + "keccak256": "0xa0e92d42942f4f57c5be50568dac11e9d00c93efcb458026e18d2d9b9b2e7308", + "urls": [ + "bzz-raw://46326c0bb1e296b67185e81c918e0b40501b8b6386165855df0a3f3c634b6a80", + "dweb:/ipfs/QmTwyrDYtsxsk6pymJTK94PnEpzsmkpUxFuzEiakDopy4Z" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/access/IAccessControl.sol": { + "keccak256": "0xc1c2a7f1563b77050dc6d507db9f4ada5d042c1f6a9ddbffdc49c77cdc0a1606", + "urls": [ + "bzz-raw://fd54abb96a6156d9a761f6fdad1d3004bc48d2d4fce47f40a3f91a7ae83fc3a1", + "dweb:/ipfs/QmUrFSGkTDJ7WaZ6qPVVe3Gn5uN2viPb7x7QQ35UX4DofX" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/access/Ownable.sol": { + "keccak256": "0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb", + "urls": [ + "bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6", + "dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol": { + "keccak256": "0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92", + "urls": [ + "bzz-raw://c5c0f29195ad64cbe556da8e257dac8f05f78c53f90323c0d2accf8e6922d33a", + "dweb:/ipfs/QmQ61TED8uaCZwcbh8KkgRSsCav7x7HbcGHwHts3U4DmUP" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol": { + "keccak256": "0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b", + "urls": [ + "bzz-raw://399594cd8bb0143bc9e55e0f1d071d0d8c850a394fb7a319d50edd55d9ed822b", + "dweb:/ipfs/QmbPZzgtT6LEm9CMqWfagQFwETbV1ztpECBB1DtQHrKiRz" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": { + "keccak256": "0x6ef9389a2c07bc40d8a7ba48914724ab2c108fac391ce12314f01321813e6368", + "urls": [ + "bzz-raw://b7a5cb39b1e6df68f4dd9a5e76e853d745a74ffb3dfd7df4ae4d2ace6992a171", + "dweb:/ipfs/QmPbzKR19rdM8X3PLQjsmHRepUKhvoZnedSR63XyGtXZib" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": { + "keccak256": "0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7", + "urls": [ + "bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db", + "dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol": { + "keccak256": "0xaa7f0646f49ebe2606eeca169f85c56451bbaeeeb06265fa076a03369a25d1d3", + "urls": [ + "bzz-raw://ee931d4e832385765967efe6366dcc6d00d6a2d794f9c66ee38283c03882de9c", + "dweb:/ipfs/QmR6SkuJGYxpQeLz38rBdghqaWqEPfzUsL9kBoXgEXKtbD" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "keccak256": "0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330", + "urls": [ + "bzz-raw://c13d13304ac79a83ab1c30168967d19e2203342ebbd6a9bbce4db7550522dcbf", + "dweb:/ipfs/QmeN5jKMN2vw5bhacr6tkg78afbTTZUeaacNHqjWt4Ew1r" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "keccak256": "0x27dbc90e5136ffe46c04f7596fc2dbcc3acebd8d504da3d93fdb8496e6de04f6", + "urls": [ + "bzz-raw://0ea8b92e4245d75a5579c10f22f118f7b4ba07c57341f181f0b2a85ff8663de3", + "dweb:/ipfs/Qme3Ss5ByjmkxxkMdLpyu7fQ1PCtjNFH1wEFszt2BZePiG" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "keccak256": "0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2", + "urls": [ + "bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12", + "dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/Nonces.sol": { + "keccak256": "0x0082767004fca261c332e9ad100868327a863a88ef724e844857128845ab350f", + "urls": [ + "bzz-raw://132dce9686a54e025eb5ba5d2e48208f847a1ec3e60a3e527766d7bf53fb7f9e", + "dweb:/ipfs/QmXn1a2nUZMpu2z6S88UoTfMVtY2YNh86iGrzJDYmMkKeZ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/Panic.sol": { + "keccak256": "0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a", + "urls": [ + "bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a", + "dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol": { + "keccak256": "0x7d94fa0af099a2172eb01f9c8a8a443cbe7e0e43654841563e4e09968efdb549", + "urls": [ + "bzz-raw://65e38fb76b6add407d4557753ae83dd1268e8261195dbe5c19a580d5ba6e4e9a", + "dweb:/ipfs/QmTkGSJtaQrqjcyWM4AgemeEmKgtDydKPPVRajsUJRQSrK" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol": { + "keccak256": "0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97", + "urls": [ + "bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b", + "dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/Strings.sol": { + "keccak256": "0x44f87e91783e88415bde66f1a63f6c7f0076f2d511548820407d5c95643ac56c", + "urls": [ + "bzz-raw://13a51bc2b23827744dcf5bad10c69e72528cf015a6fe48c93632cdb2c0eb1251", + "dweb:/ipfs/QmZwPA47Yqgje1qtkdEFEja8ntTahMStYzKf5q3JRnaR7d" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol": { + "keccak256": "0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84", + "urls": [ + "bzz-raw://8e25e4bdb7ae1f21d23bfee996e22736fc0ab44cfabedac82a757b1edc5623b9", + "dweb:/ipfs/QmQdWQvB6JCP9ZMbzi8EvQ1PTETqkcTWrbcVurS7DKpa5n" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol": { + "keccak256": "0x10eb97d047f8d84fe263a02bb4a656ac6674f6679d74532cc37546289e073a9d", + "urls": [ + "bzz-raw://3e41287d40b0c46982f1083d40d32de2761f009c5c51627fe79a7feb0ab1cf5c", + "dweb:/ipfs/Qme7dbh6HX3ZvUJdbQAcVqXkmyXyfcLiUZRhhon3cU6K8p" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol": { + "keccak256": "0x4515543bc4c78561f6bea83ecfdfc3dead55bd59858287d682045b11de1ae575", + "urls": [ + "bzz-raw://60601f91440125727244fffd2ba84da7caafecaae0fd887c7ccfec678e02b61e", + "dweb:/ipfs/QmZnKPBtVDiQS9Dp8gZ4sa3ZeTrWVfqF7yuUd6Y8hwm1Rs" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": { + "keccak256": "0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa", + "urls": [ + "bzz-raw://8084aa71a4cc7d2980972412a88fe4f114869faea3fefa5436431644eb5c0287", + "dweb:/ipfs/Qmbqfs5dRdPvHVKY8kTaeyc65NdqXRQwRK7h9s5UJEhD1p" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": { + "keccak256": "0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8", + "urls": [ + "bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621", + "dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": { + "keccak256": "0xa00be322d7db5786750ce0ac7e2f5b633ac30a5ed5fa1ced1e74acfc19acecea", + "urls": [ + "bzz-raw://6c84e822f87cbdc4082533b626667b6928715bb2b1e8e7eb96954cebb9e38c8d", + "dweb:/ipfs/QmZmy9dgxLTerBAQDuuHqbL6EpgRxddqgv5KmwpXYVbKz1" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": { + "keccak256": "0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54", + "urls": [ + "bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8", + "dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": { + "keccak256": "0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3", + "urls": [ + "bzz-raw://db5fbb3dddd8b7047465b62575d96231ba8a2774d37fb4737fbf23340fabbb03", + "dweb:/ipfs/QmVUSvooZKEdEdap619tcJjTLcAuH6QBdZqAzWwnAXZAWJ" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "id": 0 +} + +export const CAT_FACTORY_ABI = CAT_FACTORY.abi; From ace9bdd1ee033a7c364c0b481016c4df7609ef2c Mon Sep 17 00:00:00 2001 From: DengreSarthak Date: Sat, 11 Jan 2025 18:00:30 +0530 Subject: [PATCH 8/8] Added Layout --- web/src/app/[cat]/InteractionClient.tsx | 2 +- web/src/app/[cat]/page.tsx | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/web/src/app/[cat]/InteractionClient.tsx b/web/src/app/[cat]/InteractionClient.tsx index 032320b3..3085c962 100644 --- a/web/src/app/[cat]/InteractionClient.tsx +++ b/web/src/app/[cat]/InteractionClient.tsx @@ -137,7 +137,7 @@ export default function InteractionClient() { } return ( -
+
diff --git a/web/src/app/[cat]/page.tsx b/web/src/app/[cat]/page.tsx index 902bf64b..01c92eb8 100644 --- a/web/src/app/[cat]/page.tsx +++ b/web/src/app/[cat]/page.tsx @@ -1,6 +1,7 @@ import { notFound } from "next/navigation"; import InteractionClient from "./InteractionClient"; import { Suspense } from "react"; +import Layout from "@/components/Layout"; export async function generateStaticParams() { return [{ cat: "c" }]; @@ -8,8 +9,10 @@ export async function generateStaticParams() { export default function VaultPage() { return ( - - - + + + + + ); }