From 4a4248e796b67be77f1c8efaa267539c3822806e Mon Sep 17 00:00:00 2001 From: Salman <29351207+Salmandabbakuti@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:25:23 +0530 Subject: [PATCH] contract fixes, deployment scripts,subgraph deployment --- contracts/FluidGrants.sol | 22 +-- hardhat.config.ts | 8 + .../deployments/chain-11155111/journal.jsonl | 2 + ignition/modules/FluidGrants.ts | 9 + ignition/modules/Lock.ts | 17 -- subgraph/package.json | 3 +- subgraph/subgraph.yaml | 4 +- subgraph/tests/fluid-grants-utils.ts | 186 ------------------ subgraph/tests/fluid-grants.test.ts | 124 ------------ test/Lock.ts | 127 ------------ 10 files changed, 30 insertions(+), 472 deletions(-) create mode 100644 ignition/deployments/chain-11155111/journal.jsonl create mode 100644 ignition/modules/FluidGrants.ts delete mode 100644 ignition/modules/Lock.ts delete mode 100644 subgraph/tests/fluid-grants-utils.ts delete mode 100644 subgraph/tests/fluid-grants.test.ts delete mode 100644 test/Lock.ts diff --git a/contracts/FluidGrants.sol b/contracts/FluidGrants.sol index 7da60a7..096c51b 100644 --- a/contracts/FluidGrants.sol +++ b/contracts/FluidGrants.sol @@ -3,14 +3,12 @@ pragma solidity 0.8.24; import {ISuperToken} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; import {ISuperfluidPool} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/gdav1/ISuperfluidPool.sol"; -import {SuperTokenV1Library} from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol"; -import "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol"; +import {SuperTokenV1Library, PoolConfig} from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol"; contract FluidGrants { using SuperTokenV1Library for ISuperToken; uint256 public grantCount; - uint256 public projectCount; struct Grant { uint256 id; @@ -70,13 +68,11 @@ contract FluidGrants { event GrantDistributed(uint256 grantId, uint256 amount); - mapping(uint256 grantId => Grant) public grants; - mapping(uint256 projectId => Project) public projects; - mapping(uint256 grantId => uint256 count) public grantProjectCount; - mapping(uint256 grantId => mapping(address user => bool hasSubmitted)) - public hasSubmittedToGrant; - mapping(uint256 grantId => mapping(uint256 projectId => bool)) - public isProjectInGrant; + mapping(uint256 => Grant) public grants; + mapping(uint256 => Project) public projects; + mapping(uint256 => uint256) public grantProjectCount; + mapping(uint256 => mapping(address => bool)) public hasSubmittedToGrant; + mapping(uint256 => mapping(uint256 => bool)) public isProjectInGrant; function createGrant( string memory _name, @@ -151,7 +147,7 @@ contract FluidGrants { Grant memory grant = grants[_grantId]; require(grant.isActive, "Grant is not active"); require( - block.timestamp >= grant.submissionStartsAt || + block.timestamp >= grant.submissionStartsAt && block.timestamp <= grant.submissionEndsAt, "Grant is not in submission period" ); @@ -159,8 +155,6 @@ contract FluidGrants { !hasSubmittedToGrant[_grantId][msg.sender], "You have already submitted a project to this grant" ); - ISuperToken token = grant.distributionToken; - ISuperfluidPool pool = grant.pool; uint256 projectId = grantProjectCount[_grantId]++; projects[projectId] = Project({ id: projectId, @@ -194,7 +188,7 @@ contract FluidGrants { require(project.walletAddress != address(0), "Project does not exist"); require(grant.isActive, "Grant is not active"); require( - block.timestamp >= grant.judgingStartsAt || + block.timestamp >= grant.judgingStartsAt && block.timestamp <= grant.judgingEndsAt, "Grant is not in judging period" ); diff --git a/hardhat.config.ts b/hardhat.config.ts index 3bd6862..5103def 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,8 +1,16 @@ import { HardhatUserConfig } from "hardhat/config"; import "@nomicfoundation/hardhat-toolbox"; +const accounts = process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []; + const config: HardhatUserConfig = { solidity: "0.8.24", + networks: { + sepolia: { + url: "https://sepolia.drpc.org", + accounts + } + } }; export default config; diff --git a/ignition/deployments/chain-11155111/journal.jsonl b/ignition/deployments/chain-11155111/journal.jsonl new file mode 100644 index 0000000..e247ada --- /dev/null +++ b/ignition/deployments/chain-11155111/journal.jsonl @@ -0,0 +1,2 @@ + +{"chainId":11155111,"type":"DEPLOYMENT_INITIALIZE"} \ No newline at end of file diff --git a/ignition/modules/FluidGrants.ts b/ignition/modules/FluidGrants.ts new file mode 100644 index 0000000..6704d43 --- /dev/null +++ b/ignition/modules/FluidGrants.ts @@ -0,0 +1,9 @@ +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; + +const FluidGrantsModule = buildModule("FluidGrants", (m) => { + const fluidGrants = m.contract("FluidGrants", []); + + return { fluidGrants }; +}); + +export default FluidGrantsModule; diff --git a/ignition/modules/Lock.ts b/ignition/modules/Lock.ts deleted file mode 100644 index eda0eba..0000000 --- a/ignition/modules/Lock.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; - -const JAN_1ST_2030 = 1893456000; -const ONE_GWEI: bigint = 1_000_000_000n; - -const LockModule = buildModule("LockModule", (m) => { - const unlockTime = m.getParameter("unlockTime", JAN_1ST_2030); - const lockedAmount = m.getParameter("lockedAmount", ONE_GWEI); - - const lock = m.contract("Lock", [unlockTime], { - value: lockedAmount, - }); - - return { lock }; -}); - -export default LockModule; diff --git a/subgraph/package.json b/subgraph/package.json index d8fe46c..5c399b5 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -13,6 +13,5 @@ "dependencies": { "@graphprotocol/graph-cli": "0.82.0", "@graphprotocol/graph-ts": "0.32.0" - }, - "devDependencies": { "matchstick-as": "0.5.0" } + } } diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 32606dd..8f63861 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -8,9 +8,9 @@ dataSources: name: FluidGrants network: sepolia source: - address: "0xDe1EdD357001273Cd6415B225831bf636d0Ac710" + address: "0xecd65f216559427cd681ed09c6c484eedee1839a" abi: FluidGrants - startBlock: 6725519 + startBlock: 6744543 mapping: kind: ethereum/events apiVersion: 0.0.7 diff --git a/subgraph/tests/fluid-grants-utils.ts b/subgraph/tests/fluid-grants-utils.ts deleted file mode 100644 index bc520ba..0000000 --- a/subgraph/tests/fluid-grants-utils.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { newMockEvent } from "matchstick-as" -import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts" -import { - GrantCreated, - GrantDistributed, - ProjectSubmitted, - ProjectVoted -} from "../generated/FluidGrants/FluidGrants" - -export function createGrantCreatedEvent( - id: BigInt, - name: string, - description: string, - externalUrl: string, - amount: BigInt, - submissionStartsAt: BigInt, - submissionEndsAt: BigInt, - judgingStartsAt: BigInt, - judgingEndsAt: BigInt, - distributionToken: Address, - pool: Address -): GrantCreated { - let grantCreatedEvent = changetype(newMockEvent()) - - grantCreatedEvent.parameters = new Array() - - grantCreatedEvent.parameters.push( - new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam("name", ethereum.Value.fromString(name)) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "description", - ethereum.Value.fromString(description) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "externalUrl", - ethereum.Value.fromString(externalUrl) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam("amount", ethereum.Value.fromUnsignedBigInt(amount)) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "submissionStartsAt", - ethereum.Value.fromUnsignedBigInt(submissionStartsAt) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "submissionEndsAt", - ethereum.Value.fromUnsignedBigInt(submissionEndsAt) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "judgingStartsAt", - ethereum.Value.fromUnsignedBigInt(judgingStartsAt) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "judgingEndsAt", - ethereum.Value.fromUnsignedBigInt(judgingEndsAt) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam( - "distributionToken", - ethereum.Value.fromAddress(distributionToken) - ) - ) - grantCreatedEvent.parameters.push( - new ethereum.EventParam("pool", ethereum.Value.fromAddress(pool)) - ) - - return grantCreatedEvent -} - -export function createGrantDistributedEvent( - grantId: BigInt, - amount: BigInt -): GrantDistributed { - let grantDistributedEvent = changetype(newMockEvent()) - - grantDistributedEvent.parameters = new Array() - - grantDistributedEvent.parameters.push( - new ethereum.EventParam( - "grantId", - ethereum.Value.fromUnsignedBigInt(grantId) - ) - ) - grantDistributedEvent.parameters.push( - new ethereum.EventParam("amount", ethereum.Value.fromUnsignedBigInt(amount)) - ) - - return grantDistributedEvent -} - -export function createProjectSubmittedEvent( - id: BigInt, - grantId: BigInt, - name: string, - description: string, - repositoryUrl: string, - demoUrl: string, - walletAddress: Address -): ProjectSubmitted { - let projectSubmittedEvent = changetype(newMockEvent()) - - projectSubmittedEvent.parameters = new Array() - - projectSubmittedEvent.parameters.push( - new ethereum.EventParam("id", ethereum.Value.fromUnsignedBigInt(id)) - ) - projectSubmittedEvent.parameters.push( - new ethereum.EventParam( - "grantId", - ethereum.Value.fromUnsignedBigInt(grantId) - ) - ) - projectSubmittedEvent.parameters.push( - new ethereum.EventParam("name", ethereum.Value.fromString(name)) - ) - projectSubmittedEvent.parameters.push( - new ethereum.EventParam( - "description", - ethereum.Value.fromString(description) - ) - ) - projectSubmittedEvent.parameters.push( - new ethereum.EventParam( - "repositoryUrl", - ethereum.Value.fromString(repositoryUrl) - ) - ) - projectSubmittedEvent.parameters.push( - new ethereum.EventParam("demoUrl", ethereum.Value.fromString(demoUrl)) - ) - projectSubmittedEvent.parameters.push( - new ethereum.EventParam( - "walletAddress", - ethereum.Value.fromAddress(walletAddress) - ) - ) - - return projectSubmittedEvent -} - -export function createProjectVotedEvent( - projectId: BigInt, - grantId: BigInt, - votes: BigInt, - voter: Address -): ProjectVoted { - let projectVotedEvent = changetype(newMockEvent()) - - projectVotedEvent.parameters = new Array() - - projectVotedEvent.parameters.push( - new ethereum.EventParam( - "projectId", - ethereum.Value.fromUnsignedBigInt(projectId) - ) - ) - projectVotedEvent.parameters.push( - new ethereum.EventParam( - "grantId", - ethereum.Value.fromUnsignedBigInt(grantId) - ) - ) - projectVotedEvent.parameters.push( - new ethereum.EventParam("votes", ethereum.Value.fromUnsignedBigInt(votes)) - ) - projectVotedEvent.parameters.push( - new ethereum.EventParam("voter", ethereum.Value.fromAddress(voter)) - ) - - return projectVotedEvent -} diff --git a/subgraph/tests/fluid-grants.test.ts b/subgraph/tests/fluid-grants.test.ts deleted file mode 100644 index 32a87a7..0000000 --- a/subgraph/tests/fluid-grants.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { - assert, - describe, - test, - clearStore, - beforeAll, - afterAll -} from "matchstick-as/assembly/index" -import { BigInt, Address } from "@graphprotocol/graph-ts" -import { ExampleEntity } from "../generated/schema" -import { GrantCreated } from "../generated/FluidGrants/FluidGrants" -import { handleGrantCreated } from "../src/fluid-grants" -import { createGrantCreatedEvent } from "./fluid-grants-utils" - -// Tests structure (matchstick-as >=0.5.0) -// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0 - -describe("Describe entity assertions", () => { - beforeAll(() => { - let id = BigInt.fromI32(234) - let name = "Example string value" - let description = "Example string value" - let externalUrl = "Example string value" - let amount = BigInt.fromI32(234) - let submissionStartsAt = BigInt.fromI32(234) - let submissionEndsAt = BigInt.fromI32(234) - let judgingStartsAt = BigInt.fromI32(234) - let judgingEndsAt = BigInt.fromI32(234) - let distributionToken = Address.fromString( - "0x0000000000000000000000000000000000000001" - ) - let pool = Address.fromString("0x0000000000000000000000000000000000000001") - let newGrantCreatedEvent = createGrantCreatedEvent( - id, - name, - description, - externalUrl, - amount, - submissionStartsAt, - submissionEndsAt, - judgingStartsAt, - judgingEndsAt, - distributionToken, - pool - ) - handleGrantCreated(newGrantCreatedEvent) - }) - - afterAll(() => { - clearStore() - }) - - // For more test scenarios, see: - // https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test - - test("ExampleEntity created and stored", () => { - assert.entityCount("ExampleEntity", 1) - - // 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "name", - "Example string value" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "description", - "Example string value" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "externalUrl", - "Example string value" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "amount", - "234" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "submissionStartsAt", - "234" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "submissionEndsAt", - "234" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "judgingStartsAt", - "234" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "judgingEndsAt", - "234" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "distributionToken", - "0x0000000000000000000000000000000000000001" - ) - assert.fieldEquals( - "ExampleEntity", - "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", - "pool", - "0x0000000000000000000000000000000000000001" - ) - - // More assert options: - // https://thegraph.com/docs/en/developer/matchstick/#asserts - }) -}) diff --git a/test/Lock.ts b/test/Lock.ts deleted file mode 100644 index 160dbfa..0000000 --- a/test/Lock.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { - time, - loadFixture, -} from "@nomicfoundation/hardhat-toolbox/network-helpers"; -import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs"; -import { expect } from "chai"; -import hre from "hardhat"; - -describe("Lock", function () { - // We define a fixture to reuse the same setup in every test. - // We use loadFixture to run this setup once, snapshot that state, - // and reset Hardhat Network to that snapshot in every test. - async function deployOneYearLockFixture() { - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const ONE_GWEI = 1_000_000_000; - - const lockedAmount = ONE_GWEI; - const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; - - // Contracts are deployed using the first signer/account by default - const [owner, otherAccount] = await hre.ethers.getSigners(); - - const Lock = await hre.ethers.getContractFactory("Lock"); - const lock = await Lock.deploy(unlockTime, { value: lockedAmount }); - - return { lock, unlockTime, lockedAmount, owner, otherAccount }; - } - - describe("Deployment", function () { - it("Should set the right unlockTime", async function () { - const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.unlockTime()).to.equal(unlockTime); - }); - - it("Should set the right owner", async function () { - const { lock, owner } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.owner()).to.equal(owner.address); - }); - - it("Should receive and store the funds to lock", async function () { - const { lock, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - - expect(await hre.ethers.provider.getBalance(lock.target)).to.equal( - lockedAmount - ); - }); - - it("Should fail if the unlockTime is not in the future", async function () { - // We don't use the fixture here because we want a different deployment - const latestTime = await time.latest(); - const Lock = await hre.ethers.getContractFactory("Lock"); - await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith( - "Unlock time should be in the future" - ); - }); - }); - - describe("Withdrawals", function () { - describe("Validations", function () { - it("Should revert with the right error if called too soon", async function () { - const { lock } = await loadFixture(deployOneYearLockFixture); - - await expect(lock.withdraw()).to.be.revertedWith( - "You can't withdraw yet" - ); - }); - - it("Should revert with the right error if called from another account", async function () { - const { lock, unlockTime, otherAccount } = await loadFixture( - deployOneYearLockFixture - ); - - // We can increase the time in Hardhat Network - await time.increaseTo(unlockTime); - - // We use lock.connect() to send a transaction from another account - await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith( - "You aren't the owner" - ); - }); - - it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () { - const { lock, unlockTime } = await loadFixture( - deployOneYearLockFixture - ); - - // Transactions are sent using the first signer by default - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()).not.to.be.reverted; - }); - }); - - describe("Events", function () { - it("Should emit an event on withdrawals", async function () { - const { lock, unlockTime, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()) - .to.emit(lock, "Withdrawal") - .withArgs(lockedAmount, anyValue); // We accept any value as `when` arg - }); - }); - - describe("Transfers", function () { - it("Should transfer the funds to the owner", async function () { - const { lock, unlockTime, lockedAmount, owner } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - - await expect(lock.withdraw()).to.changeEtherBalances( - [owner, lock], - [lockedAmount, -lockedAmount] - ); - }); - }); - }); -});