From 322e45060a61c5dc814120473c5b3214d5101b94 Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Mon, 16 Jan 2023 13:29:54 -0300 Subject: [PATCH 1/8] add polygon aludel factory deployment file --- deployments/polygon/.chainId | 1 + deployments/polygon/AludelFactory.json | 515 +++++++++++++++++++++++++ 2 files changed, 516 insertions(+) create mode 100644 deployments/polygon/.chainId create mode 100644 deployments/polygon/AludelFactory.json diff --git a/deployments/polygon/.chainId b/deployments/polygon/.chainId new file mode 100644 index 00000000..065fd3e7 --- /dev/null +++ b/deployments/polygon/.chainId @@ -0,0 +1 @@ +137 diff --git a/deployments/polygon/AludelFactory.json b/deployments/polygon/AludelFactory.json new file mode 100644 index 00000000..caef2e90 --- /dev/null +++ b/deployments/polygon/AludelFactory.json @@ -0,0 +1,515 @@ +{ + "address": "0x075d940Fa6878c6164f3F44CFc584923c4F5654C", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint16", + "name": "bps", + "type": "uint16" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AludelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "AludelNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTemplate", + "type": "error" + }, + { + "inputs": [], + "name": "ProgramAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "TemplateAlreadyAdded", + "type": "error" + }, + { + "inputs": [], + "name": "TemplateDisabled", + "type": "error" + }, + { + "inputs": [], + "name": "TemplateNotRegistered", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "program", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "ProgramAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "program", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + } + ], + "name": "ProgramChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "program", + "type": "address" + } + ], + "name": "ProgramDelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "template", + "type": "address" + } + ], + "name": "TemplateAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "disabled", + "type": "bool" + } + ], + "name": "TemplateUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "program", + "type": "address" + }, + { + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "stakingTokenUrl", + "type": "string" + }, + { + "internalType": "uint64", + "name": "startTime", + "type": "uint64" + } + ], + "name": "addProgram", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bool", + "name": "disabled", + "type": "bool" + } + ], + "name": "addTemplate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "program", + "type": "address" + } + ], + "name": "delistProgram", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeBps", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "template", + "type": "address" + } + ], + "name": "getTemplate", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "listed", + "type": "bool" + }, + { + "internalType": "bool", + "name": "disabled", + "type": "bool" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "internalType": "struct AludelFactory.TemplateData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "isAludel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "stakingTokenUrl", + "type": "string" + }, + { + "internalType": "uint64", + "name": "startTime", + "type": "uint64" + }, + { + "internalType": "address", + "name": "vaultFactory", + "type": "address" + }, + { + "internalType": "address[]", + "name": "bonusTokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "ownerAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "launch", + "outputs": [ + { + "internalType": "address", + "name": "aludel", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "program", + "type": "address" + } + ], + "name": "programs", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "internalType": "uint64", + "name": "startTime", + "type": "uint64" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "stakingTokenUrl", + "type": "string" + } + ], + "internalType": "struct AludelFactory.ProgramData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "bps", + "type": "uint16" + } + ], + "name": "setFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newRecipient", + "type": "address" + } + ], + "name": "setFeeRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "program", + "type": "address" + }, + { + "internalType": "string", + "name": "newName", + "type": "string" + }, + { + "internalType": "string", + "name": "newUrl", + "type": "string" + } + ], + "name": "updateProgram", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "template", + "type": "address" + }, + { + "internalType": "bool", + "name": "disabled", + "type": "bool" + } + ], + "name": "updateTemplate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file From 33eb9f9d5d12666591562ae451afb56296f6a58f Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Mon, 16 Jan 2023 13:30:54 -0300 Subject: [PATCH 2/8] add polygon network config --- hardhat.config.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hardhat.config.ts b/hardhat.config.ts index aceb0933..d029051a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -84,6 +84,13 @@ const config: HardhatUserConfig = { }, saveDeployments: true, }, + polygon: { + url: process.env.POLYGON_URL || "", + accounts: { + mnemonic, + }, + saveDeployments: true, + }, avalanche: { url: "https://api.avax.network/ext/bc/C/rpc", chainId: 43114, From 0604463e6eb9d17821376ba86aa3bf89d3c98a33 Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Mon, 16 Jan 2023 13:31:05 -0300 Subject: [PATCH 3/8] add update-program hardhat task --- tasks/aludel.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tasks/aludel.ts b/tasks/aludel.ts index 22b2141c..6fe21e75 100644 --- a/tasks/aludel.ts +++ b/tasks/aludel.ts @@ -3,6 +3,7 @@ import { formatEther } from "ethers/lib/utils"; import { task, types } from "hardhat/config"; import "@nomiclabs/hardhat-ethers"; import { parseEther } from "@ethersproject/units"; +import { AludelFactory } from "../typechain-types"; // this function is meant to avoid polluting the tests with console output, and // log on every other scenario @@ -226,3 +227,28 @@ task("add-program", "add a pre-existing aludel to the network's aludel factory") ).wait(); } ); + +task("update-program", "update an already added template") + .addParam("program", "address of the program to update") + .addOptionalParam("newName", "a new name for the program. Optional.", "") + .addOptionalParam("newUrl", "a new URL for the program. Optional.", "") + .setAction(async (args, { ethers, deployments }) => { + + const factoryAddress = (await deployments.get("AludelFactory")).address; + const factory = await ethers.getContractAt( + "src/contracts/AludelFactory.sol:AludelFactory", + factoryAddress + ) as AludelFactory; + + const programData = await factory.programs(args.program); + log(`updating program ${programData.name} on factory ${factoryAddress}`); + + if (args.newName) { + log(`program's new name: ${args.newName}`) + } + if (args.newUrl) { + log(`program's new URL: ${args.newUrl}`) + } + + await (await factory.updateProgram(args.program, args.newName, args.newUrl)).wait(); + }); \ No newline at end of file From a5cf50dd13d9228c30929190d6497586bbd9483e Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Mon, 16 Jan 2023 13:46:20 -0300 Subject: [PATCH 4/8] run lint-ts --- tasks/aludel.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tasks/aludel.ts b/tasks/aludel.ts index 6fe21e75..af9698be 100644 --- a/tasks/aludel.ts +++ b/tasks/aludel.ts @@ -233,22 +233,23 @@ task("update-program", "update an already added template") .addOptionalParam("newName", "a new name for the program. Optional.", "") .addOptionalParam("newUrl", "a new URL for the program. Optional.", "") .setAction(async (args, { ethers, deployments }) => { - const factoryAddress = (await deployments.get("AludelFactory")).address; - const factory = await ethers.getContractAt( + const factory = (await ethers.getContractAt( "src/contracts/AludelFactory.sol:AludelFactory", factoryAddress - ) as AludelFactory; + )) as AludelFactory; const programData = await factory.programs(args.program); log(`updating program ${programData.name} on factory ${factoryAddress}`); if (args.newName) { - log(`program's new name: ${args.newName}`) + log(`program's new name: ${args.newName}`); } if (args.newUrl) { - log(`program's new URL: ${args.newUrl}`) + log(`program's new URL: ${args.newUrl}`); } - await (await factory.updateProgram(args.program, args.newName, args.newUrl)).wait(); - }); \ No newline at end of file + await ( + await factory.updateProgram(args.program, args.newName, args.newUrl) + ).wait(); + }); From c9c7f95c24b4b48243a6d4d714cd23cf649a3d9d Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Tue, 17 Jan 2023 09:34:17 -0300 Subject: [PATCH 5/8] add tests for update-program task use proper WHEN-THEN syntaxis update tests grammar --- test/deployments.ts | 69 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/test/deployments.ts b/test/deployments.ts index 2a3a4a44..e15874fc 100644 --- a/test/deployments.ts +++ b/test/deployments.ts @@ -120,7 +120,7 @@ describe("Aludel factory deployments", function () { preexistingProgram = (await ethersFactory.deploy()) as Aludel; }); - describe("WHEN adding it with the add-program task, AND passing al parameters", () => { + describe("WHEN adding it with the add-program task, AND passing all parameters", () => { beforeEach(async () => { await run("add-program", { program: preexistingProgram.address, @@ -134,6 +134,73 @@ describe("Aludel factory deployments", function () { const program = await factory.programs(preexistingProgram.address); expect(program.name).to.eq("some name"); }); + describe("WHEN updates the program using update-program", () => { + let program: AludelFactory.ProgramDataStruct; + beforeEach(async () => { + program = await factory.programs(preexistingProgram.address); + }); + describe("AND updates the name", async () => { + beforeEach(async () => { + await run("update-program", { + program: preexistingProgram.address, + newName: "a brave new name" + }); + }); + it("THEN only the name is changed", async () => { + const updatedProgram = await factory.programs(preexistingProgram.address); + expect(updatedProgram.name).to.eq("a brave new name"); + expect(updatedProgram.stakingTokenUrl).to.eq(program.stakingTokenUrl); + expect(updatedProgram.template).to.eq(program.template); + expect(updatedProgram.startTime).to.eq(program.startTime); + }); + }); + describe("AND updates the url", async () => { + beforeEach(async () => { + await run("update-program", { + program: preexistingProgram.address, + newUrl: "https://new.domain", + }); + }); + it("THEN only the url is changed", async () => { + const updatedProgram = await factory.programs( + preexistingProgram.address + ); + expect(updatedProgram.name).to.eq(program.name); + expect(updatedProgram.stakingTokenUrl).to.eq( + "https://new.domain" + ); + expect(updatedProgram.template).to.eq(program.template); + expect(updatedProgram.startTime).to.eq(program.startTime); + }); + }); + describe("AND update the name and the url", async () => { + beforeEach(async () => { + await run("update-program", { + program: preexistingProgram.address, + newName: "a brave new name", + newUrl: "https://new.domain", + }); + }); + it("THEN only the name and the url are changed", async () => { + const updatedProgram = await factory.programs( + preexistingProgram.address + ); + expect(updatedProgram.name).to.eq("a brave new name"); + expect(updatedProgram.stakingTokenUrl).to.eq( + "https://new.domain" + ); + expect(updatedProgram.template).to.eq(program.template); + expect(updatedProgram.startTime).to.eq(program.startTime); + }); + }); + describe("BUT updates nothing", async () => { + it("THEN it throws", async () => { + await expect( + run("update-program", {program: preexistingProgram.address}) + ).to.be.rejectedWith("pass *either* --newName or --newUrl"); + }); + }); + }); }); it("WHEN adding it with the add-program task, AND omitting the template THEN it fails because the template is not optional", async () => { From 26685161f289a84894513485e99a7256e06257a2 Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Fri, 20 Jan 2023 15:09:25 -0300 Subject: [PATCH 6/8] throw when no optional parameters are passed fix throw message error --- tasks/aludel.ts | 6 +++++- test/deployments.ts | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tasks/aludel.ts b/tasks/aludel.ts index af9698be..f76a2be2 100644 --- a/tasks/aludel.ts +++ b/tasks/aludel.ts @@ -240,13 +240,17 @@ task("update-program", "update an already added template") )) as AludelFactory; const programData = await factory.programs(args.program); + if (args.newName.length == 0 && args.newUrl.length == 0) { + throw new Error("pass --newName and/or --newUrl"); + } + log(`updating program ${programData.name} on factory ${factoryAddress}`); if (args.newName) { log(`program's new name: ${args.newName}`); } if (args.newUrl) { - log(`program's new URL: ${args.newUrl}`); + log(`update URL ${programData.name} to ${args.newName}`); } await ( diff --git a/test/deployments.ts b/test/deployments.ts index e15874fc..bb90748c 100644 --- a/test/deployments.ts +++ b/test/deployments.ts @@ -196,8 +196,8 @@ describe("Aludel factory deployments", function () { describe("BUT updates nothing", async () => { it("THEN it throws", async () => { await expect( - run("update-program", {program: preexistingProgram.address}) - ).to.be.rejectedWith("pass *either* --newName or --newUrl"); + run("update-program", { program: preexistingProgram.address }) + ).to.be.rejectedWith("pass --newName and/or --newUrl"); }); }); }); From 96476e0d818bb90302eccdf44d67f421d7d71651 Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Thu, 19 Jan 2023 09:48:54 -0300 Subject: [PATCH 7/8] make log message more vebose yarn lint-ts --- tasks/aludel.ts | 2 +- test/deployments.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tasks/aludel.ts b/tasks/aludel.ts index f76a2be2..baab46f0 100644 --- a/tasks/aludel.ts +++ b/tasks/aludel.ts @@ -247,7 +247,7 @@ task("update-program", "update an already added template") log(`updating program ${programData.name} on factory ${factoryAddress}`); if (args.newName) { - log(`program's new name: ${args.newName}`); + log(`rename ${programData.name} to ${args.newName}`); } if (args.newUrl) { log(`update URL ${programData.name} to ${args.newName}`); diff --git a/test/deployments.ts b/test/deployments.ts index bb90748c..bfcfc550 100644 --- a/test/deployments.ts +++ b/test/deployments.ts @@ -143,13 +143,17 @@ describe("Aludel factory deployments", function () { beforeEach(async () => { await run("update-program", { program: preexistingProgram.address, - newName: "a brave new name" + newName: "a brave new name", }); }); it("THEN only the name is changed", async () => { - const updatedProgram = await factory.programs(preexistingProgram.address); + const updatedProgram = await factory.programs( + preexistingProgram.address + ); expect(updatedProgram.name).to.eq("a brave new name"); - expect(updatedProgram.stakingTokenUrl).to.eq(program.stakingTokenUrl); + expect(updatedProgram.stakingTokenUrl).to.eq( + program.stakingTokenUrl + ); expect(updatedProgram.template).to.eq(program.template); expect(updatedProgram.startTime).to.eq(program.startTime); }); From 632a0a615e01a5cd53f88df51fbbacc606629832 Mon Sep 17 00:00:00 2001 From: Ignacio Tirabasso Date: Thu, 19 Jan 2023 09:50:06 -0300 Subject: [PATCH 8/8] add Polygon RPC to env.example file --- .env.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.example b/.env.example index 79f0525d..8878ffdc 100644 --- a/.env.example +++ b/.env.example @@ -13,4 +13,6 @@ RINKEBY_URL= GOERLI_URL= ROPSTEN_URL= MUMBAI_URL= +POLYGON_URL= + REPORT_GAS=