diff --git a/Makefile b/Makefile index 94b023f4..3b875c90 100644 --- a/Makefile +++ b/Makefile @@ -23,5 +23,11 @@ coverage :; forge coverage snapshot :; forge clean && forge snapshot --optimize --optimize-runs 1000000 # Deployment -# use the "@" to hide the command from your shell -deploy-contract :; @forge script script/${contract}.s.sol:Deploy${contract} --rpc-url ${RPC_URL} --private-key ${PRIVATE_KEY} --broadcast --verify --etherscan-api-key ${ETHERSCAN_API_KEY} -vvvv \ No newline at end of file +deploy-ajnatoken: + eval MINT_TO_ADDRESS=${mintto} + forge script script/AjnaToken.s.sol:DeployAjnaToken \ + --rpc-url ${ETH_RPC_URL} --sender ${DEPLOY_ADDRESS} --keystore ${DEPLOY_KEY} --broadcast -vvv +deploy-grantfund: + eval AJNA_TOKEN=${ajna} + forge script script/GrantFund.s.sol:DeployGrantFund \ + --rpc-url ${ETH_RPC_URL} --sender ${DEPLOY_ADDRESS} --keystore ${DEPLOY_KEY} --broadcast -vvv diff --git a/README.md b/README.md index a3881e2e..947aa507 100644 --- a/README.md +++ b/README.md @@ -49,16 +49,43 @@ bash ./check-code-coverage.sh ``` ### Contract Deployment -Ensure the following env variables are set in your env file `.env` +Ensure the following env variables are in your `.env` file or exported into your environment. +| Environment Variable | Purpose | +|----------------------|---------| +| `DEPLOY_ADDRESS` | address from which you wish to deploy +| `DEPLOY_KEY` | path to the JSON keystore file for the deployment address +| `ETHERSCAN_API_KEY` | required to verify contracts +| `ETH_RPC_URL` | node on your target deployment network + +Here's an example: +``` +DEPLOY_ADDRESS=0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc +DEPLOY_KEY=~/hush/deployment.json +ETHERSCAN_API_KEY=55ORCKI875XKNO89475DNOCHDPINI54OFY +ETH_RPC_URL=http://127.0.0.1:8545 +``` + +You will be prompted for your key's password interactively. + +⚠ The `ETH_RPC_URL` you provide determines the deployment network for your contract. + +If you wish to deploy against an `anvil` or `ganache` endpoint, edit the `Makefile`, replacing `--keystore ${DEPLOY_KEY}` with `--private-key ${DEPLOY_PRIVATE_KEY}`. In your environment, set `DEPLOY_ADDRESS` to one of the pre-funded accounts and `DEPLOY_PRIVATE_KEY` to the unencrypted private key. + + +#### AJNA token +Deployment of the AJNA token requires an argument stating where minted tokens should be sent. AJNA has already been deployed to Goerli and Mainnet; see [AJNA_TOKEN.md](src/token/AJNA_TOKEN.md#ajna-token) for addresses. There is no reason to deploy the AJNA token to L2s or sidechains; see [MULTICHAIN_STRATEGY.md](MULTICHAIN_STRATEGY.md) for details. Since contract verification only works on Etherscan-supported networks, the `--verify` switch has been omitted. Upon deployment, minted tokens are transferred to a user-specified address which must be specified in make arguments. To run a new deployment on a test network or local testchain, run: ``` -PRIVATE_KEY = -ETHERSCAN_API_KEY = -MINT_TO_ADDRESS = +make deploy-ajnatoken mintto= ``` +Record the address of the token upon deployment. See [AJNA_TOKEN.md](src/token/AJNA_TOKEN.md#deployment) for validation. -Once the above variables are set run the following: -WARNING: THE RPC_URL PASSED IN WILL DETERMINE WHAT NETWORK YOUR CONTRACT IS DEPLOYED ON. +#### Grant Fund +Deployment of the Grant Coordination Fund requires an argument to specify the address of the AJNA token. Per requirements, the deployment script calculates the treasury size based upon a fixed percentage of AJNA token supply. + +Since contract source has not yet been made public, the `--verify` switch has been omitted. To deploy, run: ``` -make deploy-contract contract= RPC_URL= +make deploy-grantfund ajna= ``` + +See [GRANT_FUND.md](src/grants/GRANT_FUND.md#deployment) for next steps. \ No newline at end of file diff --git a/script/AjnaToken.s.sol b/script/AjnaToken.s.sol index 381fe46c..7078ac38 100644 --- a/script/AjnaToken.s.sol +++ b/script/AjnaToken.s.sol @@ -1,16 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.7; -import { Script } from "forge-std/Script.sol"; +import { Script } from "forge-std/Script.sol"; +import "forge-std/console.sol"; + import { AjnaToken } from "../src/token/AjnaToken.sol"; +import { IERC20 } from "@oz/token/ERC20/IERC20.sol"; contract DeployAjnaToken is Script { - function run() public { - vm.startBroadcast(); - - new AjnaToken(vm.envAddress("MINT_TO_ADDRESS")); + address mintTo = vm.envAddress("MINT_TO_ADDRESS"); + vm.startBroadcast(); + address ajna = address(new AjnaToken(mintTo)); vm.stopBroadcast(); + + console.log("AJNA token deployed to %s", ajna); + console.log("Minting %s AJNA token to %s", (IERC20(ajna)).totalSupply() / 1e18, mintTo); } } diff --git a/script/GrantFund.s.sol b/script/GrantFund.s.sol new file mode 100644 index 00000000..45d8a2fb --- /dev/null +++ b/script/GrantFund.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import { Script } from "forge-std/Script.sol"; +import "forge-std/console.sol"; + +import { IVotes } from "@oz/governance/utils/IVotes.sol"; +import { IERC20 } from "@oz/token/ERC20/IERC20.sol"; + +import { GrantFund } from "src/grants/GrantFund.sol"; +import { Maths } from "src/grants/libraries/Maths.sol"; + +contract DeployGrantFund is Script { + uint256 constant TREASURY_PCT_OF_AJNA_SUPPLY = 0.3 * 1e18; + + function run() public { + IERC20 ajna = IERC20(vm.envAddress("AJNA_TOKEN")); + console.log("Deploying GrantFund to chain with AJNA token address %s", address(ajna)); + + vm.startBroadcast(); + uint256 treasury = Maths.wmul(ajna.totalSupply(), TREASURY_PCT_OF_AJNA_SUPPLY); + address grantFund = address(new GrantFund(IVotes(address(ajna)), treasury)); + vm.stopBroadcast(); + + console.log("GrantFund deployed to %s", grantFund); + console.log("Please transfer %s AJNA (%s WAD) into the treasury", treasury / 1e18, treasury); + } +} diff --git a/src/grants/GRANT_FUND.md b/src/grants/GRANT_FUND.md index 481bee7c..9f947140 100644 --- a/src/grants/GRANT_FUND.md +++ b/src/grants/GRANT_FUND.md @@ -2,6 +2,11 @@ As a decentralized protocol with no external governance, Ajna requires a sustainable mechanism by which to coordinate ecosystem growth in a scalable and decentralized way. The grant coordination mechanism is premised upon the idea that the AJNA token has value from the buy and burn mechanism. Upon launch, the Ajna community will be given a fixed portion of the total AJNA token supply, which will be held and distributed by the Grant Coordination Fund. +| Deployment | Address | +| ---------: | ------- | +| Mainnet | (net yet deployed) | +| Goerli | [0xc9216387C7920C8a7b6C2cE4A44dEd5776a3B5B4](https://goerli.etherscan.io/address/0xc9216387C7920C8a7b6C2cE4A44dEd5776a3B5B4) | + ## Design The Grant Coordination Fund will distribute funds through the two sub-mechanisms defined below. It is based upon Openzeppelin's Governor contract. @@ -58,3 +63,24 @@ For more information, see the Ajna Protocol Whitepaper. *Tally* - https://docs.tally.xyz/user-guides/tally-contract-compatibility + + +## Deployment + +See [README.md](../../README.md) for instructions using the `Makefile` target. + +Output should confirm the AJNA token address, provid the GrantFund address, and the amount of AJNA which should be transferred to the GrantFund adress: +``` +== Logs == + Deploying GrantFund to chain with AJNA token address 0xaadebCF61AA7Da0573b524DE57c67aDa797D46c5 + GrantFund deployed to 0xc9216387C7920C8a7b6C2cE4A44dEd5776a3B5B4 + Please transfer 600000000 AJNA (600000000000000000000000000 WAD) into the treasury +``` + +Record the deployment address in your environment as `GRANTFUND_ADDRESS`. As requested, transfer the specified amount of AJNA tokens to the GrantFund address. WAD-scaled value was included in output for copy/paste convenience. + +To perform the transfer, set `TREASURY_ADDRESS` and `TREASURY_KEY` to the appropriate values and run the following: + +``` +cast send ${AJNA_TOKEN} "transfer(address,uint256)" ${GRANTFUND_ADDRESS} 600000000000000000000000000 --from ${TREASURY_ADDRESS} --keystore ${TREASURY_KEY} --rpc-url ${ETH_RPC_URL} +``` \ No newline at end of file diff --git a/src/token/AJNA_TOKEN.md b/src/token/AJNA_TOKEN.md index f73ef4f1..af356720 100644 --- a/src/token/AJNA_TOKEN.md +++ b/src/token/AJNA_TOKEN.md @@ -46,17 +46,16 @@ Ajna ERC20 Token contract ## Deployment -Configure environment with `ETH_RPC_URL` pointing to the target chain for deployment. Set `DEPLOY_ADDRESS` to the deployment address and `DEPLOY_KEY` to the JSON keystore file. If you want initial tokens minted to a different address than the deploying address, update constructor arguments accordingly. +See [README.md](../../README.md) for instructions using the `Makefile` target. -Run +Output should provide the token address, confirm the amount minted and where it was sent: ``` -forge create --rpc-url ${ETH_RPC_URL} \ - --keystore ${DEPLOY_KEY} src/AjnaToken.sol:AjnaToken \ - --constructor-args ${DEPLOY_ADDRESS} +== Logs == + AJNA token deployed to 0xef11D1c2aA48826D4c41e54ab82D1Ff5Ad8A64Ca + Minting 2000000000 AJNA token to 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 ``` -and interactively enter your password. Add `--verify` switch once repository has been made public. -Record the `Deployed to` address returned, exporting to your environment as `AJNA_TOKEN`. +Record the token address, exporting to your environment as `AJNA_TOKEN`. Run the following to validate AJNA token balance: ```