const { ethers, network } = require("hardhat"); const { time } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); const stakingAddr = "0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29"; const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce"; const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C"; async function getManyEth(addr) { await network.provider.send("hardhat_setBalance", [addr, "0x111166630153483537"]); } async function getPermitSignature(signer, tokenContract, spender, value, deadline) { const [nonce, name, version, chainId] = await Promise.all([ tokenContract.nonces(signer.address), tokenContract.name(), "1", tokenContract.chainID(), ]); const domain = { name, version, chainId, verifyingContract: tornAddr, }; const types = { Permit: [ { name: "owner", type: "address", }, { name: "spender", type: "address", }, { name: "value", type: "uint256", }, { name: "nonce", type: "uint256", }, { name: "deadline", type: "uint256", }, ], }; const values = { owner: signer.address, spender, value, nonce, deadline, }; const signature = await signer.signTypedData(domain, types, values); return ethers.Signature.from(signature); } async function resetStateBeforeProposal() { await network.provider.request({ method: "hardhat_reset", params: [ { forking: { jsonRpcUrl: config.networks.hardhat.forking.url, blockNumber: config.networks.hardhat.forking.blockNumber, }, }, ], }); } async function getTorn(signer) { return await ethers.getContractAt(require("./abi/torn.abi.json"), tornAddr, signer); } async function getEnsRegistry() { const ensAddr = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; return await ethers.getContractAt(require("./abi/ensRegistry.abi.json"), ensAddr); } async function getEnsResolver(ensName) { const ensRegistry = await getEnsRegistry(); const resolverAddr = await ensRegistry.resolver(ethers.namehash(ensName)); return await ethers.getContractAt(require("./abi/ensResolver.abi.json"), resolverAddr); } async function resolveAddr(ensName) { if (ethers.isAddress(ensName)) return ensName; const ensResolver = await getEnsResolver(ensName); return await ensResolver.addr(ethers.namehash(ensName)); } async function getProxyImplAddr(proxyAddr) { const implementation = await ethers.provider.getStorage( proxyAddr, "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", ); const [implementationAddr] = new ethers.AbiCoder().decode(["address"], implementation); return implementationAddr; } async function getGovernance(signer) { return await ethers.getContractAt(require("./abi/governance.abi.json"), governanceAddr, signer); } async function getAirdrop(airdropAddr, signer) { return await ethers.getContractAt(require("./abi/airdrop.abi.json"), airdropAddr, signer); } async function signerLockInGov(tornAmount, signer) { if (!signer) signer = (await ethers.getSigners())[0]; if (tornAmount == "quorum") tornAmount = await (await getGovernance()).QUORUM_VOTES(); const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr); const torn = await getTorn(governanceSigner); await torn.transfer(signer.address, tornAmount); await getManyEth(signer.address); const governance = await getGovernance(signer); const deadline = ethers.MaxUint256; const { v, r, s } = await getPermitSignature(signer, torn, governanceAddr, tornAmount, deadline); await governance.lock(signer.address, tornAmount, deadline, v, r, s); return signer; } async function executeNewProposal(proposalAddr) { const governance = await getGovernance(); const quorum = await governance.QUORUM_VOTES(); const stakerSigner = await signerLockInGov(quorum); const governanceContract = await getGovernance(stakerSigner); await governanceContract.propose(proposalAddr, ""); const proposalId = await governanceContract.proposalCount(); await time.increase(60 * 60); await governanceContract.castVote(proposalId, true); await time.increase(60 * 60 * 24 * 7 + 60); await getManyEth(stakerSigner.address); await governanceContract.execute(proposalId); await time.increase(60 * 60 * 24 * 4); await governanceContract.unlock(quorum); const torn = await getTorn(stakerSigner); await torn.transfer(governanceAddr, quorum); } async function deployAndExecuteProposal() { const recipientsFactory = await ethers.getContractFactory("AirdropRecipients"); const airdropRecipientsContract = await recipientsFactory.deploy(require("../data/airdropRecipients.json")); const recipientStorageAddr = await airdropRecipientsContract.getAddress(); const airdropFactory = await ethers.getContractFactory("SablierAirdrop"); const airdrop = await airdropFactory.deploy(); const airdropAddr = await airdrop.getAddress(); const proposalFactory = await ethers.getContractFactory("Proposal"); const proposal = await proposalFactory.deploy(airdropAddr, recipientStorageAddr); const deployedProposalAddr = await proposal.getAddress(); await executeNewProposal(deployedProposalAddr); const airdropContract = await getAirdrop(airdropAddr, await ethers.getImpersonatedSigner(governanceAddr)); return { airdropAddr, airdropContract, airdropRecipientsContract }; } module.exports = { resetStateBeforeProposal, deployAndExecuteProposal, getGovernance, getEnsRegistry, getEnsResolver, resolveAddr, getProxyImplAddr, governanceAddr, getManyEth, tornAddr, getTorn, stakingAddr, getPermitSignature, signerLockInGov, executeNewProposal, };