diff --git a/Makefile b/Makefile index 7465d9e..49a3595 100644 --- a/Makefile +++ b/Makefile @@ -37,4 +37,6 @@ deploy-grantfund: deploy-burnwrapper: eval AJNA_TOKEN=${ajna} forge script script/BurnWrapper.s.sol:DeployBurnWrapper \ - --rpc-url ${ETH_RPC_URL} --sender ${DEPLOY_ADDRESS} --keystore ${DEPLOY_KEY} --broadcast -vvv --verify \ No newline at end of file + --rpc-url ${ETH_RPC_URL} --sender ${DEPLOY_ADDRESS} --keystore ${DEPLOY_KEY} --broadcast -vvv --verify +deploy-grantfund-deployer: + forge create --rpc-url ${ETH_RPC_URL} --keystore ${DEPLOY_KEY} --verify src/grants/Deployer.sol:Deployer diff --git a/README.md b/README.md index d5232f3..a3e32df 100644 --- a/README.md +++ b/README.md @@ -83,3 +83,17 @@ make deploy-grantfund ajna= ``` See [GRANT_FUND.md](src/grants/GRANT_FUND.md#deployment) for next steps. + +#### Grant Fund deployer +Deployer contract can be used to deploy grant fund, fund treasury and start distribution in a single call to avoid someone starting a distribution without treasury. + +Steps to use Deployer contract to deploy grant Fund: +1. Deploy `Deployer` contract. +2. Approve `` `AJNA ` to `Deployer` contract from `treasury` address. +3. Call `deployGrantFund(address ajnaToken_, uint256 treasury_)` from `treasury` address to deploy grant fund and start distribution with treasury amount. +4. GrantFund can be verified using remix contract verification plugin, foundry or hardhat. + +To deploy Deployer contract, run: +``` +make deploy-grantfund-deployer +``` diff --git a/src/grants/Deployer.sol b/src/grants/Deployer.sol new file mode 100644 index 0000000..796c011 --- /dev/null +++ b/src/grants/Deployer.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import { IERC20 } from "@oz/token/ERC20/IERC20.sol"; + +import { GrantFund } from "./GrantFund.sol"; + +contract Deployer { + + error IncorrectTreasuryBalance(); + + error DistributionNotStarted(); + + GrantFund public grantFund; + + function deployGrantFund(address ajnaToken_, uint256 treasury_) public returns (GrantFund grantFund_) { + + // deploy grant Fund + grantFund_ = new GrantFund(ajnaToken_); + + // Approve ajna token to fund treasury + IERC20(ajnaToken_).approve(address(grantFund_), treasury_); + + // Transfer treasury ajna tokens to Deployer contract + IERC20(ajnaToken_).transferFrom(msg.sender, address(this), treasury_); + + // Fund treasury and start new distribution + grantFund_.fundTreasury(treasury_); + grantFund_.startNewDistributionPeriod(); + + // check treasury balance is correct + if(IERC20(ajnaToken_).balanceOf(address(grantFund_)) != treasury_) revert IncorrectTreasuryBalance(); + + // check new distribution started + if(grantFund_.getDistributionId() != 1) revert DistributionNotStarted(); + + grantFund = grantFund_; + } +} \ No newline at end of file diff --git a/test/unit/Deployer.t.sol b/test/unit/Deployer.t.sol new file mode 100644 index 0000000..6d0cd6f --- /dev/null +++ b/test/unit/Deployer.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +import { Test } from "@std/Test.sol"; + +import { Deployer } from "../../src/grants/Deployer.sol"; +import { GrantFund } from "../../src/grants/GrantFund.sol"; +import { TestAjnaToken } from "../utils/harness/TestAjnaToken.sol"; + +contract DeployerTest is Test { + + function testGrantFundDeployment() external { + address owner = makeAddr("owner"); + vm.startPrank(owner); + + uint256 treasury = 50_000_000 * 1e18; + + TestAjnaToken ajnaToken = new TestAjnaToken(); + ajnaToken.mint(owner, treasury); + + Deployer deployer = new Deployer(); + ajnaToken.approve(address(deployer), treasury); + + GrantFund grantFund = deployer.deployGrantFund(address(ajnaToken), treasury); + + assertEq(grantFund.getDistributionId(), 1); + + (,,,uint256 fundAvailable,,) = grantFund.getDistributionPeriodInfo(1); + + assertEq(grantFund.treasury(), treasury - fundAvailable); + + assertEq(fundAvailable, treasury * 3 / 100); + } +} \ No newline at end of file