Skip to content

Commit

Permalink
add proposal creation script
Browse files Browse the repository at this point in the history
  • Loading branch information
MrToph committed Dec 21, 2021
1 parent 8e89033 commit 850891e
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 8 deletions.
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1
ROPSTEN_URL=https://eth-ropsten.alchemyapi.io/v2/<YOUR ALCHEMY KEY>
PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1
RINKEBY_URL=https://eth-rinkeby.alchemyapi.io/v2/<YOUR ALCHEMY KEY>
PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
# Code4rena contracts


# Scripts

## Proposing transfers

```bash
# fill out example file for your network
cp .env.example .env
# create a batch transfers JSON file
# propose it
yarn hardhat propose --network polygon --json scripts/proposals/example.json
```
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'hardhat-gas-reporter';
import 'solidity-coverage';
import './scripts/deploy';
import './scripts/verify';
import './scripts/proposals/transfer';

dotenv.config();

Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"compile": "yarn hardhat compile",
"generate-merkle-root": "ts-node ./scripts/airdrop/generate-merkle-root.ts",
"generate-merkle-root:example": "ts-node ./scripts/airdrop/generate-merkle-root.ts -i ./scripts/airdrop/example.json -o resultExample.json",
"lint:check": "prettier --check '(contracts|interfaces|src|test|deployments)/**/*.(sol|json|ts)'",
"lint:write": "prettier -w '(contracts|interfaces|src|test|deployments)/**/*.(sol|json|ts)'"
"lint:check": "prettier --check '(contracts|interfaces|src|scripts|test|deployments)/**/*.(sol|json|ts)'",
"lint:write": "prettier -w '(contracts|interfaces|src|scripts|test|deployments)/**/*.(sol|json|ts)'"
},
"repository": {
"type": "git",
Expand All @@ -24,7 +24,8 @@
},
"homepage": "https://github.com/code-423n4/genesis#readme",
"dependencies": {
"hardhat": "2.7.0"
"hardhat": "2.7.0",
"lodash": "^4.17.21"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.3",
Expand All @@ -34,6 +35,7 @@
"@typechain/ethers-v5": "^7.0.1",
"@typechain/hardhat": "^2.3.0",
"@types/chai": "^4.2.21",
"@types/lodash": "^4.14.178",
"@types/mocha": "^9.0.0",
"@types/node": "^16.4.13",
"@typescript-eslint/eslint-plugin": "^4.29.1",
Expand Down
16 changes: 14 additions & 2 deletions scripts/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import {BigNumber as BN, constants} from 'ethers';
import {BigNumber, BigNumber as BN, constants} from 'ethers';
import {ONE_DAY, ONE_YEAR} from '../test/shared/Constants';
export const allConfigs: any = {

type Config = {
FREE_SUPPLY: BigNumber;
AIRDROP_SUPPLY: BigNumber;
CLAIMABLE_PROPORTION: number;
CLAIM_END_DATE: string;
VEST_DURATION: number;
MERKLE_ROOT: string;
TIMELOCK_DELAY: number;
EXPORT_FILENAME: string;
};

export const allConfigs: {[key: number]: Config} = {
// rinkeby
4: {
FREE_SUPPLY: BN.from(900).mul(1_000_000).mul(constants.WeiPerEther), // 900M
Expand Down
23 changes: 23 additions & 0 deletions scripts/proposals/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"token": "0xc1D2300f0065FC076c36F6D414a31A2949ca3027",
"transfers": [
{
"to": "0x0f4Aeb1847B7F1a735f4a5Af7E8C299b793c1a9A",
"amount": "1000000000000000000"
},
{
"to": "0x3Ab0029e1C4515134464b267557cB80A39902699",
"amount": "2000000000000000000"
},
{
"to": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"amount": "3000000000000000000"
},
{
"to": "0x0000000000000000000000000000000000000000",
"amount": "4000000000000000000"
}
]
}
]
91 changes: 91 additions & 0 deletions scripts/proposals/transfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {ethers, Signer} from 'ethers';
import fs from 'fs';
import {task} from 'hardhat/config';
import path from 'path';
import _ from 'lodash';
import {ArenaGovernor__factory, ArenaToken__factory} from '../../typechain';
import {allConfigs} from '../config';

let transferInterface = new ethers.utils.Interface([`function transfer(address to, uint256 amount)`]);
const getContracts = (signer: Signer, config: typeof allConfigs[0]) => {
const deploymentFilePath = path.join(`deployments`, config.EXPORT_FILENAME);
if (!fs.existsSync(deploymentFilePath)) throw new Error(`File '${path.resolve(deploymentFilePath)}' does not exist.`);

const contents = fs.readFileSync(deploymentFilePath, `utf8`);
let governorAddress;
let arenaAddress;
try {
({ governor: governorAddress, token: arenaAddress } = JSON.parse(contents));
} catch (error) {
throw new Error(`Cannot parse deployment config at '${path.resolve(deploymentFilePath)}'.`);
}
if (!governorAddress) throw new Error(`Deployment file did not include governor address '${deploymentFilePath}'.`);
if (!arenaAddress) throw new Error(`Deployment file did not include arena token address '${deploymentFilePath}'.`);

return { governor: ArenaGovernor__factory.connect(governorAddress, signer), arenaToken: ArenaToken__factory.connect(arenaAddress, signer) };
};

type BatchTransfer = {
token: string;
transfers: Array<{to: string; amount: string}>;
};
const getTransfers = (transferPath: string) => {
if (!fs.existsSync(transferPath)) throw new Error(`File '${path.resolve(transferPath)}' does not exist.`);

const contents = fs.readFileSync(transferPath, `utf8`);
let json;
try {
json = JSON.parse(contents);
} catch (error) {
throw new Error(`Cannot parse transfer JSON file at '${path.resolve(transferPath)}'.`);
}
if (!Array.isArray(json)) throw new Error(`Transfer file must be an array of batch transfers`);

return json as BatchTransfer[];
};

const toProposalPayload = (batchTransfer: BatchTransfer) => {
return batchTransfer.transfers.map((transfer) => ({
target: batchTransfer.token,
calldata: transferInterface.encodeFunctionData(`transfer`, [transfer.to, transfer.amount]),
value: `0`,
}));
};

task('propose', 'propose transfer')
.addOptionalParam('json', 'The path to batch transfer JSON file', `transfers.json`)
.setAction(async ({json}, hre) => {
const networkId = hre.network.config.chainId as number;
const [proposer] = await hre.ethers.getSigners();
const proposerAddress = await proposer.getAddress();
let config = allConfigs[networkId];
if (!config) throw new Error(`Unknown network ${hre.network.name} (${networkId})`);

const batchTransfers = _.flattenDeep(getTransfers(json).map(toProposalPayload));
const targets = batchTransfers.map(({target}) => target);
const values = batchTransfers.map(({value}) => value);
const calldatas = batchTransfers.map(({calldata}) => calldata);

const { governor, arenaToken } = getContracts(proposer, config);
console.log(`Proposer: ${proposerAddress}`);
console.log(`Governor: ${governor.address}`);
console.log(`Proposal Threshold: ${await governor.proposalThreshold()}`);
console.log(`Proposer Votes: ${await arenaToken.getVotes(proposerAddress)}`);

console.log(JSON.stringify(targets));
console.log(JSON.stringify(calldatas));

const tx = await governor['propose(address[],uint256[],bytes[],string)'](
targets,
values,
calldatas,
`Distribute tokens for contest #Test`
);
console.log(`proposal submitted: ${tx.hash}`);
console.log(`waiting for block inclusion ...`);
await tx.wait(1)
// TODO: query the transaction for the ProposalCreated event so we can get the proposalId

console.log(`transaction included - proposal created!`);
process.exit(0);
});
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,11 @@
"@types/level-errors" "*"
"@types/node" "*"

"@types/lodash@^4.14.178":
version "4.14.178"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8"
integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==

"@types/lru-cache@^5.1.0":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef"
Expand Down

0 comments on commit 850891e

Please sign in to comment.