Skip to content

Commit

Permalink
fix and add readme
Browse files Browse the repository at this point in the history
  • Loading branch information
canercidam committed Jul 30, 2023
1 parent 61a69e6 commit dc10cd5
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 19 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"coverage": "yarn hardhat coverage --testfiles 'test/' --solcoverjs .solcover.js",
"lint": "npm run lint:solidity && npm run lint:javascript",
"lint:javascript": "eslint ./",
"test": "hardhat test"
"test": "hardhat test",
"unlock:propose": "node scripts/unlock-admin/propose.js"
},
"repository": {
"type": "git",
Expand Down
6 changes: 6 additions & 0 deletions scripts/unlock-admin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Unlock admin proposals

To create Unlock admin proposals:
1. Create a new proposal file (like in scripts/unlock-admin/example.yaml).
2. At the project root, do `npm run unlock:propose -- <proposal-file-path>`.
3. Follow the links in the output to verify that the proposals were created in Defender.
15 changes: 12 additions & 3 deletions scripts/unlock-admin/call.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,34 @@ function createUpgradeableLockAtVersion(initArgs, version) {
const args = [initArgs.lockCreator, initArgs.expirationDuration, initArgs.tokenAddress, initArgs.keyPrice, initArgs.maxNumberOfKeys, initArgs.lockName];
const data = contracts.publicLock.encodeFunctionData('initialize', args);
return {
function: contracts.unlock.getFunction('createUpgradeableLockAtVersion'),
func: simplify(contracts.unlock.getFunction('createUpgradeableLockAtVersion')),
inputs: [data, version],
};
}

function updateKeyPricing(keyPrice, tokenAddress) {
return {
function: contracts.unlock.getFunction('updateKeyPricing'),
func: simplify(contracts.publicLock.getFunction('updateKeyPricing')),
inputs: [keyPrice, tokenAddress],
};
}

function withdraw(tokenAddress, recipient, amount) {
return {
function: contracts.unlock.getFunction('withdraw'),
func: simplify(contracts.publicLock.getFunction('withdraw')),
inputs: [tokenAddress, recipient, amount],
};
}

function simplify(func) {
return {
name: func.name,
inputs: func.inputs.map((input) => {
return { name: input.name, type: input.type };
}),
};
}

module.exports = {
createUpgradeableLockAtVersion,
updateKeyPricing,
Expand Down
8 changes: 4 additions & 4 deletions scripts/unlock-admin/example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ config:
publicLock: '0xbC2B60393e81B1F5399977030ba4e2165A2e213A'

proposals:
- title: Deploy new PublicLock contract (Spam Detector)
- title: Deploy new PublicLock contract
description: To be used for one of the plans
contract: unlock
type: deploy
args:
version: 13
version: '13'
initArgs:
lockName: 'Spam Detector (FORT)'
lockCreator: '0x874B5d427b2d27F6Ea0ed3BCE4De454824AEC9cC' # this account manages the lock
tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon
keyPrice: '1000000000000000000' # enter in wei: example is 1 wei
expirationDuration: '1440' # in seconds
maxNumberOfKeys: '100' # set this only if necessary: defaults to unlimited
expirationDuration: '86400' # one day in seconds: expires every day
#maxNumberOfKeys: '100' # set this only if necessary: defaults to unlimited

- title: Update key pricing
description: Using a different price for the same token
Expand Down
37 changes: 26 additions & 11 deletions scripts/unlock-admin/propose.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,62 @@
const fs = require('fs');
require('dotenv').config();
const { AdminClient } = require('defender-admin-client');
const defenderAdmin = new AdminClient({ apiKey: process.env.DEFENDER_API_KEY, apiSecret: process.env.DEFENDER_API_SECRET });
const defenderAdmin = new AdminClient({
apiKey: process.env.DEFENDER_API_KEY,
apiSecret: process.env.DEFENDER_SECRET_KEY,
});
const jsyaml = require('js-yaml');
const { ethers } = require('ethers');

const call = require('./call');

async function main() {
const proposalFile = jsyaml.load(process.argv[2]);
const proposalFile = jsyaml.load(fs.readFileSync(process.argv[2], 'utf8'));
for (let i = 0; i < proposalFile.proposals.length; i++) {
const proposal = proposalFile.proposals[i];
await propose(proposalFile.config, proposal);
}
}

async function propose(config, proposal) {
const proposalCall = getCall(proposal);
const result = await defenderAdmin.createProposal({
const { func, inputs } = getCall(proposal);
const proposalParams = {
contract: {
address: config.contracts[proposal.contract],
network: config.network,
},
title: proposal.title,
description: proposal.description,
type: 'custom',
functionInterface: proposalCall.function,
functionInputs: proposalCall.inputs,
functionInterface: func,
functionInputs: inputs,
via: config.signer.address,
viaType: config.signer.type,
});
console.log(result.url);
};
const result = await defenderAdmin.createProposal(proposalParams);
console.log(`${proposal.title}: ${result.url}`);
}

function getCall(proposal) {
const { args } = proposal;
switch (proposal.type) {
case 'deploy':
return call.createUpgradeableLockAtVersion(proposal.initArgs, proposal.version);
if (!args.initArgs.maxNumberOfKeys) {
args.initArgs.maxNumberOfKeys = ethers.constants.MaxUint256.toString();
}
return call.createUpgradeableLockAtVersion(args.initArgs, args.version);

case 'updateKeyPricing':
return call.updateKeyPricing(proposal.keyPrice, proposal.tokenAddress);
return call.updateKeyPricing(args.keyPrice, args.tokenAddress);

case 'withdraw':
return call.withdraw(proposal.tokenAddress, proposal.recipient, proposal.amount);
return call.withdraw(args.tokenAddress, args.recipient, args.amount);

default:
throw `unknown proposal type ${proposal.type}`;
}
}

main().then(() => {
console.log('successfully created the proposal(s)!');
});

0 comments on commit dc10cd5

Please sign in to comment.