From ae9aad8c39842cb7187717045329d2f3b33484df Mon Sep 17 00:00:00 2001 From: Andres Aiello Date: Wed, 6 Nov 2024 14:08:27 -0300 Subject: [PATCH] add test --- .../instant-rewards/InstantRewardsFactory.sol | 14 +++ .../instant-rewards/InstantRewardsV2.sol | 2 +- .../instant-rewards-v2-compatibility.ts | 8 +- .../instant-rewards/instant-rewards-v2.ts | 94 +++++++++++++++++++ 4 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2.ts diff --git a/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsFactory.sol b/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsFactory.sol index 1674b28..0c69f89 100644 --- a/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsFactory.sol +++ b/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsFactory.sol @@ -5,14 +5,28 @@ import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "./InstantRewardsV2.sol"; contract InstantRewardsFactory is Ownable2Step { + bool public allowPublicCreation = false; + + error AccessDenied(); event InstantRewardsCreated(address indexed instantRewards, address indexed owner); + constructor(address owner) Ownable() { + transferOwnership(owner); + } + + function setAllowPublicCreation(bool allowPublicCreation_) external onlyOwner { + allowPublicCreation = allowPublicCreation_; + } + function createInstantRewards( address signerAddress, uint256 start, uint256 end, string memory name ) external returns (address) { + bool isOwner = owner() == msg.sender; + if (!allowPublicCreation && !isOwner) revert AccessDenied(); + InstantRewardsV2 instantRewards = new InstantRewardsV2(signerAddress, owner(), start, end, name); instantRewards.transferOwnership(owner()); emit InstantRewardsCreated(address(instantRewards), owner()); diff --git a/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsV2.sol b/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsV2.sol index 8750088..145eeeb 100644 --- a/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsV2.sol +++ b/packages/zevm-app-contracts/contracts/instant-rewards/InstantRewardsV2.sol @@ -47,7 +47,7 @@ contract InstantRewardsV2 is InstantRewards { super.claim(claimData); } - function withdraw(address wallet, uint256 amount) public override { + function withdraw(address wallet, uint256 amount) public override onlyOwner { if (isActive()) revert InstantRewardStillActive(); super.withdraw(wallet, amount); } diff --git a/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2-compatibility.ts b/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2-compatibility.ts index bfc21ff..7ac1ff1 100644 --- a/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2-compatibility.ts +++ b/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2-compatibility.ts @@ -9,7 +9,7 @@ import { ClaimData, getSignature } from "./test.helpers"; const HARDHAT_CHAIN_ID = 1337; -describe("Instant Rewards Contract test", () => { +describe("Instant Rewards V2 Contract Compatibility test", () => { let instantRewards: InstantRewardsV2, owner: SignerWithAddress, signer: SignerWithAddress, @@ -198,7 +198,7 @@ describe("Instant Rewards Contract test", () => { to ); - instantRewards.claim(claimDataSigned); + await instantRewards.claim(claimDataSigned); const tx = instantRewards.claim(claimDataSigned); await expect(tx).to.revertedWith("TaskAlreadyClaimed"); @@ -227,7 +227,7 @@ describe("Instant Rewards Contract test", () => { taskId, to ); - instantRewards.claim(claimDataSigned); + await instantRewards.claim(claimDataSigned); } const claimDataSigned = await getClaimDataSigned( HARDHAT_CHAIN_ID, @@ -275,7 +275,7 @@ describe("Instant Rewards Contract test", () => { to ); - instantRewards.claim(newClaimDataSigned); + await instantRewards.claim(newClaimDataSigned); const tx = instantRewards.claim(claimDataSigned); await expect(tx).to.revertedWith("TaskAlreadyClaimed"); diff --git a/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2.ts b/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2.ts new file mode 100644 index 0000000..06965cb --- /dev/null +++ b/packages/zevm-app-contracts/test/instant-rewards/instant-rewards-v2.ts @@ -0,0 +1,94 @@ +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { BigNumber, utils } from "ethers"; +import { parseEther } from "ethers/lib/utils"; +import { ethers } from "hardhat"; + +import { InstantRewardsFactory, InstantRewardsV2 } from "../../typechain-types"; +import { ClaimData, getSignature } from "./test.helpers"; + +const HARDHAT_CHAIN_ID = 1337; + +describe("Instant Rewards Contract test", () => { + let instantRewardsFactory: InstantRewardsFactory, + deployer: SignerWithAddress, + owner: SignerWithAddress, + signer: SignerWithAddress, + user: SignerWithAddress, + addrs: SignerWithAddress[]; + + const encodeTaskId = (taskId: string) => utils.keccak256(utils.defaultAbiCoder.encode(["string"], [taskId])); + + const getClaimDataSigned = async ( + chainId: number, + verifyingContract: string, + signer: SignerWithAddress, + amount: BigNumber, + sigExpiration: number, + taskId: string, + to: string + ) => { + const claimData: ClaimData = { + amount, + sigExpiration, + taskId, + to, + }; + + const signature = await getSignature(chainId, verifyingContract, signer, claimData); + return { + ...claimData, + signature, + }; + }; + + beforeEach(async () => { + [deployer, owner, signer, user, ...addrs] = await ethers.getSigners(); + const instantRewardsFactoryF = await ethers.getContractFactory("InstantRewardsFactory"); + instantRewardsFactory = (await instantRewardsFactoryF.deploy(owner.address)) as InstantRewardsFactory; + await instantRewardsFactory.deployed(); + await instantRewardsFactory.connect(owner).acceptOwnership(); + }); + + it("Should deploy an IR instance", async () => { + const currentBlock = await ethers.provider.getBlock("latest"); + const start = currentBlock.timestamp + 1000; + const end = start + 1000; + const name = "Instant Rewards"; + const tx = instantRewardsFactory.connect(owner).createInstantRewards(signer.address, start, end, name); + await expect(tx).to.emit(instantRewardsFactory, "InstantRewardsCreated"); + + const events = await instantRewardsFactory.queryFilter("InstantRewardsCreated"); + const address = events[0].args?.instantRewards; + expect(address).to.be.not.undefined; + + const instantRewards = (await ethers.getContractAt("InstantRewardsV2", address)) as InstantRewardsV2; + expect(await instantRewards.signerAddress()).to.be.eq(signer.address); + expect(await instantRewards.start()).to.be.eq(start); + expect(await instantRewards.end()).to.be.eq(end); + expect(await instantRewards.name()).to.be.eq(name); + + await instantRewards.connect(owner).acceptOwnership(); + expect(await instantRewards.owner()).to.be.eq(owner.address); + }); + + it("Should revert if not owner try to deploy", async () => { + const currentBlock = await ethers.provider.getBlock("latest"); + const start = currentBlock.timestamp + 1000; + const end = start + 1000; + const name = "Instant Rewards"; + const tx = instantRewardsFactory.createInstantRewards(signer.address, start, end, name); + await expect(tx).to.revertedWith("AccessDenied"); + }); + + it("Should deploy an IR instance with any wallet if it's open", async () => { + await instantRewardsFactory.connect(owner).setAllowPublicCreation(true); + + const currentBlock = await ethers.provider.getBlock("latest"); + const start = currentBlock.timestamp + 1000; + const end = start + 1000; + const name = "Instant Rewards"; + const tx = instantRewardsFactory.createInstantRewards(signer.address, start, end, name); + await expect(tx).to.emit(instantRewardsFactory, "InstantRewardsCreated"); + }); +});