├── .browserslistrc ├── public ├── _redirects ├── robots.txt ├── favicon.ico ├── img │ └── icons │ │ ├── favicon.ico │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── mstile-150x150.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-144x144.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── msapplication-icon-144x144.png │ │ ├── android-chrome-maskable-192x192.png │ │ ├── android-chrome-maskable-512x512.png │ │ ├── browserconfig.xml │ │ ├── site.webmanifest │ │ └── safari-pinned-tab.svg ├── index.html └── service-worker.js ├── .gitattributes ├── src ├── shims-vue-tabs.d.ts ├── assets │ ├── logo.png │ ├── smiling-face-with-horns.png │ └── logo.svg ├── shims-vue.d.ts ├── components │ ├── Web3Signin.vue │ └── MinionItem.vue ├── plugins │ └── vuetify.ts ├── shims-tsx.d.ts ├── views │ ├── About.vue │ ├── Home.vue │ ├── Ens.vue │ └── NewMinion.vue ├── router │ └── index.ts ├── main.ts ├── abi │ ├── moloch_v2_guildbank.json │ ├── minion.json │ ├── erc721.json │ ├── erc20.json │ ├── moloch_v1_pool.json │ ├── certnft.json │ ├── minion_subdomain_registrar.json │ ├── moloch_v1.json │ ├── ens_registrar.json │ └── uniswap_v2_router.json ├── registerServiceWorker.ts └── App.vue ├── .env-sample ├── cypress.json ├── babel.config.js ├── tests ├── e2e │ ├── .eslintrc.js │ ├── specs │ │ └── example.spec.js │ ├── support │ │ ├── index.js │ │ └── commands.js │ └── plugins │ │ └── index.js ├── unit │ └── example.spec.ts └── contracts │ ├── utils │ ├── types.ts │ ├── constants.ts │ └── utils.ts │ └── minion_integration.spec.ts ├── .vscode ├── extensions.json └── settings.json ├── vue.config.js ├── networks.js ├── CONTRIBUTORS.md ├── .gitignore ├── README.md ├── contracts ├── mock │ ├── RevertingMoloch.sol │ ├── TargetMock.sol │ └── Token.sol ├── moloch │ ├── oz │ │ ├── IERC20.sol │ │ ├── SafeMath.sol │ │ ├── LICENSE │ │ ├── ReentrancyGuard.sol │ │ └── ERC20.sol │ ├── tokens │ │ ├── Token.sol │ │ └── ClaimsToken.sol │ ├── MolochSummoner.sol │ └── test-helpers │ │ └── Submitter.sol └── Minion.sol ├── buidler.config.ts ├── .eslintrc.js ├── tsconfig.json └── package.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /src/shims-vue-tabs.d.ts: -------------------------------------------------------------------------------- 1 | declare module "vue-nav-tabs"; 2 | -------------------------------------------------------------------------------- /.env-sample: -------------------------------------------------------------------------------- 1 | VUE_APP_CHAIN_ID="42" 2 | VUE_APP_CHAIN="kovan" 3 | VUE_APP_INFURA= -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"] 3 | }; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.vue" { 2 | import Vue from "vue"; 3 | export default Vue; 4 | } 5 | -------------------------------------------------------------------------------- /public/img/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/favicon.ico -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/smiling-face-with-horns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/src/assets/smiling-face-with-horns.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/android-chrome-144x144.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-maskable-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/android-chrome-maskable-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-maskable-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raid-guild/moloch-minion/HEAD/public/img/icons/android-chrome-maskable-512x512.png -------------------------------------------------------------------------------- /tests/e2e/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ["cypress"], 3 | env: { 4 | mocha: true, 5 | "cypress/globals": true 6 | }, 7 | rules: { 8 | strict: "off" 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "juanblanco.solidity", 6 | "ms-vscode.vscode-typescript-tslint-plugin" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transpileDependencies: ["vuetify"], 3 | pwa: { 4 | workboxPluginMode: "InjectManifest", 5 | workboxOptions: { 6 | swSrc: "service-worker.js" 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/Web3Signin.vue: -------------------------------------------------------------------------------- 1 | 4 | 11 | -------------------------------------------------------------------------------- /networks.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | protocol: "http", 5 | host: "localhost", 6 | port: 8545, 7 | gas: 5000000, 8 | gasPrice: 5e9, 9 | networkId: "*" 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /src/plugins/vuetify.ts: -------------------------------------------------------------------------------- 1 | import "@fortawesome/fontawesome-free/css/all.css"; 2 | import Vue from "vue"; 3 | import Vuetify from "vuetify/lib"; 4 | 5 | Vue.use(Vuetify); 6 | 7 | export default new Vuetify({ 8 | icons: { 9 | iconfont: "fa" 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /tests/e2e/specs/example.spec.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe("My First Test", () => { 4 | it("Visits the app root url", () => { 5 | cy.visit("/"); 6 | cy.contains("h2", "Welcome to Your Vue.js + TypeScript dApp"); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /public/img/icons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from "vue"; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /public/img/icons/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-144x144.png", 7 | "sizes": "144x144", 8 | "type": "image/png" 9 | } 10 | ], 11 | "theme_color": "#ffffff", 12 | "background_color": "#ffffff", 13 | "display": "standalone" 14 | } 15 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | ## Special thanks for all the people who had helped this project so far: 4 | 5 | * [Dekan Brown](https://github.com/dekanbro) 6 | * [Wolflo](https://github.com/wolflo) 7 | * [Sam kuhlmann](https://github.com/skuhlmann) 8 | * [Tommy](https://github.com/proofoftom) 9 | * [Ven Gist](https://github.com/oovg) 10 | * [TomAFrench](https://github.com/TomAFrench) 11 | -------------------------------------------------------------------------------- /tests/unit/example.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { shallowMount } from "@vue/test-utils"; 3 | import HelloWorld from "@/components/HelloWorld.vue"; 4 | 5 | describe("HelloWorld.vue", () => { 6 | it("renders props.msg when passed", () => { 7 | const msg = "new message"; 8 | const wrapper = shallowMount(HelloWorld, { 9 | propsData: { msg } 10 | }); 11 | expect(wrapper.text()).to.include(msg); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | .env 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # Editor directories and files 19 | .idea 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | # Build specific files 27 | build 28 | cache 29 | .openzeppelin/.session 30 | .openzeppelin/dev-*.json 31 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll": true 4 | }, 5 | "editor.defaultFormatter": "esbenp.prettier-vscode", 6 | "eslint.packageManager": "yarn", 7 | "eslint.validate": [ 8 | "vue", 9 | "json", 10 | "javascript", 11 | "javascriptreact", 12 | "typescript", 13 | "typescriptreact" 14 | ], 15 | "solidity.compileUsingRemoteVersion": "0.6.3+commit.8dda9521", 16 | "solidity.packageDefaultDependenciesContractsDirectory": "" 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moloch Minion 2 | 3 | A contract that allows execution of arbitrary calls voted on by members of a Moloch DAO. 4 | 5 | ## Usage 6 | 7 | ### Install the dependencies 8 | ``` 9 | yarn 10 | ``` 11 | 12 | #### Compile and generate type definitions for contracts 13 | ``` 14 | yarn build:contracts 15 | ``` 16 | 17 | #### Run Waffle tests with stack traces 18 | ``` 19 | yarn test:contracts 20 | ``` 21 | 22 | #### Run web 23 | ``` 24 | yarn start:web 25 | ``` 26 | 27 | #### build web 28 | ``` 29 | yarn build:web 30 | ``` -------------------------------------------------------------------------------- /contracts/mock/RevertingMoloch.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract RevertingMoloch { 4 | address public depositToken; 5 | 6 | function submitProposal( 7 | address applicant, 8 | uint256 sharesRequested, 9 | uint256 lootRequested, 10 | uint256 tributeOffered, 11 | address tributeToken, 12 | uint256 paymentRequested, 13 | address paymentToken, 14 | string memory details 15 | ) public returns (uint256 proposalId) { 16 | revert(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | Artboard 46 2 | -------------------------------------------------------------------------------- /buidler.config.ts: -------------------------------------------------------------------------------- 1 | import { BuidlerConfig, usePlugin } from "@nomiclabs/buidler/config"; 2 | 3 | usePlugin("@nomiclabs/buidler-waffle"); 4 | usePlugin("buidler-typechain"); 5 | 6 | const config: BuidlerConfig = { 7 | paths: { 8 | artifacts: "./build/artifacts", 9 | tests: "./tests/contracts" 10 | }, 11 | solc: { 12 | version: "0.5.12", 13 | optimizer: { 14 | enabled: true, 15 | runs: 200 16 | } 17 | }, 18 | typechain: { 19 | outDir: "./build/types", 20 | target: "ethers" 21 | } 22 | }; 23 | 24 | export default config; 25 | -------------------------------------------------------------------------------- /tests/contracts/utils/types.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | 3 | interface Action { 4 | to: string; 5 | value: ethers.utils.BigNumber; 6 | data: string; 7 | description: string; 8 | proposalId: number; 9 | queueIndex: number; 10 | } 11 | 12 | interface Proposal { 13 | applicant: string; 14 | proposer: string; 15 | sharesRequested: number; 16 | lootRequested: number; 17 | tributeOffered: number; 18 | tributeToken: string; 19 | paymentRequested: number; 20 | paymentToken: string; 21 | details: string; 22 | } 23 | 24 | export { Action, Proposal }; 25 | -------------------------------------------------------------------------------- /contracts/mock/TargetMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract TargetMock { 4 | 5 | event Called( 6 | address indexed caller, 7 | uint indexed value, 8 | bytes data 9 | ); 10 | 11 | function fail() external payable { 12 | revert(); 13 | } 14 | 15 | function() external payable { 16 | // bytes memory data; 17 | // assembly{ 18 | // let _size := calldatasize 19 | // mstore(data, _size) 20 | // calldatacopy(add(data, 0x20), 0x00, size) 21 | // } 22 | // emit Called(msg.sender, msg.value, data); 23 | emit Called(msg.sender, msg.value, msg.data); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Moloch Minion 9 | 10 | 11 | 12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | "plugin:vue/essential", 8 | "eslint:recommended", 9 | "@vue/typescript/recommended", 10 | "@vue/prettier", 11 | "@vue/prettier/@typescript-eslint" 12 | ], 13 | parserOptions: { 14 | ecmaVersion: 2020 15 | }, 16 | rules: { 17 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off", 18 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off" 19 | }, 20 | overrides: [ 21 | { 22 | files: [ 23 | "**/__tests__/*.{j,t}s?(x)", 24 | "**/tests/unit/**/*.spec.{j,t}s?(x)" 25 | ], 26 | env: { 27 | mocha: true 28 | } 29 | } 30 | ] 31 | }; 32 | -------------------------------------------------------------------------------- /tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import "./commands"; 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /contracts/moloch/oz/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | interface IERC20 { 4 | function transfer(address to, uint256 value) external returns (bool); 5 | 6 | function approve(address spender, uint256 value) external returns (bool); 7 | 8 | function transferFrom(address from, address to, uint256 value) external returns (bool); 9 | 10 | function totalSupply() external view returns (uint256); 11 | 12 | function balanceOf(address who) external view returns (uint256); 13 | 14 | function allowance(address owner, address spender) external view returns (uint256); 15 | 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | 18 | event Approval(address indexed owner, address indexed spender, uint256 value); 19 | } 20 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /contracts/mock/Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "../moloch/oz/ERC20.sol"; 4 | 5 | contract Token is ERC20 { 6 | bool transfersEnabled = true; 7 | bool transfersReturningFalse = false; 8 | 9 | constructor(uint256 supply) public { 10 | _mint(msg.sender, supply); 11 | } 12 | 13 | function updateTransfersEnabled(bool enabled) external { 14 | transfersEnabled = enabled; 15 | } 16 | 17 | function updateTransfersReturningFalse(bool enabled) external { 18 | transfersReturningFalse = enabled; 19 | } 20 | 21 | function transfer(address to, uint256 value) public returns (bool) { 22 | if (transfersReturningFalse) { 23 | return false; 24 | } 25 | require(transfersEnabled); 26 | return super.transfer(to, value); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/moloch/tokens/Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "../oz/ERC20.sol"; 4 | 5 | contract Token is ERC20 { 6 | bool transfersEnabled = true; 7 | bool transfersReturningFalse = false; 8 | 9 | constructor(uint256 supply) public { 10 | _mint(msg.sender, supply); 11 | } 12 | 13 | function updateTransfersEnabled(bool enabled) external { 14 | transfersEnabled = enabled; 15 | } 16 | 17 | function updateTransfersReturningFalse(bool enabled) external { 18 | transfersReturningFalse = enabled; 19 | } 20 | 21 | function transfer(address to, uint256 value) public returns (bool) { 22 | if (transfersReturningFalse) { 23 | return false; 24 | } 25 | require(transfersEnabled); 26 | return super.transfer(to, value); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import VueRouter from "vue-router"; 3 | import Home from "../views/Home.vue"; 4 | import About from "../views/About.vue"; 5 | import NewMinion from "../views/NewMinion.vue"; 6 | import Ens from "../views/Ens.vue"; 7 | 8 | Vue.use(VueRouter); 9 | 10 | const routes = [ 11 | { 12 | path: "/about/:minion?", 13 | name: "About", 14 | component: About 15 | }, 16 | { 17 | path: "/new/:minion?", 18 | name: "New Minion", 19 | component: NewMinion 20 | }, 21 | { 22 | path: "/ens/:minion?", 23 | name: "ENS", 24 | component: Ens 25 | }, 26 | { 27 | path: "/:minion?", 28 | name: "Home", 29 | component: Home 30 | } 31 | ]; 32 | 33 | const router = new VueRouter({ 34 | mode: "history", 35 | base: process.env.BASE_URL, 36 | routes 37 | }); 38 | 39 | export default router; 40 | -------------------------------------------------------------------------------- /contracts/moloch/oz/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | library SafeMath { 4 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 5 | if (a == 0) { 6 | return 0; 7 | } 8 | 9 | uint256 c = a * b; 10 | require(c / a == b); 11 | 12 | return c; 13 | } 14 | 15 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 16 | 17 | require(b > 0); 18 | uint256 c = a / b; 19 | 20 | return c; 21 | } 22 | 23 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 24 | require(b <= a); 25 | uint256 c = a - b; 26 | 27 | return c; 28 | } 29 | 30 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 31 | uint256 c = a + b; 32 | require(c >= a); 33 | 34 | return c; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App.vue"; 3 | import "./registerServiceWorker"; 4 | import router from "./router"; 5 | import vuetify from "./plugins/vuetify"; 6 | import VueApollo from "vue-apollo"; 7 | import ApolloClient from "apollo-boost"; 8 | 9 | Vue.use(VueApollo); 10 | Vue.config.productionTip = false; 11 | 12 | const graphURI = { 13 | kovan: 14 | "https://api.thegraph.com/subgraphs/name/odyssy-automaton/daohaus-kovan", 15 | mainnet: "https://api.thegraph.com/subgraphs/name/odyssy-automaton/daohaus" 16 | }; 17 | 18 | const apolloClient = new ApolloClient({ 19 | // You should use an absolute URL here 20 | uri: process.env.VUE_APP_CHAIN === "kovan" ? graphURI.kovan : graphURI.mainnet 21 | }); 22 | 23 | const apolloProvider = new VueApollo({ 24 | defaultClient: apolloClient 25 | }); 26 | 27 | new Vue({ 28 | router, 29 | vuetify, 30 | apolloProvider, 31 | render: h => h(App) 32 | }).$mount("#app"); 33 | -------------------------------------------------------------------------------- /tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /tests/contracts/utils/constants.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "ethers"; 2 | 3 | const MINION_ACTION_DETAILS = 4 | '{"isMinion": true, "title":"MINION", "description":"'; 5 | 6 | const molochConfig = { 7 | PERIOD_DURATION_IN_SECONDS: 17280, 8 | VOTING_DURATON_IN_PERIODS: 35, 9 | GRACE_DURATON_IN_PERIODS: 35, 10 | PROPOSAL_DEPOSIT: 10, 11 | DILUTION_BOUND: 3, 12 | PROCESSING_REWARD: 1, 13 | TOKEN_SUPPLY: 10000 14 | }; 15 | 16 | const revertStrings = { 17 | none: "revert", 18 | INVALID_PROP_TARGET: "Minion::invalid _actionTo", 19 | INVALID_EXEC_TARGET: "Minion::invalid target", 20 | INVALID_EXEC_ID: "Minion::invalid _proposalId", 21 | IS_EXECUTED: "Minion::action executed", 22 | NO_ETH: "Minion::insufficient eth", 23 | NOT_PASSED: "Minion::proposal not passed", 24 | CALL_FAIL: "Minion::call failure" 25 | }; 26 | 27 | const systemConstants = { 28 | MINION_ACTION_DETAILS, 29 | molochConfig, 30 | revertStrings 31 | }; 32 | 33 | export default { ...ethers.constants, ...systemConstants }; 34 | -------------------------------------------------------------------------------- /tests/e2e/plugins/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | // https://docs.cypress.io/guides/guides/plugins-guide.html 3 | 4 | // if you need a custom webpack configuration you can uncomment the following import 5 | // and then use the `file:preprocessor` event 6 | // as explained in the cypress docs 7 | // https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples 8 | 9 | // /* eslint-disable import/no-extraneous-dependencies, global-require */ 10 | // const webpack = require('@cypress/webpack-preprocessor') 11 | 12 | module.exports = (on, config) => { 13 | // on('file:preprocessor', webpack({ 14 | // webpackOptions: require('@vue/cli-service/webpack.config'), 15 | // watchOptions: {} 16 | // })) 17 | 18 | return Object.assign({}, config, { 19 | fixturesFolder: "tests/e2e/fixtures", 20 | integrationFolder: "tests/e2e/specs", 21 | screenshotsFolder: "tests/e2e/screenshots", 22 | videosFolder: "tests/e2e/videos", 23 | supportFile: "tests/e2e/support/index.js" 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/abi/moloch_v2_guildbank.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "token", 7 | "type": "address" 8 | }, 9 | { 10 | "name": "receiver", 11 | "type": "address" 12 | }, 13 | { 14 | "name": "amount", 15 | "type": "uint256" 16 | } 17 | ], 18 | "name": "withdrawToken", 19 | "outputs": [ 20 | { 21 | "name": "", 22 | "type": "bool" 23 | } 24 | ], 25 | "payable": false, 26 | "stateMutability": "nonpayable", 27 | "type": "function" 28 | }, 29 | { 30 | "constant": false, 31 | "inputs": [ 32 | { 33 | "name": "receiver", 34 | "type": "address" 35 | }, 36 | { 37 | "name": "shares", 38 | "type": "uint256" 39 | }, 40 | { 41 | "name": "totalShares", 42 | "type": "uint256" 43 | }, 44 | { 45 | "name": "approvedTokens", 46 | "type": "address[]" 47 | } 48 | ], 49 | "name": "withdraw", 50 | "outputs": [ 51 | { 52 | "name": "", 53 | "type": "bool" 54 | } 55 | ], 56 | "payable": false, 57 | "stateMutability": "nonpayable", 58 | "type": "function" 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /src/registerServiceWorker.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from "register-service-worker"; 4 | 5 | if (process.env.NODE_ENV === "production") { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready() { 8 | console.log( 9 | "App is being served from cache by a service worker.\n" + 10 | "For more details, visit https://goo.gl/AFskqB" 11 | ); 12 | }, 13 | registered() { 14 | console.log("Service worker has been registered."); 15 | }, 16 | cached() { 17 | console.log("Content has been cached for offline use."); 18 | }, 19 | updatefound() { 20 | console.log("New content is downloading."); 21 | }, 22 | updated() { 23 | console.log("New content is available; Refresh..."); 24 | setTimeout(() => { 25 | window.location.reload(true); 26 | }, 1000); 27 | }, 28 | offline() { 29 | console.log( 30 | "No internet connection found. App is running in offline mode." 31 | ); 32 | }, 33 | error(error) { 34 | console.error("Error during service worker registration:", error); 35 | } 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /contracts/moloch/MolochSummoner.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.12; 2 | 3 | import "./Moloch.sol"; 4 | 5 | contract MolochSummoner { 6 | 7 | Moloch private M; 8 | 9 | address[] public Molochs; 10 | 11 | event Summoned(address indexed M, address indexed _summoner); 12 | 13 | function summonMoloch( 14 | address _summoner, 15 | address[] memory _approvedTokens, 16 | uint256 _periodDuration, 17 | uint256 _votingPeriodLength, 18 | uint256 _gracePeriodLength, 19 | uint256 _proposalDeposit, 20 | uint256 _dilutionBound, 21 | uint256 _processingReward) public { 22 | 23 | M = new Moloch( 24 | _summoner, 25 | _approvedTokens, 26 | _periodDuration, 27 | _votingPeriodLength, 28 | _gracePeriodLength, 29 | _proposalDeposit, 30 | _dilutionBound, 31 | _processingReward); 32 | 33 | Molochs.push(address(M)); 34 | 35 | emit Summoned(address(M), _summoner); 36 | 37 | } 38 | 39 | function getMolochCount() public view returns (uint256 MolochCount) { 40 | return Molochs.length; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/moloch/oz/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2019 zOS Global Limited 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 56 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "outDir": "dist", 12 | "resolveJsonModule": true, 13 | "allowSyntheticDefaultImports": true, 14 | "allowJs": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "typeRoots": [ 18 | "./node_modules/@types", 19 | "./node_modules/vuetify/types" 20 | ], 21 | "types": [ 22 | "webpack-env", 23 | "mocha", 24 | "chai", 25 | "vuetify" 26 | ], 27 | "paths": { 28 | "@/*": [ 29 | "src/*" 30 | ] 31 | }, 32 | "lib": [ 33 | "esnext", 34 | "dom", 35 | "dom.iterable", 36 | "scripthost" 37 | ] 38 | }, 39 | "include": [ 40 | "src/**/*.ts", 41 | "src/**/*.tsx", 42 | "src/**/*.vue", 43 | "tests/**/*.ts", 44 | "tests/**/*.tsx", 45 | "./scripts", 46 | "./test" 47 | ], 48 | "exclude": [ 49 | "node_modules" 50 | ], 51 | "files": [ 52 | "./buidler.config.ts", 53 | "./node_modules/@nomiclabs/buidler-ethers/src/type-extensions.d.ts", 54 | "./node_modules/@nomiclabs/buidler-waffle/src/type-extensions.d.ts", 55 | "node_modules/buidler-typechain/src/type-extensions.d.ts" 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /contracts/moloch/test-helpers/Submitter.sol: -------------------------------------------------------------------------------- 1 | // helper for testing moloch.submitProposal return value 2 | 3 | pragma solidity 0.5.12; 4 | 5 | import "../Moloch.sol"; 6 | 7 | contract Submitter { 8 | 9 | event Submit(uint256 proposalId); 10 | 11 | Moloch public moloch; // moloch contract reference 12 | 13 | constructor(address molochAddress) public { 14 | moloch = Moloch(molochAddress); 15 | } 16 | 17 | function submitProposal( 18 | address applicant, 19 | uint256 sharesRequested, 20 | uint256 lootRequested, 21 | uint256 tributeOffered, 22 | address tributeToken, 23 | uint256 paymentRequested, 24 | address paymentToken, 25 | string memory details 26 | ) public { 27 | uint256 proposalId = moloch.submitProposal( 28 | applicant, 29 | sharesRequested, 30 | lootRequested, 31 | tributeOffered, 32 | tributeToken, 33 | paymentRequested, 34 | paymentToken, 35 | details 36 | ); 37 | 38 | emit Submit(proposalId); 39 | } 40 | 41 | function submitWhitelistProposal( 42 | address tokenToWhitelist, 43 | string memory details 44 | ) public { 45 | uint256 proposalId = moloch.submitWhitelistProposal( 46 | tokenToWhitelist, 47 | details 48 | ); 49 | 50 | emit Submit(proposalId); 51 | } 52 | 53 | function submitGuildKickProposal( 54 | address memberToKick, 55 | string memory details 56 | ) public { 57 | uint256 proposalId = moloch.submitGuildKickProposal( 58 | memberToKick, 59 | details 60 | ); 61 | 62 | emit Submit(proposalId); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/components/MinionItem.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 57 | -------------------------------------------------------------------------------- /tests/contracts/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { ethereum } from "@nomiclabs/buidler"; 2 | import { ethers } from "ethers"; 3 | 4 | import { Action } from "./types"; 5 | import Constants from "./constants"; 6 | import { Moloch } from "../../../build/types/Moloch"; 7 | import { Minion } from "../../../build/types/Minion"; 8 | 9 | const molochConfig = Constants.molochConfig; 10 | 11 | function encodeDetailsString(actionDescription: string) { 12 | return Constants.MINION_ACTION_DETAILS + actionDescription + '"}'; 13 | } 14 | 15 | async function incProposalCount(moloch: Moloch, n: number) { 16 | const token = await moloch.depositToken(); 17 | for (let i = 0; i < n; i++) { 18 | await moloch.submitProposal(moloch.address, 0, 0, 0, token, 0, token, ""); 19 | } 20 | } 21 | 22 | async function bumpTime(periods: number, duration: number) { 23 | const timeIncrease = periods * duration; 24 | await ethereum.send("evm_increaseTime", [timeIncrease]); 25 | await ethereum.send("evm_mine", []); 26 | } 27 | 28 | async function passProposal(moloch: Moloch, action: Action) { 29 | await moloch.sponsorProposal(action.proposalId); 30 | await bumpTime(1, molochConfig.PERIOD_DURATION_IN_SECONDS); 31 | await moloch.submitVote(action.queueIndex, 1); 32 | await bumpTime( 33 | molochConfig.VOTING_DURATON_IN_PERIODS, 34 | molochConfig.PERIOD_DURATION_IN_SECONDS 35 | ); 36 | await bumpTime( 37 | molochConfig.GRACE_DURATON_IN_PERIODS, 38 | molochConfig.PERIOD_DURATION_IN_SECONDS 39 | ); 40 | await moloch.processProposal(action.queueIndex); 41 | } 42 | 43 | async function proposeAndPass(minion: Minion, moloch: Moloch, action: Action) { 44 | await minion.proposeAction( 45 | action.to, 46 | action.value, 47 | action.data, 48 | action.description 49 | ); 50 | await passProposal(moloch, action); 51 | } 52 | 53 | export default { 54 | bumpTime, 55 | passProposal, 56 | proposeAndPass, 57 | incProposalCount, 58 | encodeDetailsString 59 | }; 60 | -------------------------------------------------------------------------------- /public/service-worker.js: -------------------------------------------------------------------------------- 1 | // service-worker.js 2 | 3 | workbox.core.setCacheNameDetails({ prefix: "d4" }); 4 | //Change this value every time before you build 5 | const LATEST_VERSION = "v0.1"; 6 | self.addEventListener("activate", event => { 7 | console.log(`%c ${LATEST_VERSION} `, "background: #ddd; color: #0000ff"); 8 | if (caches) { 9 | caches.keys().then(arr => { 10 | arr.forEach(key => { 11 | if (key.indexOf("d4-precache") < -1) { 12 | caches 13 | .delete(key) 14 | .then(() => 15 | console.log( 16 | `%c Cleared ${key}`, 17 | "background: #333; color: #ff0000" 18 | ) 19 | ); 20 | } else { 21 | caches.open(key).then(cache => { 22 | cache.match("version").then(res => { 23 | if (!res) { 24 | cache.put( 25 | "version", 26 | new Response(LATEST_VERSION, { 27 | status: 200, 28 | statusText: LATEST_VERSION 29 | }) 30 | ); 31 | } else if (res.statusText !== LATEST_VERSION) { 32 | caches 33 | .delete(key) 34 | .then(() => 35 | console.log( 36 | `%c Cleared Cache ${LATEST_VERSION}`, 37 | "background: #333; color: #ff0000" 38 | ) 39 | ); 40 | } else 41 | console.log( 42 | `%c Great you have the latest version ${LATEST_VERSION}`, 43 | "background: #333; color: #00ff00" 44 | ); 45 | }); 46 | }); 47 | } 48 | }); 49 | }); 50 | } 51 | }); 52 | 53 | workbox.skipWaiting(); 54 | workbox.clientsClaim(); 55 | 56 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 57 | workbox.precaching.suppressWarnings(); 58 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 59 | -------------------------------------------------------------------------------- /contracts/moloch/oz/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @dev Contract module that helps prevent reentrant calls to a function. 5 | * 6 | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier 7 | * available, which can be applied to functions to make sure there are no nested 8 | * (reentrant) calls to them. 9 | * 10 | * Note that because there is a single `nonReentrant` guard, functions marked as 11 | * `nonReentrant` may not call one another. This can be worked around by making 12 | * those functions `private`, and then adding `external` `nonReentrant` entry 13 | * points to them. 14 | * 15 | * _Since v2.5.0:_ this module is now much more gas efficient, given net gas 16 | * metering changes introduced in the Istanbul hardfork. 17 | */ 18 | contract ReentrancyGuard { 19 | bool private _notEntered; 20 | 21 | constructor () internal { 22 | // Storing an initial non-zero value makes deployment a bit more 23 | // expensive, but in exchange the refund on every call to nonReentrant 24 | // will be lower in amount. Since refunds are capped to a percetange of 25 | // the total transaction's gas, it is best to keep them low in cases 26 | // like this one, to increase the likelihood of the full refund coming 27 | // into effect. 28 | _notEntered = true; 29 | } 30 | 31 | /** 32 | * @dev Prevents a contract from calling itself, directly or indirectly. 33 | * Calling a `nonReentrant` function from another `nonReentrant` 34 | * function is not supported. It is possible to prevent this from happening 35 | * by making the `nonReentrant` function external, and make it call a 36 | * `private` function that does the actual work. 37 | */ 38 | modifier nonReentrant() { 39 | // On the first call to nonReentrant, _notEntered will be true 40 | require(_notEntered, "ReentrancyGuard: reentrant call"); 41 | 42 | // Any calls to nonReentrant after this point will fail 43 | _notEntered = false; 44 | 45 | _; 46 | 47 | // By storing the original value once again, a refund is triggered (see 48 | // https://eips.ethereum.org/EIPS/eip-2200) 49 | _notEntered = true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /contracts/Minion.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.12; 2 | 3 | import "./moloch/Moloch.sol"; 4 | 5 | contract Minion { 6 | 7 | string public constant MINION_ACTION_DETAILS = '{"isMinion": true, "title":"MINION", "description":"'; 8 | 9 | Moloch public moloch; 10 | address public molochApprovedToken; 11 | mapping (uint256 => Action) public actions; // proposalId => Action 12 | 13 | struct Action { 14 | uint256 value; 15 | address to; 16 | address proposer; 17 | bool executed; 18 | bytes data; 19 | } 20 | 21 | event ActionProposed(uint256 proposalId, address proposer); 22 | event ActionExecuted(uint256 proposalId, address executor); 23 | 24 | constructor(address _moloch) public { 25 | moloch = Moloch(_moloch); 26 | molochApprovedToken = moloch.depositToken(); 27 | } 28 | 29 | // withdraw funds from the moloch 30 | function doWithdraw(address _token, uint256 _amount) public { 31 | moloch.withdrawBalance(_token, _amount); 32 | } 33 | 34 | function proposeAction( 35 | address _actionTo, 36 | uint256 _actionValue, 37 | bytes memory _actionData, 38 | string memory _description 39 | ) 40 | public 41 | returns (uint256) 42 | { 43 | // No calls to zero address allows us to check that Minion submitted 44 | // the proposal without getting the proposal struct from the moloch 45 | require(_actionTo != address(0), "Minion::invalid _actionTo"); 46 | 47 | string memory details = string(abi.encodePacked(MINION_ACTION_DETAILS, _description, '"}')); 48 | 49 | uint256 proposalId = moloch.submitProposal( 50 | address(this), 51 | 0, 52 | 0, 53 | 0, 54 | molochApprovedToken, 55 | 0, 56 | molochApprovedToken, 57 | details 58 | ); 59 | 60 | Action memory action = Action({ 61 | value: _actionValue, 62 | to: _actionTo, 63 | proposer: msg.sender, 64 | executed: false, 65 | data: _actionData 66 | }); 67 | 68 | actions[proposalId] = action; 69 | 70 | emit ActionProposed(proposalId, msg.sender); 71 | return proposalId; 72 | } 73 | 74 | function executeAction(uint256 _proposalId) public returns (bytes memory) { 75 | Action memory action = actions[_proposalId]; 76 | bool[6] memory flags = moloch.getProposalFlags(_proposalId); 77 | 78 | // minion did not submit this proposal 79 | require(action.to != address(0), "Minion::invalid _proposalId"); 80 | // can't call arbitrary functions on parent moloch 81 | require(action.to != address(moloch), "Minion::invalid target"); 82 | require(!action.executed, "Minion::action executed"); 83 | require(address(this).balance >= action.value, "Minion::insufficient eth"); 84 | require(flags[2], "Minion::proposal not passed"); 85 | 86 | // execute call 87 | actions[_proposalId].executed = true; 88 | (bool success, bytes memory retData) = action.to.call.value(action.value)(action.data); 89 | require(success, "Minion::call failure"); 90 | emit ActionExecuted(_proposalId, msg.sender); 91 | return retData; 92 | } 93 | 94 | function() external payable { } 95 | } 96 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "buidler-waffle-typechain-vue", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "yarn build:contracts && yarn build:web", 7 | "build:contracts": "buidler typechain", 8 | "build:web": "vue-cli-service build", 9 | "clean": "rm -rf cache && rm -rf build", 10 | "deploy:local": "yarn clean && yarn build:contracts", 11 | "lint": "vue-cli-service lint", 12 | "start:dev": "yarn deploy:local && vue-cli-service serve", 13 | "start:node": "buidler node", 14 | "start:web": "vue-cli-service serve", 15 | "test": "yarn test:contracts && yarn test:unit && yarn test:e2e", 16 | "test:contracts": "buidler test", 17 | "test:e2e": "vue-cli-service test:e2e", 18 | "test:unit": "vue-cli-service test:unit", 19 | "upgrade:local": "yarn build:contracts" 20 | }, 21 | "dependencies": { 22 | "@fortawesome/fontawesome-free": "^5.8.2", 23 | "@resolver-engine/core": "^0.3.3", 24 | "@walletconnect/web3-provider": "^1.0.0-beta.47", 25 | "abi-decoder": "^2.3.0", 26 | "apollo-boost": "^0.4.7", 27 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 28 | "core-js": "^3.6.4", 29 | "ethers": "^4.0.45", 30 | "graphql": "^14.0.0", 31 | "register-service-worker": "^1.6.2", 32 | "roboto-fontface": "*", 33 | "vue": "^2.6.11", 34 | "vue-apollo": "^3.0.3", 35 | "vue-class-component": "^7.2.2", 36 | "vue-property-decorator": "^8.3.0", 37 | "vue-router": "^3.1.5", 38 | "vuetify": "^2.2.11", 39 | "vuex": "^3.1.2", 40 | "web3modal": "^1.3.0" 41 | }, 42 | "devDependencies": { 43 | "@nomiclabs/buidler": "^1.2.0", 44 | "@nomiclabs/buidler-ethers": "^1.2.0", 45 | "@nomiclabs/buidler-waffle": "^1.2.0", 46 | "@types/chai": "^4.2.9", 47 | "@types/mocha": "^7.0.1", 48 | "@types/node": "^13.7.7", 49 | "@typescript-eslint/eslint-plugin": "^2.18.0", 50 | "@typescript-eslint/parser": "^2.18.0", 51 | "@vue/cli-plugin-babel": "~4.2.0", 52 | "@vue/cli-plugin-e2e-cypress": "~4.2.0", 53 | "@vue/cli-plugin-eslint": "~4.2.0", 54 | "@vue/cli-plugin-pwa": "~4.2.0", 55 | "@vue/cli-plugin-router": "~4.2.0", 56 | "@vue/cli-plugin-typescript": "~4.2.0", 57 | "@vue/cli-plugin-unit-mocha": "~4.2.0", 58 | "@vue/cli-plugin-vuex": "~4.2.0", 59 | "@vue/cli-service": "~4.2.0", 60 | "@vue/eslint-config-prettier": "^6.0.0", 61 | "@vue/eslint-config-typescript": "^5.0.1", 62 | "@vue/test-utils": "1.0.0-beta.31", 63 | "buidler-typechain": "^0.0.5", 64 | "chai": "^4.2.0", 65 | "eslint": "^6.7.2", 66 | "eslint-plugin-prettier": "^3.1.1", 67 | "eslint-plugin-vue": "^6.1.2", 68 | "ethereum-waffle": "^2.3.2", 69 | "lint-staged": "^9.5.0", 70 | "null-loader": "^3.0.0", 71 | "prettier": "^1.19.1", 72 | "sass": "^1.25.0", 73 | "sass-loader": "^8.0.2", 74 | "solc": "0.6.3", 75 | "ts-generator": "^0.0.8", 76 | "ts-node": "^8.6.2", 77 | "typechain": "^1.0.5", 78 | "typechain-target-ethers": "^1.0.3", 79 | "typechain-target-truffle": "^1.0.2", 80 | "typechain-target-web3-v1": "^1.0.4", 81 | "typescript": "^3.8.3", 82 | "vue-cli-plugin-vuetify": "~2.0.5", 83 | "vue-template-compiler": "^2.6.11", 84 | "vuetify-loader": "^1.3.0" 85 | }, 86 | "gitHooks": { 87 | "pre-commit": "lint-staged" 88 | }, 89 | "lint-staged": { 90 | "*.{js,jsx,vue,ts,tsx}": [ 91 | "vue-cli-service lint", 92 | "git add" 93 | ] 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/views/Ens.vue: -------------------------------------------------------------------------------- 1 | 72 | 73 | 145 | -------------------------------------------------------------------------------- /src/abi/minion.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_moloch", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "proposalId", 21 | "type": "uint256" 22 | }, 23 | { 24 | "indexed": false, 25 | "internalType": "address", 26 | "name": "executor", 27 | "type": "address" 28 | } 29 | ], 30 | "name": "ActionExecuted", 31 | "type": "event" 32 | }, 33 | { 34 | "anonymous": false, 35 | "inputs": [ 36 | { 37 | "indexed": false, 38 | "internalType": "uint256", 39 | "name": "proposalId", 40 | "type": "uint256" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "address", 45 | "name": "proposer", 46 | "type": "address" 47 | } 48 | ], 49 | "name": "ActionProposed", 50 | "type": "event" 51 | }, 52 | { 53 | "payable": true, 54 | "stateMutability": "payable", 55 | "type": "fallback" 56 | }, 57 | { 58 | "constant": true, 59 | "inputs": [], 60 | "name": "MINION_ACTION_DETAILS", 61 | "outputs": [ 62 | { 63 | "internalType": "string", 64 | "name": "", 65 | "type": "string" 66 | } 67 | ], 68 | "payable": false, 69 | "stateMutability": "view", 70 | "type": "function" 71 | }, 72 | { 73 | "constant": true, 74 | "inputs": [ 75 | { 76 | "internalType": "uint256", 77 | "name": "", 78 | "type": "uint256" 79 | } 80 | ], 81 | "name": "actions", 82 | "outputs": [ 83 | { 84 | "internalType": "uint256", 85 | "name": "value", 86 | "type": "uint256" 87 | }, 88 | { 89 | "internalType": "address", 90 | "name": "to", 91 | "type": "address" 92 | }, 93 | { 94 | "internalType": "address", 95 | "name": "proposer", 96 | "type": "address" 97 | }, 98 | { 99 | "internalType": "bool", 100 | "name": "executed", 101 | "type": "bool" 102 | }, 103 | { 104 | "internalType": "bytes", 105 | "name": "data", 106 | "type": "bytes" 107 | } 108 | ], 109 | "payable": false, 110 | "stateMutability": "view", 111 | "type": "function" 112 | }, 113 | { 114 | "constant": false, 115 | "inputs": [ 116 | { 117 | "internalType": "address", 118 | "name": "_token", 119 | "type": "address" 120 | }, 121 | { 122 | "internalType": "uint256", 123 | "name": "_amount", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "doWithdraw", 128 | "outputs": [], 129 | "payable": false, 130 | "stateMutability": "nonpayable", 131 | "type": "function" 132 | }, 133 | { 134 | "constant": false, 135 | "inputs": [ 136 | { 137 | "internalType": "uint256", 138 | "name": "_proposalId", 139 | "type": "uint256" 140 | } 141 | ], 142 | "name": "executeAction", 143 | "outputs": [ 144 | { 145 | "internalType": "bytes", 146 | "name": "", 147 | "type": "bytes" 148 | } 149 | ], 150 | "payable": false, 151 | "stateMutability": "nonpayable", 152 | "type": "function" 153 | }, 154 | { 155 | "constant": true, 156 | "inputs": [], 157 | "name": "moloch", 158 | "outputs": [ 159 | { 160 | "internalType": "contract Moloch", 161 | "name": "", 162 | "type": "address" 163 | } 164 | ], 165 | "payable": false, 166 | "stateMutability": "view", 167 | "type": "function" 168 | }, 169 | { 170 | "constant": true, 171 | "inputs": [], 172 | "name": "molochApprovedToken", 173 | "outputs": [ 174 | { 175 | "internalType": "address", 176 | "name": "", 177 | "type": "address" 178 | } 179 | ], 180 | "payable": false, 181 | "stateMutability": "view", 182 | "type": "function" 183 | }, 184 | { 185 | "constant": false, 186 | "inputs": [ 187 | { 188 | "internalType": "address", 189 | "name": "_actionTo", 190 | "type": "address" 191 | }, 192 | { 193 | "internalType": "uint256", 194 | "name": "_actionValue", 195 | "type": "uint256" 196 | }, 197 | { 198 | "internalType": "bytes", 199 | "name": "_actionData", 200 | "type": "bytes" 201 | }, 202 | { 203 | "internalType": "string", 204 | "name": "_description", 205 | "type": "string" 206 | } 207 | ], 208 | "name": "proposeAction", 209 | "outputs": [ 210 | { 211 | "internalType": "uint256", 212 | "name": "", 213 | "type": "uint256" 214 | } 215 | ], 216 | "payable": false, 217 | "stateMutability": "nonpayable", 218 | "type": "function" 219 | } 220 | ] -------------------------------------------------------------------------------- /src/abi/erc721.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [ 5 | { 6 | "name": "_tokenId", 7 | "type": "uint256" 8 | } 9 | ], 10 | "name": "getApproved", 11 | "outputs": [ 12 | { 13 | "name": "", 14 | "type": "address" 15 | } 16 | ], 17 | "payable": false, 18 | "stateMutability": "view", 19 | "type": "function" 20 | }, 21 | { 22 | "constant": false, 23 | "inputs": [ 24 | { 25 | "name": "_approved", 26 | "type": "address" 27 | }, 28 | { 29 | "name": "_tokenId", 30 | "type": "uint256" 31 | } 32 | ], 33 | "name": "approve", 34 | "outputs": [], 35 | "payable": true, 36 | "stateMutability": "payable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": false, 41 | "inputs": [ 42 | { 43 | "name": "_from", 44 | "type": "address" 45 | }, 46 | { 47 | "name": "_to", 48 | "type": "address" 49 | }, 50 | { 51 | "name": "_tokenId", 52 | "type": "uint256" 53 | } 54 | ], 55 | "name": "transferFrom", 56 | "outputs": [], 57 | "payable": true, 58 | "stateMutability": "payable", 59 | "type": "function" 60 | }, 61 | { 62 | "constant": false, 63 | "inputs": [ 64 | { 65 | "name": "_from", 66 | "type": "address" 67 | }, 68 | { 69 | "name": "_to", 70 | "type": "address" 71 | }, 72 | { 73 | "name": "_tokenId", 74 | "type": "uint256" 75 | } 76 | ], 77 | "name": "safeTransferFrom", 78 | "outputs": [], 79 | "payable": true, 80 | "stateMutability": "payable", 81 | "type": "function" 82 | }, 83 | { 84 | "constant": true, 85 | "inputs": [ 86 | { 87 | "name": "_tokenId", 88 | "type": "uint256" 89 | } 90 | ], 91 | "name": "ownerOf", 92 | "outputs": [ 93 | { 94 | "name": "", 95 | "type": "address" 96 | } 97 | ], 98 | "payable": false, 99 | "stateMutability": "view", 100 | "type": "function" 101 | }, 102 | { 103 | "constant": true, 104 | "inputs": [ 105 | { 106 | "name": "_owner", 107 | "type": "address" 108 | } 109 | ], 110 | "name": "balanceOf", 111 | "outputs": [ 112 | { 113 | "name": "", 114 | "type": "uint256" 115 | } 116 | ], 117 | "payable": false, 118 | "stateMutability": "view", 119 | "type": "function" 120 | }, 121 | { 122 | "constant": false, 123 | "inputs": [ 124 | { 125 | "name": "_operator", 126 | "type": "address" 127 | }, 128 | { 129 | "name": "_approved", 130 | "type": "bool" 131 | } 132 | ], 133 | "name": "setApprovalForAll", 134 | "outputs": [], 135 | "payable": false, 136 | "stateMutability": "nonpayable", 137 | "type": "function" 138 | }, 139 | { 140 | "constant": false, 141 | "inputs": [ 142 | { 143 | "name": "_from", 144 | "type": "address" 145 | }, 146 | { 147 | "name": "_to", 148 | "type": "address" 149 | }, 150 | { 151 | "name": "_tokenId", 152 | "type": "uint256" 153 | }, 154 | { 155 | "name": "data", 156 | "type": "bytes" 157 | } 158 | ], 159 | "name": "safeTransferFrom", 160 | "outputs": [], 161 | "payable": true, 162 | "stateMutability": "payable", 163 | "type": "function" 164 | }, 165 | { 166 | "constant": true, 167 | "inputs": [ 168 | { 169 | "name": "_owner", 170 | "type": "address" 171 | }, 172 | { 173 | "name": "_operator", 174 | "type": "address" 175 | } 176 | ], 177 | "name": "isApprovedForAll", 178 | "outputs": [ 179 | { 180 | "name": "", 181 | "type": "bool" 182 | } 183 | ], 184 | "payable": false, 185 | "stateMutability": "view", 186 | "type": "function" 187 | }, 188 | { 189 | "anonymous": false, 190 | "inputs": [ 191 | { 192 | "indexed": true, 193 | "name": "_from", 194 | "type": "address" 195 | }, 196 | { 197 | "indexed": true, 198 | "name": "_to", 199 | "type": "address" 200 | }, 201 | { 202 | "indexed": true, 203 | "name": "_tokenId", 204 | "type": "uint256" 205 | } 206 | ], 207 | "name": "Transfer", 208 | "type": "event" 209 | }, 210 | { 211 | "anonymous": false, 212 | "inputs": [ 213 | { 214 | "indexed": true, 215 | "name": "_owner", 216 | "type": "address" 217 | }, 218 | { 219 | "indexed": true, 220 | "name": "_approved", 221 | "type": "address" 222 | }, 223 | { 224 | "indexed": true, 225 | "name": "_tokenId", 226 | "type": "uint256" 227 | } 228 | ], 229 | "name": "Approval", 230 | "type": "event" 231 | }, 232 | { 233 | "anonymous": false, 234 | "inputs": [ 235 | { 236 | "indexed": true, 237 | "name": "_owner", 238 | "type": "address" 239 | }, 240 | { 241 | "indexed": true, 242 | "name": "_operator", 243 | "type": "address" 244 | }, 245 | { 246 | "indexed": false, 247 | "name": "_approved", 248 | "type": "bool" 249 | } 250 | ], 251 | "name": "ApprovalForAll", 252 | "type": "event" 253 | } 254 | ] 255 | -------------------------------------------------------------------------------- /src/abi/erc20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "name", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "string" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [ 19 | { 20 | "name": "_spender", 21 | "type": "address" 22 | }, 23 | { 24 | "name": "_value", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "approve", 29 | "outputs": [ 30 | { 31 | "name": "", 32 | "type": "bool" 33 | } 34 | ], 35 | "payable": false, 36 | "stateMutability": "nonpayable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": true, 41 | "inputs": [], 42 | "name": "totalSupply", 43 | "outputs": [ 44 | { 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "payable": false, 50 | "stateMutability": "view", 51 | "type": "function" 52 | }, 53 | { 54 | "constant": false, 55 | "inputs": [ 56 | { 57 | "name": "_from", 58 | "type": "address" 59 | }, 60 | { 61 | "name": "_to", 62 | "type": "address" 63 | }, 64 | { 65 | "name": "_value", 66 | "type": "uint256" 67 | } 68 | ], 69 | "name": "transferFrom", 70 | "outputs": [ 71 | { 72 | "name": "", 73 | "type": "bool" 74 | } 75 | ], 76 | "payable": false, 77 | "stateMutability": "nonpayable", 78 | "type": "function" 79 | }, 80 | { 81 | "constant": true, 82 | "inputs": [], 83 | "name": "decimals", 84 | "outputs": [ 85 | { 86 | "name": "", 87 | "type": "uint8" 88 | } 89 | ], 90 | "payable": false, 91 | "stateMutability": "view", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [ 97 | { 98 | "name": "_owner", 99 | "type": "address" 100 | } 101 | ], 102 | "name": "balanceOf", 103 | "outputs": [ 104 | { 105 | "name": "balance", 106 | "type": "uint256" 107 | } 108 | ], 109 | "payable": false, 110 | "stateMutability": "view", 111 | "type": "function" 112 | }, 113 | { 114 | "constant": true, 115 | "inputs": [], 116 | "name": "symbol", 117 | "outputs": [ 118 | { 119 | "name": "", 120 | "type": "string" 121 | } 122 | ], 123 | "payable": false, 124 | "stateMutability": "view", 125 | "type": "function" 126 | }, 127 | { 128 | "constant": false, 129 | "inputs": [ 130 | { 131 | "name": "_to", 132 | "type": "address" 133 | }, 134 | { 135 | "name": "_value", 136 | "type": "uint256" 137 | } 138 | ], 139 | "name": "transfer", 140 | "outputs": [ 141 | { 142 | "name": "", 143 | "type": "bool" 144 | } 145 | ], 146 | "payable": false, 147 | "stateMutability": "nonpayable", 148 | "type": "function" 149 | }, 150 | { 151 | "constant": true, 152 | "inputs": [ 153 | { 154 | "name": "_owner", 155 | "type": "address" 156 | }, 157 | { 158 | "name": "_spender", 159 | "type": "address" 160 | } 161 | ], 162 | "name": "allowance", 163 | "outputs": [ 164 | { 165 | "name": "", 166 | "type": "uint256" 167 | } 168 | ], 169 | "payable": false, 170 | "stateMutability": "view", 171 | "type": "function" 172 | }, 173 | { 174 | "payable": true, 175 | "stateMutability": "payable", 176 | "type": "fallback" 177 | }, 178 | { 179 | "anonymous": false, 180 | "inputs": [ 181 | { 182 | "indexed": true, 183 | "name": "owner", 184 | "type": "address" 185 | }, 186 | { 187 | "indexed": true, 188 | "name": "spender", 189 | "type": "address" 190 | }, 191 | { 192 | "indexed": false, 193 | "name": "value", 194 | "type": "uint256" 195 | } 196 | ], 197 | "name": "Approval", 198 | "type": "event" 199 | }, 200 | { 201 | "anonymous": false, 202 | "inputs": [ 203 | { 204 | "indexed": true, 205 | "name": "from", 206 | "type": "address" 207 | }, 208 | { 209 | "indexed": true, 210 | "name": "to", 211 | "type": "address" 212 | }, 213 | { 214 | "indexed": false, 215 | "name": "value", 216 | "type": "uint256" 217 | } 218 | ], 219 | "name": "Transfer", 220 | "type": "event" 221 | } 222 | ] 223 | -------------------------------------------------------------------------------- /src/abi/moloch_v1_pool.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "sharesToBurn", 7 | "type": "uint256" 8 | } 9 | ], 10 | "name": "withdraw", 11 | "outputs": [], 12 | "payable": false, 13 | "stateMutability": "nonpayable", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [ 19 | { 20 | "name": "newKeepers", 21 | "type": "address[]" 22 | } 23 | ], 24 | "name": "addKeepers", 25 | "outputs": [], 26 | "payable": false, 27 | "stateMutability": "nonpayable", 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "currentProposalIndex", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "uint256" 38 | } 39 | ], 40 | "payable": false, 41 | "stateMutability": "view", 42 | "type": "function" 43 | }, 44 | { 45 | "constant": true, 46 | "inputs": [], 47 | "name": "moloch", 48 | "outputs": [ 49 | { 50 | "name": "", 51 | "type": "address" 52 | } 53 | ], 54 | "payable": false, 55 | "stateMutability": "view", 56 | "type": "function" 57 | }, 58 | { 59 | "constant": true, 60 | "inputs": [], 61 | "name": "totalPoolShares", 62 | "outputs": [ 63 | { 64 | "name": "", 65 | "type": "uint256" 66 | } 67 | ], 68 | "payable": false, 69 | "stateMutability": "view", 70 | "type": "function" 71 | }, 72 | { 73 | "constant": false, 74 | "inputs": [ 75 | { 76 | "name": "initialTokens", 77 | "type": "uint256" 78 | }, 79 | { 80 | "name": "initialPoolShares", 81 | "type": "uint256" 82 | } 83 | ], 84 | "name": "activate", 85 | "outputs": [], 86 | "payable": false, 87 | "stateMutability": "nonpayable", 88 | "type": "function" 89 | }, 90 | { 91 | "constant": false, 92 | "inputs": [ 93 | { 94 | "name": "sharesToBurn", 95 | "type": "uint256" 96 | }, 97 | { 98 | "name": "recipient", 99 | "type": "address" 100 | } 101 | ], 102 | "name": "keeperWithdraw", 103 | "outputs": [], 104 | "payable": false, 105 | "stateMutability": "nonpayable", 106 | "type": "function" 107 | }, 108 | { 109 | "constant": false, 110 | "inputs": [ 111 | { 112 | "name": "toIndex", 113 | "type": "uint256" 114 | } 115 | ], 116 | "name": "sync", 117 | "outputs": [], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "constant": false, 124 | "inputs": [ 125 | { 126 | "name": "tokenAmount", 127 | "type": "uint256" 128 | } 129 | ], 130 | "name": "deposit", 131 | "outputs": [], 132 | "payable": false, 133 | "stateMutability": "nonpayable", 134 | "type": "function" 135 | }, 136 | { 137 | "constant": true, 138 | "inputs": [], 139 | "name": "approvedToken", 140 | "outputs": [ 141 | { 142 | "name": "", 143 | "type": "address" 144 | } 145 | ], 146 | "payable": false, 147 | "stateMutability": "view", 148 | "type": "function" 149 | }, 150 | { 151 | "constant": true, 152 | "inputs": [ 153 | { 154 | "name": "", 155 | "type": "address" 156 | } 157 | ], 158 | "name": "donors", 159 | "outputs": [ 160 | { 161 | "name": "shares", 162 | "type": "uint256" 163 | } 164 | ], 165 | "payable": false, 166 | "stateMutability": "view", 167 | "type": "function" 168 | }, 169 | { 170 | "constant": false, 171 | "inputs": [ 172 | { 173 | "name": "keepersToRemove", 174 | "type": "address[]" 175 | } 176 | ], 177 | "name": "removeKeepers", 178 | "outputs": [], 179 | "payable": false, 180 | "stateMutability": "nonpayable", 181 | "type": "function" 182 | }, 183 | { 184 | "inputs": [ 185 | { 186 | "name": "_moloch", 187 | "type": "address" 188 | } 189 | ], 190 | "payable": false, 191 | "stateMutability": "nonpayable", 192 | "type": "constructor" 193 | }, 194 | { 195 | "anonymous": false, 196 | "inputs": [ 197 | { 198 | "indexed": false, 199 | "name": "currentProposalIndex", 200 | "type": "uint256" 201 | } 202 | ], 203 | "name": "Sync", 204 | "type": "event" 205 | }, 206 | { 207 | "anonymous": false, 208 | "inputs": [ 209 | { 210 | "indexed": false, 211 | "name": "donor", 212 | "type": "address" 213 | }, 214 | { 215 | "indexed": false, 216 | "name": "sharesMinted", 217 | "type": "uint256" 218 | }, 219 | { 220 | "indexed": false, 221 | "name": "tokensDeposited", 222 | "type": "uint256" 223 | } 224 | ], 225 | "name": "Deposit", 226 | "type": "event" 227 | }, 228 | { 229 | "anonymous": false, 230 | "inputs": [ 231 | { 232 | "indexed": false, 233 | "name": "donor", 234 | "type": "address" 235 | }, 236 | { 237 | "indexed": false, 238 | "name": "sharesBurned", 239 | "type": "uint256" 240 | } 241 | ], 242 | "name": "Withdraw", 243 | "type": "event" 244 | }, 245 | { 246 | "anonymous": false, 247 | "inputs": [ 248 | { 249 | "indexed": false, 250 | "name": "donor", 251 | "type": "address" 252 | }, 253 | { 254 | "indexed": false, 255 | "name": "sharesBurned", 256 | "type": "uint256" 257 | }, 258 | { 259 | "indexed": false, 260 | "name": "keeper", 261 | "type": "address" 262 | } 263 | ], 264 | "name": "KeeperWithdraw", 265 | "type": "event" 266 | }, 267 | { 268 | "anonymous": false, 269 | "inputs": [ 270 | { 271 | "indexed": false, 272 | "name": "donor", 273 | "type": "address" 274 | }, 275 | { 276 | "indexed": false, 277 | "name": "addedKeepers", 278 | "type": "address[]" 279 | } 280 | ], 281 | "name": "AddKeepers", 282 | "type": "event" 283 | }, 284 | { 285 | "anonymous": false, 286 | "inputs": [ 287 | { 288 | "indexed": false, 289 | "name": "donor", 290 | "type": "address" 291 | }, 292 | { 293 | "indexed": false, 294 | "name": "removedKeepers", 295 | "type": "address[]" 296 | } 297 | ], 298 | "name": "RemoveKeepers", 299 | "type": "event" 300 | }, 301 | { 302 | "anonymous": false, 303 | "inputs": [ 304 | { 305 | "indexed": false, 306 | "name": "sharesToMint", 307 | "type": "uint256" 308 | }, 309 | { 310 | "indexed": false, 311 | "name": "recipient", 312 | "type": "address" 313 | }, 314 | { 315 | "indexed": false, 316 | "name": "totalPoolShares", 317 | "type": "uint256" 318 | } 319 | ], 320 | "name": "SharesMinted", 321 | "type": "event" 322 | }, 323 | { 324 | "anonymous": false, 325 | "inputs": [ 326 | { 327 | "indexed": false, 328 | "name": "sharesToBurn", 329 | "type": "uint256" 330 | }, 331 | { 332 | "indexed": false, 333 | "name": "recipient", 334 | "type": "address" 335 | }, 336 | { 337 | "indexed": false, 338 | "name": "totalPoolShares", 339 | "type": "uint256" 340 | } 341 | ], 342 | "name": "SharesBurned", 343 | "type": "event" 344 | } 345 | ] 346 | -------------------------------------------------------------------------------- /contracts/moloch/oz/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "./IERC20.sol"; 4 | import "./SafeMath.sol"; 5 | 6 | /** 7 | * @title Standard ERC20 token 8 | * 9 | * @dev Implementation of the basic standard token. 10 | * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md 11 | * Originally based on code by FirstBlood: 12 | * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 13 | * 14 | * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for 15 | * all accounts just by listening to said events. Note that this isn't required by the specification, and other 16 | * compliant implementations may not do it. 17 | */ 18 | contract ERC20 is IERC20 { 19 | using SafeMath for uint256; 20 | 21 | mapping (address => uint256) private _balances; 22 | 23 | mapping (address => mapping (address => uint256)) private _allowed; 24 | 25 | uint256 private _totalSupply; 26 | 27 | /** 28 | * @dev Total number of tokens in existence 29 | */ 30 | function totalSupply() public view returns (uint256) { 31 | return _totalSupply; 32 | } 33 | 34 | /** 35 | * @dev Gets the balance of the specified address. 36 | * @param owner The address to query the balance of. 37 | * @return An uint256 representing the amount owned by the passed address. 38 | */ 39 | function balanceOf(address owner) public view returns (uint256) { 40 | return _balances[owner]; 41 | } 42 | 43 | /** 44 | * @dev Function to check the amount of tokens that an owner allowed to a spender. 45 | * @param owner address The address which owns the funds. 46 | * @param spender address The address which will spend the funds. 47 | * @return A uint256 specifying the amount of tokens still available for the spender. 48 | */ 49 | function allowance(address owner, address spender) public view returns (uint256) { 50 | return _allowed[owner][spender]; 51 | } 52 | 53 | /** 54 | * @dev Transfer token for a specified address 55 | * @param to The address to transfer to. 56 | * @param value The amount to be transferred. 57 | */ 58 | function transfer(address to, uint256 value) public returns (bool) { 59 | _transfer(msg.sender, to, value); 60 | return true; 61 | } 62 | 63 | /** 64 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 65 | * Beware that changing an allowance with this method brings the risk that someone may use both the old 66 | * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 67 | * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 68 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 69 | * @param spender The address which will spend the funds. 70 | * @param value The amount of tokens to be spent. 71 | */ 72 | function approve(address spender, uint256 value) public returns (bool) { 73 | _approve(msg.sender, spender, value); 74 | return true; 75 | } 76 | 77 | /** 78 | * @dev Transfer tokens from one address to another. 79 | * Note that while this function emits an Approval event, this is not required as per the specification, 80 | * and other compliant implementations may not emit the event. 81 | * @param from address The address which you want to send tokens from 82 | * @param to address The address which you want to transfer to 83 | * @param value uint256 the amount of tokens to be transferred 84 | */ 85 | function transferFrom(address from, address to, uint256 value) public returns (bool) { 86 | _transfer(from, to, value); 87 | _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); 88 | return true; 89 | } 90 | 91 | /** 92 | * @dev Increase the amount of tokens that an owner allowed to a spender. 93 | * approve should be called when allowed_[_spender] == 0. To increment 94 | * allowed value is better to use this function to avoid 2 calls (and wait until 95 | * the first transaction is mined) 96 | * From MonolithDAO Token.sol 97 | * Emits an Approval event. 98 | * @param spender The address which will spend the funds. 99 | * @param addedValue The amount of tokens to increase the allowance by. 100 | */ 101 | function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { 102 | _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); 103 | return true; 104 | } 105 | 106 | /** 107 | * @dev Decrease the amount of tokens that an owner allowed to a spender. 108 | * approve should be called when allowed_[_spender] == 0. To decrement 109 | * allowed value is better to use this function to avoid 2 calls (and wait until 110 | * the first transaction is mined) 111 | * From MonolithDAO Token.sol 112 | * Emits an Approval event. 113 | * @param spender The address which will spend the funds. 114 | * @param subtractedValue The amount of tokens to decrease the allowance by. 115 | */ 116 | function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { 117 | _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); 118 | return true; 119 | } 120 | 121 | /** 122 | * @dev Transfer token for a specified addresses 123 | * @param from The address to transfer from. 124 | * @param to The address to transfer to. 125 | * @param value The amount to be transferred. 126 | */ 127 | function _transfer(address from, address to, uint256 value) internal { 128 | require(to != address(0)); 129 | 130 | _balances[from] = _balances[from].sub(value); 131 | _balances[to] = _balances[to].add(value); 132 | emit Transfer(from, to, value); 133 | } 134 | 135 | /** 136 | * @dev Internal function that mints an amount of the token and assigns it to 137 | * an account. This encapsulates the modification of balances such that the 138 | * proper events are emitted. 139 | * @param account The account that will receive the created tokens. 140 | * @param value The amount that will be created. 141 | */ 142 | function _mint(address account, uint256 value) internal { 143 | require(account != address(0)); 144 | 145 | _totalSupply = _totalSupply.add(value); 146 | _balances[account] = _balances[account].add(value); 147 | emit Transfer(address(0), account, value); 148 | } 149 | 150 | /** 151 | * @dev Internal function that burns an amount of the token of a given 152 | * account. 153 | * @param account The account whose tokens will be burnt. 154 | * @param value The amount that will be burnt. 155 | */ 156 | function _burn(address account, uint256 value) internal { 157 | require(account != address(0)); 158 | 159 | _totalSupply = _totalSupply.sub(value); 160 | _balances[account] = _balances[account].sub(value); 161 | emit Transfer(account, address(0), value); 162 | } 163 | 164 | /** 165 | * @dev Approve an address to spend another addresses' tokens. 166 | * @param owner The address that owns the tokens. 167 | * @param spender The address that will spend the tokens. 168 | * @param value The number of tokens that can be spent. 169 | */ 170 | function _approve(address owner, address spender, uint256 value) internal { 171 | require(spender != address(0)); 172 | require(owner != address(0)); 173 | 174 | _allowed[owner][spender] = value; 175 | emit Approval(owner, spender, value); 176 | } 177 | 178 | /** 179 | * @dev Internal function that burns an amount of the token of a given 180 | * account, deducting from the sender's allowance for said account. Uses the 181 | * internal burn function. 182 | * Emits an Approval event (reflecting the reduced allowance). 183 | * @param account The account whose tokens will be burnt. 184 | * @param value The amount that will be burnt. 185 | */ 186 | function _burnFrom(address account, uint256 value) internal { 187 | _burn(account, value); 188 | _approve(account, msg.sender, _allowed[account][msg.sender].sub(value)); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/views/NewMinion.vue: -------------------------------------------------------------------------------- 1 | 128 | 268 | -------------------------------------------------------------------------------- /contracts/moloch/tokens/ClaimsToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "../oz/SafeMath.sol"; 4 | import "../oz/IERC20.sol"; 5 | import "../oz/ERC20.sol"; 6 | 7 | /** 8 | * @dev Optional functions from the ERC20 standard. 9 | */ 10 | contract ERC20Detailed is IERC20 { 11 | string private _name; 12 | string private _symbol; 13 | uint8 private _decimals; 14 | 15 | /** 16 | * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of 17 | * these values are immutable: they can only be set once during 18 | * construction. 19 | */ 20 | constructor (string memory name, string memory symbol, uint8 decimals) public { 21 | _name = name; 22 | _symbol = symbol; 23 | _decimals = decimals; 24 | } 25 | 26 | /** 27 | * @dev Returns the name of the token. 28 | */ 29 | function name() public view returns (string memory) { 30 | return _name; 31 | } 32 | 33 | /** 34 | * @dev Returns the symbol of the token, usually a shorter version of the 35 | * name. 36 | */ 37 | function symbol() public view returns (string memory) { 38 | return _symbol; 39 | } 40 | 41 | /** 42 | * @dev Returns the number of decimals used to get its user representation. 43 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 44 | * be displayed to a user as `5,05` (`505 / 10 ** 2`). 45 | * 46 | * Tokens usually opt for a value of 18, imitating the relationship between 47 | * Ether and Wei. 48 | * 49 | * NOTE: This information is only used for _display_ purposes: it in 50 | * no way affects any of the arithmetic of the contract, including 51 | * {IERC20-balanceOf} and {IERC20-transfer}. 52 | */ 53 | function decimals() public view returns (uint8) { 54 | return _decimals; 55 | } 56 | } 57 | 58 | interface IClaimsToken { 59 | 60 | /** 61 | * @dev This event emits when funds to be deposited are sent to the token contract 62 | * @param from contains the address of the sender of the received funds 63 | * @param fundsReceived contains the amount of funds received for distribution 64 | */ 65 | event FundsReceived(address indexed from, uint256 fundsReceived); 66 | 67 | /** 68 | * @dev This event emits when distributed funds are withdrawn by a token holder. 69 | * @param by contains the address of the receiver of funds 70 | * @param fundsWithdrawn contains the amount of funds that were withdrawn 71 | */ 72 | event FundsWithdrawn(address indexed by, uint256 fundsWithdrawn); 73 | 74 | /** 75 | * @dev Withdraws available funds for user. 76 | */ 77 | function withdrawFunds() external payable; 78 | 79 | /** 80 | * @dev Returns the amount of funds a given address is able to withdraw currently. 81 | * @param _forAddress Address of ClaimsToken holder 82 | * @return A uint256 representing the available funds for a given account 83 | */ 84 | function availableFunds(address _forAddress) external view returns (uint256); 85 | 86 | /** 87 | * @dev Get cumulative funds received by ClaimsToken. 88 | * @return A uint256 representing the total funds received by ClaimsToken 89 | */ 90 | function totalReceivedFunds() external view returns (uint256); 91 | } 92 | 93 | contract ClaimsToken is IClaimsToken, ERC20, ERC20Detailed { 94 | 95 | using SafeMath for uint256; 96 | 97 | // cumulative funds received by this contract 98 | uint256 public receivedFunds; 99 | // cumulative funds received which were already processed for distribution - by user 100 | mapping (address => uint256) public processedFunds; 101 | // claimed but not yet withdrawn funds for a user 102 | mapping (address => uint256) public claimedFunds; 103 | 104 | 105 | constructor(address _owner) 106 | public 107 | ERC20Detailed("ClaimsToken", "CST", 18) 108 | { 109 | _mint(_owner, 10000 * (10 ** uint256(18))); 110 | 111 | receivedFunds = 0; 112 | } 113 | 114 | /** 115 | * @dev Transfer token to a specified address. 116 | * Claims funds for both parties, whereby the amount of tokens withdrawn 117 | * is inherited by the new token owner. 118 | * @param _to The address to transfer to 119 | * @param _value The amount to be transferred 120 | */ 121 | function transfer(address _to, uint256 _value) 122 | public 123 | returns (bool) 124 | { 125 | _claimFunds(msg.sender); 126 | _claimFunds(_to); 127 | 128 | return super.transfer(_to, _value); 129 | } 130 | 131 | 132 | /** 133 | * @dev Transfer tokens from one address to another. 134 | * Claims funds for both parties, whereby the amount of tokens withdrawn 135 | * is inherited by the new token owner. 136 | * @param _from address The address which you want to send tokens from 137 | * @param _to address The address which you want to transfer to 138 | * @param _value uint256 the amount of tokens to be transferred 139 | */ 140 | function transferFrom(address _from, address _to, uint256 _value) 141 | public 142 | returns (bool) 143 | { 144 | _claimFunds(_from); 145 | _claimFunds(_to); 146 | 147 | return super.transferFrom(_from, _to, _value); 148 | } 149 | 150 | /** 151 | * @dev Get cumulative funds received by ClaimsToken. 152 | * @return A uint256 representing the total funds received by ClaimsToken 153 | */ 154 | function totalReceivedFunds() 155 | external 156 | view 157 | returns (uint256) 158 | { 159 | return receivedFunds; 160 | } 161 | 162 | /** 163 | * @dev Returns the amount of funds a given address is able to withdraw currently. 164 | * @param _forAddress Address of ClaimsToken holder 165 | * @return A uint256 representing the available funds for a given account 166 | */ 167 | function availableFunds(address _forAddress) 168 | public 169 | view 170 | returns (uint256) 171 | { 172 | return _calcUnprocessedFunds(_forAddress).add(claimedFunds[_forAddress]); 173 | } 174 | 175 | /** 176 | * @dev Increments cumulative received funds by new received funds. 177 | * Called when ClaimsToken receives funds. 178 | * @param _value Amount of tokens / Ether received 179 | */ 180 | function _registerFunds(uint256 _value) 181 | internal 182 | { 183 | receivedFunds = receivedFunds.add(_value); 184 | } 185 | 186 | /** 187 | * @dev Returns payout for a user which can be withdrawn or claimed. 188 | * @param _forAddress Address of ClaimsToken holder 189 | */ 190 | function _calcUnprocessedFunds(address _forAddress) 191 | internal 192 | view 193 | returns (uint256) 194 | { 195 | uint256 newReceivedFunds = receivedFunds.sub(processedFunds[_forAddress]); 196 | return balanceOf(_forAddress).mul(newReceivedFunds).div(totalSupply()); 197 | } 198 | 199 | /** 200 | * @dev Claims funds for a user. 201 | * @param _forAddress Address of ClaimsToken holder 202 | */ 203 | function _claimFunds(address _forAddress) internal { 204 | uint256 unprocessedFunds = _calcUnprocessedFunds(_forAddress); 205 | 206 | processedFunds[_forAddress] = receivedFunds; 207 | claimedFunds[_forAddress] = claimedFunds[_forAddress].add(unprocessedFunds); 208 | } 209 | 210 | /** 211 | * @dev Sets claimed but not yet withdrawn funds to 0, 212 | * marks total received funds as processed and 213 | * returns the withdrawable amount for a user. 214 | * @return A uint256 representing the withdrawable funds 215 | */ 216 | function _prepareWithdraw() 217 | internal 218 | returns (uint256) 219 | { 220 | uint256 withdrawableFunds = availableFunds(msg.sender); 221 | 222 | processedFunds[msg.sender] = receivedFunds; 223 | claimedFunds[msg.sender] = 0; 224 | 225 | return withdrawableFunds; 226 | } 227 | } 228 | 229 | contract ClaimsTokenERC20Extension is IClaimsToken, ClaimsToken { 230 | 231 | // token that ClaimsToken takes in custodianship 232 | IERC20 public fundsToken; 233 | 234 | modifier onlyFundsToken () { 235 | require(msg.sender == address(fundsToken), "UNAUTHORIZED_SENDER"); 236 | _; 237 | } 238 | 239 | constructor(address _owner, IERC20 _fundsToken) 240 | public 241 | ClaimsToken(_owner) 242 | { 243 | require(address(_fundsToken) != address(0)); 244 | 245 | fundsToken = _fundsToken; 246 | } 247 | 248 | /** 249 | * @dev Withdraws available funds for user. 250 | */ 251 | function withdrawFunds() 252 | external 253 | payable 254 | { 255 | require(msg.value == 0, ""); 256 | 257 | uint256 withdrawableFunds = _prepareWithdraw(); 258 | 259 | require(fundsToken.transfer(msg.sender, withdrawableFunds), "TRANSFER_FAILED"); 260 | } 261 | 262 | /** 263 | * @dev For ERC223. 264 | * Calls _registerFunds(), whereby total received funds (cumulative) gets updated. 265 | * @param _sender Sender of tokens 266 | * @param _value Amount of tokens 267 | */ 268 | function tokenFallback(address _sender, uint256 _value, bytes memory) 269 | public 270 | onlyFundsToken() 271 | { 272 | if (_value > 0) { 273 | _registerFunds(_value); 274 | emit FundsReceived(_sender, _value); 275 | } 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /src/abi/certnft.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "anonymous": false, 9 | "inputs": [ 10 | { 11 | "indexed": true, 12 | "internalType": "address", 13 | "name": "owner", 14 | "type": "address" 15 | }, 16 | { 17 | "indexed": true, 18 | "internalType": "address", 19 | "name": "approved", 20 | "type": "address" 21 | }, 22 | { 23 | "indexed": true, 24 | "internalType": "uint256", 25 | "name": "tokenId", 26 | "type": "uint256" 27 | } 28 | ], 29 | "name": "Approval", 30 | "type": "event" 31 | }, 32 | { 33 | "anonymous": false, 34 | "inputs": [ 35 | { 36 | "indexed": true, 37 | "internalType": "address", 38 | "name": "owner", 39 | "type": "address" 40 | }, 41 | { 42 | "indexed": true, 43 | "internalType": "address", 44 | "name": "operator", 45 | "type": "address" 46 | }, 47 | { 48 | "indexed": false, 49 | "internalType": "bool", 50 | "name": "approved", 51 | "type": "bool" 52 | } 53 | ], 54 | "name": "ApprovalForAll", 55 | "type": "event" 56 | }, 57 | { 58 | "inputs": [ 59 | { 60 | "internalType": "address", 61 | "name": "to", 62 | "type": "address" 63 | }, 64 | { 65 | "internalType": "uint256", 66 | "name": "tokenId", 67 | "type": "uint256" 68 | } 69 | ], 70 | "name": "approve", 71 | "outputs": [], 72 | "stateMutability": "nonpayable", 73 | "type": "function" 74 | }, 75 | { 76 | "inputs": [ 77 | { 78 | "internalType": "address[]", 79 | "name": "players", 80 | "type": "address[]" 81 | }, 82 | { 83 | "internalType": "string", 84 | "name": "tokenURI", 85 | "type": "string" 86 | } 87 | ], 88 | "name": "awardCerts", 89 | "outputs": [ 90 | { 91 | "internalType": "bool", 92 | "name": "", 93 | "type": "bool" 94 | } 95 | ], 96 | "stateMutability": "nonpayable", 97 | "type": "function" 98 | }, 99 | { 100 | "anonymous": false, 101 | "inputs": [ 102 | { 103 | "indexed": true, 104 | "internalType": "address", 105 | "name": "previousOwner", 106 | "type": "address" 107 | }, 108 | { 109 | "indexed": true, 110 | "internalType": "address", 111 | "name": "newOwner", 112 | "type": "address" 113 | } 114 | ], 115 | "name": "OwnershipTransferred", 116 | "type": "event" 117 | }, 118 | { 119 | "inputs": [], 120 | "name": "renounceOwnership", 121 | "outputs": [], 122 | "stateMutability": "nonpayable", 123 | "type": "function" 124 | }, 125 | { 126 | "inputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "_from", 130 | "type": "address" 131 | }, 132 | { 133 | "internalType": "address", 134 | "name": "_to", 135 | "type": "address" 136 | }, 137 | { 138 | "internalType": "bytes", 139 | "name": "_data", 140 | "type": "bytes" 141 | } 142 | ], 143 | "name": "safeTransferAllFrom", 144 | "outputs": [], 145 | "stateMutability": "nonpayable", 146 | "type": "function" 147 | }, 148 | { 149 | "inputs": [ 150 | { 151 | "internalType": "address", 152 | "name": "from", 153 | "type": "address" 154 | }, 155 | { 156 | "internalType": "address", 157 | "name": "to", 158 | "type": "address" 159 | }, 160 | { 161 | "internalType": "uint256", 162 | "name": "tokenId", 163 | "type": "uint256" 164 | } 165 | ], 166 | "name": "safeTransferFrom", 167 | "outputs": [], 168 | "stateMutability": "nonpayable", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [ 173 | { 174 | "internalType": "address", 175 | "name": "from", 176 | "type": "address" 177 | }, 178 | { 179 | "internalType": "address", 180 | "name": "to", 181 | "type": "address" 182 | }, 183 | { 184 | "internalType": "uint256", 185 | "name": "tokenId", 186 | "type": "uint256" 187 | }, 188 | { 189 | "internalType": "bytes", 190 | "name": "_data", 191 | "type": "bytes" 192 | } 193 | ], 194 | "name": "safeTransferFrom", 195 | "outputs": [], 196 | "stateMutability": "nonpayable", 197 | "type": "function" 198 | }, 199 | { 200 | "inputs": [ 201 | { 202 | "internalType": "address", 203 | "name": "operator", 204 | "type": "address" 205 | }, 206 | { 207 | "internalType": "bool", 208 | "name": "approved", 209 | "type": "bool" 210 | } 211 | ], 212 | "name": "setApprovalForAll", 213 | "outputs": [], 214 | "stateMutability": "nonpayable", 215 | "type": "function" 216 | }, 217 | { 218 | "anonymous": false, 219 | "inputs": [ 220 | { 221 | "indexed": true, 222 | "internalType": "address", 223 | "name": "from", 224 | "type": "address" 225 | }, 226 | { 227 | "indexed": true, 228 | "internalType": "address", 229 | "name": "to", 230 | "type": "address" 231 | }, 232 | { 233 | "indexed": true, 234 | "internalType": "uint256", 235 | "name": "tokenId", 236 | "type": "uint256" 237 | } 238 | ], 239 | "name": "Transfer", 240 | "type": "event" 241 | }, 242 | { 243 | "inputs": [ 244 | { 245 | "internalType": "address", 246 | "name": "from", 247 | "type": "address" 248 | }, 249 | { 250 | "internalType": "address", 251 | "name": "to", 252 | "type": "address" 253 | }, 254 | { 255 | "internalType": "uint256", 256 | "name": "tokenId", 257 | "type": "uint256" 258 | } 259 | ], 260 | "name": "transferFrom", 261 | "outputs": [], 262 | "stateMutability": "nonpayable", 263 | "type": "function" 264 | }, 265 | { 266 | "inputs": [ 267 | { 268 | "internalType": "address", 269 | "name": "newOwner", 270 | "type": "address" 271 | } 272 | ], 273 | "name": "transferOwnership", 274 | "outputs": [], 275 | "stateMutability": "nonpayable", 276 | "type": "function" 277 | }, 278 | { 279 | "inputs": [ 280 | { 281 | "internalType": "address", 282 | "name": "owner", 283 | "type": "address" 284 | } 285 | ], 286 | "name": "balanceOf", 287 | "outputs": [ 288 | { 289 | "internalType": "uint256", 290 | "name": "", 291 | "type": "uint256" 292 | } 293 | ], 294 | "stateMutability": "view", 295 | "type": "function" 296 | }, 297 | { 298 | "inputs": [], 299 | "name": "baseURI", 300 | "outputs": [ 301 | { 302 | "internalType": "string", 303 | "name": "", 304 | "type": "string" 305 | } 306 | ], 307 | "stateMutability": "view", 308 | "type": "function" 309 | }, 310 | { 311 | "inputs": [ 312 | { 313 | "internalType": "uint256", 314 | "name": "tokenId", 315 | "type": "uint256" 316 | } 317 | ], 318 | "name": "getApproved", 319 | "outputs": [ 320 | { 321 | "internalType": "address", 322 | "name": "", 323 | "type": "address" 324 | } 325 | ], 326 | "stateMutability": "view", 327 | "type": "function" 328 | }, 329 | { 330 | "inputs": [ 331 | { 332 | "internalType": "address", 333 | "name": "owner", 334 | "type": "address" 335 | }, 336 | { 337 | "internalType": "address", 338 | "name": "operator", 339 | "type": "address" 340 | } 341 | ], 342 | "name": "isApprovedForAll", 343 | "outputs": [ 344 | { 345 | "internalType": "bool", 346 | "name": "", 347 | "type": "bool" 348 | } 349 | ], 350 | "stateMutability": "view", 351 | "type": "function" 352 | }, 353 | { 354 | "inputs": [], 355 | "name": "name", 356 | "outputs": [ 357 | { 358 | "internalType": "string", 359 | "name": "", 360 | "type": "string" 361 | } 362 | ], 363 | "stateMutability": "view", 364 | "type": "function" 365 | }, 366 | { 367 | "inputs": [], 368 | "name": "owner", 369 | "outputs": [ 370 | { 371 | "internalType": "address", 372 | "name": "", 373 | "type": "address" 374 | } 375 | ], 376 | "stateMutability": "view", 377 | "type": "function" 378 | }, 379 | { 380 | "inputs": [ 381 | { 382 | "internalType": "uint256", 383 | "name": "tokenId", 384 | "type": "uint256" 385 | } 386 | ], 387 | "name": "ownerOf", 388 | "outputs": [ 389 | { 390 | "internalType": "address", 391 | "name": "", 392 | "type": "address" 393 | } 394 | ], 395 | "stateMutability": "view", 396 | "type": "function" 397 | }, 398 | { 399 | "inputs": [ 400 | { 401 | "internalType": "bytes4", 402 | "name": "interfaceId", 403 | "type": "bytes4" 404 | } 405 | ], 406 | "name": "supportsInterface", 407 | "outputs": [ 408 | { 409 | "internalType": "bool", 410 | "name": "", 411 | "type": "bool" 412 | } 413 | ], 414 | "stateMutability": "view", 415 | "type": "function" 416 | }, 417 | { 418 | "inputs": [], 419 | "name": "symbol", 420 | "outputs": [ 421 | { 422 | "internalType": "string", 423 | "name": "", 424 | "type": "string" 425 | } 426 | ], 427 | "stateMutability": "view", 428 | "type": "function" 429 | }, 430 | { 431 | "inputs": [ 432 | { 433 | "internalType": "uint256", 434 | "name": "index", 435 | "type": "uint256" 436 | } 437 | ], 438 | "name": "tokenByIndex", 439 | "outputs": [ 440 | { 441 | "internalType": "uint256", 442 | "name": "", 443 | "type": "uint256" 444 | } 445 | ], 446 | "stateMutability": "view", 447 | "type": "function" 448 | }, 449 | { 450 | "inputs": [ 451 | { 452 | "internalType": "address", 453 | "name": "owner", 454 | "type": "address" 455 | }, 456 | { 457 | "internalType": "uint256", 458 | "name": "index", 459 | "type": "uint256" 460 | } 461 | ], 462 | "name": "tokenOfOwnerByIndex", 463 | "outputs": [ 464 | { 465 | "internalType": "uint256", 466 | "name": "", 467 | "type": "uint256" 468 | } 469 | ], 470 | "stateMutability": "view", 471 | "type": "function" 472 | }, 473 | { 474 | "inputs": [ 475 | { 476 | "internalType": "uint256", 477 | "name": "tokenId", 478 | "type": "uint256" 479 | } 480 | ], 481 | "name": "tokenURI", 482 | "outputs": [ 483 | { 484 | "internalType": "string", 485 | "name": "", 486 | "type": "string" 487 | } 488 | ], 489 | "stateMutability": "view", 490 | "type": "function" 491 | }, 492 | { 493 | "inputs": [], 494 | "name": "totalSupply", 495 | "outputs": [ 496 | { 497 | "internalType": "uint256", 498 | "name": "", 499 | "type": "uint256" 500 | } 501 | ], 502 | "stateMutability": "view", 503 | "type": "function" 504 | } 505 | ] 506 | -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/abi/minion_subdomain_registrar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "contract ENS", 6 | "name": "_ens", 7 | "type": "address" 8 | } 9 | ], 10 | "payable": false, 11 | "stateMutability": "nonpayable", 12 | "type": "constructor" 13 | }, 14 | { 15 | "anonymous": false, 16 | "inputs": [ 17 | { 18 | "indexed": true, 19 | "internalType": "bytes32", 20 | "name": "label", 21 | "type": "bytes32" 22 | }, 23 | { 24 | "indexed": false, 25 | "internalType": "string", 26 | "name": "domain", 27 | "type": "string" 28 | }, 29 | { 30 | "indexed": true, 31 | "internalType": "address", 32 | "name": "minion", 33 | "type": "address" 34 | } 35 | ], 36 | "name": "DomainConfigured", 37 | "type": "event" 38 | }, 39 | { 40 | "anonymous": false, 41 | "inputs": [ 42 | { 43 | "indexed": true, 44 | "internalType": "bytes32", 45 | "name": "label", 46 | "type": "bytes32" 47 | }, 48 | { 49 | "indexed": false, 50 | "internalType": "string", 51 | "name": "name", 52 | "type": "string" 53 | } 54 | ], 55 | "name": "DomainTransferred", 56 | "type": "event" 57 | }, 58 | { 59 | "anonymous": false, 60 | "inputs": [ 61 | { 62 | "indexed": true, 63 | "internalType": "bytes32", 64 | "name": "label", 65 | "type": "bytes32" 66 | } 67 | ], 68 | "name": "DomainUnlisted", 69 | "type": "event" 70 | }, 71 | { 72 | "anonymous": false, 73 | "inputs": [ 74 | { 75 | "indexed": true, 76 | "internalType": "bytes32", 77 | "name": "label", 78 | "type": "bytes32" 79 | }, 80 | { 81 | "indexed": false, 82 | "internalType": "string", 83 | "name": "subdomain", 84 | "type": "string" 85 | }, 86 | { 87 | "indexed": true, 88 | "internalType": "address", 89 | "name": "owner", 90 | "type": "address" 91 | } 92 | ], 93 | "name": "NewRegistration", 94 | "type": "event" 95 | }, 96 | { 97 | "anonymous": false, 98 | "inputs": [ 99 | { 100 | "indexed": true, 101 | "internalType": "bytes32", 102 | "name": "label", 103 | "type": "bytes32" 104 | }, 105 | { 106 | "indexed": true, 107 | "internalType": "address", 108 | "name": "oldOwner", 109 | "type": "address" 110 | }, 111 | { 112 | "indexed": true, 113 | "internalType": "address", 114 | "name": "newOwner", 115 | "type": "address" 116 | } 117 | ], 118 | "name": "OwnerChanged", 119 | "type": "event" 120 | }, 121 | { 122 | "anonymous": false, 123 | "inputs": [ 124 | { 125 | "indexed": true, 126 | "internalType": "bytes32", 127 | "name": "label", 128 | "type": "bytes32" 129 | }, 130 | { 131 | "indexed": false, 132 | "internalType": "address", 133 | "name": "addr", 134 | "type": "address" 135 | } 136 | ], 137 | "name": "TransferAddressSet", 138 | "type": "event" 139 | }, 140 | { 141 | "constant": true, 142 | "inputs": [], 143 | "name": "TLD_NODE", 144 | "outputs": [ 145 | { 146 | "internalType": "bytes32", 147 | "name": "", 148 | "type": "bytes32" 149 | } 150 | ], 151 | "payable": false, 152 | "stateMutability": "view", 153 | "type": "function" 154 | }, 155 | { 156 | "constant": false, 157 | "inputs": [ 158 | { 159 | "internalType": "string", 160 | "name": "name", 161 | "type": "string" 162 | }, 163 | { 164 | "internalType": "address", 165 | "name": "minion", 166 | "type": "address" 167 | } 168 | ], 169 | "name": "configureDomain", 170 | "outputs": [], 171 | "payable": false, 172 | "stateMutability": "nonpayable", 173 | "type": "function" 174 | }, 175 | { 176 | "constant": false, 177 | "inputs": [ 178 | { 179 | "internalType": "string", 180 | "name": "name", 181 | "type": "string" 182 | }, 183 | { 184 | "internalType": "address", 185 | "name": "minion", 186 | "type": "address" 187 | }, 188 | { 189 | "internalType": "address", 190 | "name": "_owner", 191 | "type": "address" 192 | } 193 | ], 194 | "name": "configureDomainFor", 195 | "outputs": [], 196 | "payable": false, 197 | "stateMutability": "nonpayable", 198 | "type": "function" 199 | }, 200 | { 201 | "constant": false, 202 | "inputs": [ 203 | { 204 | "internalType": "bytes32", 205 | "name": "label", 206 | "type": "bytes32" 207 | }, 208 | { 209 | "internalType": "string", 210 | "name": "subdomain", 211 | "type": "string" 212 | }, 213 | { 214 | "internalType": "address", 215 | "name": "resolver", 216 | "type": "address" 217 | } 218 | ], 219 | "name": "deregister", 220 | "outputs": [], 221 | "payable": false, 222 | "stateMutability": "nonpayable", 223 | "type": "function" 224 | }, 225 | { 226 | "constant": true, 227 | "inputs": [], 228 | "name": "ens", 229 | "outputs": [ 230 | { 231 | "internalType": "contract ENS", 232 | "name": "", 233 | "type": "address" 234 | } 235 | ], 236 | "payable": false, 237 | "stateMutability": "view", 238 | "type": "function" 239 | }, 240 | { 241 | "constant": false, 242 | "inputs": [ 243 | { 244 | "internalType": "string", 245 | "name": "name", 246 | "type": "string" 247 | } 248 | ], 249 | "name": "migrate", 250 | "outputs": [], 251 | "payable": false, 252 | "stateMutability": "nonpayable", 253 | "type": "function" 254 | }, 255 | { 256 | "constant": true, 257 | "inputs": [], 258 | "name": "migration", 259 | "outputs": [ 260 | { 261 | "internalType": "address", 262 | "name": "", 263 | "type": "address" 264 | } 265 | ], 266 | "payable": false, 267 | "stateMutability": "view", 268 | "type": "function" 269 | }, 270 | { 271 | "constant": true, 272 | "inputs": [ 273 | { 274 | "internalType": "bytes32", 275 | "name": "label", 276 | "type": "bytes32" 277 | } 278 | ], 279 | "name": "owner", 280 | "outputs": [ 281 | { 282 | "internalType": "address", 283 | "name": "", 284 | "type": "address" 285 | } 286 | ], 287 | "payable": false, 288 | "stateMutability": "view", 289 | "type": "function" 290 | }, 291 | { 292 | "constant": false, 293 | "inputs": [ 294 | { 295 | "internalType": "bytes32", 296 | "name": "label", 297 | "type": "bytes32" 298 | }, 299 | { 300 | "internalType": "string", 301 | "name": "subdomain", 302 | "type": "string" 303 | }, 304 | { 305 | "internalType": "address", 306 | "name": "_subdomainOwner", 307 | "type": "address" 308 | }, 309 | { 310 | "internalType": "address", 311 | "name": "resolver", 312 | "type": "address" 313 | } 314 | ], 315 | "name": "register", 316 | "outputs": [], 317 | "payable": false, 318 | "stateMutability": "nonpayable", 319 | "type": "function" 320 | }, 321 | { 322 | "constant": true, 323 | "inputs": [], 324 | "name": "registrar", 325 | "outputs": [ 326 | { 327 | "internalType": "address", 328 | "name": "", 329 | "type": "address" 330 | } 331 | ], 332 | "payable": false, 333 | "stateMutability": "view", 334 | "type": "function" 335 | }, 336 | { 337 | "constant": true, 338 | "inputs": [], 339 | "name": "registrarOwner", 340 | "outputs": [ 341 | { 342 | "internalType": "address", 343 | "name": "", 344 | "type": "address" 345 | } 346 | ], 347 | "payable": false, 348 | "stateMutability": "view", 349 | "type": "function" 350 | }, 351 | { 352 | "constant": false, 353 | "inputs": [ 354 | { 355 | "internalType": "address", 356 | "name": "_migration", 357 | "type": "address" 358 | } 359 | ], 360 | "name": "setMigrationAddress", 361 | "outputs": [], 362 | "payable": false, 363 | "stateMutability": "nonpayable", 364 | "type": "function" 365 | }, 366 | { 367 | "constant": false, 368 | "inputs": [ 369 | { 370 | "internalType": "string", 371 | "name": "name", 372 | "type": "string" 373 | }, 374 | { 375 | "internalType": "address", 376 | "name": "resolver", 377 | "type": "address" 378 | } 379 | ], 380 | "name": "setResolver", 381 | "outputs": [], 382 | "payable": false, 383 | "stateMutability": "nonpayable", 384 | "type": "function" 385 | }, 386 | { 387 | "constant": false, 388 | "inputs": [], 389 | "name": "stop", 390 | "outputs": [], 391 | "payable": false, 392 | "stateMutability": "nonpayable", 393 | "type": "function" 394 | }, 395 | { 396 | "constant": true, 397 | "inputs": [], 398 | "name": "stopped", 399 | "outputs": [ 400 | { 401 | "internalType": "bool", 402 | "name": "", 403 | "type": "bool" 404 | } 405 | ], 406 | "payable": false, 407 | "stateMutability": "view", 408 | "type": "function" 409 | }, 410 | { 411 | "constant": false, 412 | "inputs": [ 413 | { 414 | "internalType": "string", 415 | "name": "name", 416 | "type": "string" 417 | }, 418 | { 419 | "internalType": "address", 420 | "name": "newOwner", 421 | "type": "address" 422 | } 423 | ], 424 | "name": "transfer", 425 | "outputs": [], 426 | "payable": false, 427 | "stateMutability": "nonpayable", 428 | "type": "function" 429 | }, 430 | { 431 | "constant": false, 432 | "inputs": [ 433 | { 434 | "internalType": "address", 435 | "name": "newOwner", 436 | "type": "address" 437 | } 438 | ], 439 | "name": "transferOwnership", 440 | "outputs": [], 441 | "payable": false, 442 | "stateMutability": "nonpayable", 443 | "type": "function" 444 | }, 445 | { 446 | "constant": false, 447 | "inputs": [ 448 | { 449 | "internalType": "string", 450 | "name": "name", 451 | "type": "string" 452 | } 453 | ], 454 | "name": "unlistDomain", 455 | "outputs": [], 456 | "payable": false, 457 | "stateMutability": "nonpayable", 458 | "type": "function" 459 | } 460 | ] 461 | -------------------------------------------------------------------------------- /src/abi/moloch_v1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": true, 4 | "inputs": [], 5 | "name": "processingReward", 6 | "outputs": [ 7 | { 8 | "name": "", 9 | "type": "uint256" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "view", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": true, 18 | "inputs": [ 19 | { 20 | "name": "memberAddress", 21 | "type": "address" 22 | }, 23 | { 24 | "name": "proposalIndex", 25 | "type": "uint256" 26 | } 27 | ], 28 | "name": "getMemberProposalVote", 29 | "outputs": [ 30 | { 31 | "name": "", 32 | "type": "uint8" 33 | } 34 | ], 35 | "payable": false, 36 | "stateMutability": "view", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": true, 41 | "inputs": [], 42 | "name": "getCurrentPeriod", 43 | "outputs": [ 44 | { 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "payable": false, 50 | "stateMutability": "view", 51 | "type": "function" 52 | }, 53 | { 54 | "constant": true, 55 | "inputs": [ 56 | { 57 | "name": "", 58 | "type": "address" 59 | } 60 | ], 61 | "name": "members", 62 | "outputs": [ 63 | { 64 | "name": "delegateKey", 65 | "type": "address" 66 | }, 67 | { 68 | "name": "shares", 69 | "type": "uint256" 70 | }, 71 | { 72 | "name": "exists", 73 | "type": "bool" 74 | }, 75 | { 76 | "name": "highestIndexYesVote", 77 | "type": "uint256" 78 | } 79 | ], 80 | "payable": false, 81 | "stateMutability": "view", 82 | "type": "function" 83 | }, 84 | { 85 | "constant": true, 86 | "inputs": [], 87 | "name": "totalSharesRequested", 88 | "outputs": [ 89 | { 90 | "name": "", 91 | "type": "uint256" 92 | } 93 | ], 94 | "payable": false, 95 | "stateMutability": "view", 96 | "type": "function" 97 | }, 98 | { 99 | "constant": false, 100 | "inputs": [ 101 | { 102 | "name": "newDelegateKey", 103 | "type": "address" 104 | } 105 | ], 106 | "name": "updateDelegateKey", 107 | "outputs": [], 108 | "payable": false, 109 | "stateMutability": "nonpayable", 110 | "type": "function" 111 | }, 112 | { 113 | "constant": true, 114 | "inputs": [], 115 | "name": "totalShares", 116 | "outputs": [ 117 | { 118 | "name": "", 119 | "type": "uint256" 120 | } 121 | ], 122 | "payable": false, 123 | "stateMutability": "view", 124 | "type": "function" 125 | }, 126 | { 127 | "constant": true, 128 | "inputs": [ 129 | { 130 | "name": "", 131 | "type": "uint256" 132 | } 133 | ], 134 | "name": "proposalQueue", 135 | "outputs": [ 136 | { 137 | "name": "proposer", 138 | "type": "address" 139 | }, 140 | { 141 | "name": "applicant", 142 | "type": "address" 143 | }, 144 | { 145 | "name": "sharesRequested", 146 | "type": "uint256" 147 | }, 148 | { 149 | "name": "startingPeriod", 150 | "type": "uint256" 151 | }, 152 | { 153 | "name": "yesVotes", 154 | "type": "uint256" 155 | }, 156 | { 157 | "name": "noVotes", 158 | "type": "uint256" 159 | }, 160 | { 161 | "name": "processed", 162 | "type": "bool" 163 | }, 164 | { 165 | "name": "didPass", 166 | "type": "bool" 167 | }, 168 | { 169 | "name": "aborted", 170 | "type": "bool" 171 | }, 172 | { 173 | "name": "tokenTribute", 174 | "type": "uint256" 175 | }, 176 | { 177 | "name": "details", 178 | "type": "string" 179 | }, 180 | { 181 | "name": "maxTotalSharesAtYesVote", 182 | "type": "uint256" 183 | } 184 | ], 185 | "payable": false, 186 | "stateMutability": "view", 187 | "type": "function" 188 | }, 189 | { 190 | "constant": true, 191 | "inputs": [ 192 | { 193 | "name": "", 194 | "type": "address" 195 | } 196 | ], 197 | "name": "memberAddressByDelegateKey", 198 | "outputs": [ 199 | { 200 | "name": "", 201 | "type": "address" 202 | } 203 | ], 204 | "payable": false, 205 | "stateMutability": "view", 206 | "type": "function" 207 | }, 208 | { 209 | "constant": true, 210 | "inputs": [], 211 | "name": "gracePeriodLength", 212 | "outputs": [ 213 | { 214 | "name": "", 215 | "type": "uint256" 216 | } 217 | ], 218 | "payable": false, 219 | "stateMutability": "view", 220 | "type": "function" 221 | }, 222 | { 223 | "constant": true, 224 | "inputs": [], 225 | "name": "abortWindow", 226 | "outputs": [ 227 | { 228 | "name": "", 229 | "type": "uint256" 230 | } 231 | ], 232 | "payable": false, 233 | "stateMutability": "view", 234 | "type": "function" 235 | }, 236 | { 237 | "constant": true, 238 | "inputs": [], 239 | "name": "getProposalQueueLength", 240 | "outputs": [ 241 | { 242 | "name": "", 243 | "type": "uint256" 244 | } 245 | ], 246 | "payable": false, 247 | "stateMutability": "view", 248 | "type": "function" 249 | }, 250 | { 251 | "constant": true, 252 | "inputs": [], 253 | "name": "summoningTime", 254 | "outputs": [ 255 | { 256 | "name": "", 257 | "type": "uint256" 258 | } 259 | ], 260 | "payable": false, 261 | "stateMutability": "view", 262 | "type": "function" 263 | }, 264 | { 265 | "constant": true, 266 | "inputs": [], 267 | "name": "votingPeriodLength", 268 | "outputs": [ 269 | { 270 | "name": "", 271 | "type": "uint256" 272 | } 273 | ], 274 | "payable": false, 275 | "stateMutability": "view", 276 | "type": "function" 277 | }, 278 | { 279 | "constant": false, 280 | "inputs": [ 281 | { 282 | "name": "sharesToBurn", 283 | "type": "uint256" 284 | } 285 | ], 286 | "name": "ragequit", 287 | "outputs": [], 288 | "payable": false, 289 | "stateMutability": "nonpayable", 290 | "type": "function" 291 | }, 292 | { 293 | "constant": true, 294 | "inputs": [], 295 | "name": "proposalDeposit", 296 | "outputs": [ 297 | { 298 | "name": "", 299 | "type": "uint256" 300 | } 301 | ], 302 | "payable": false, 303 | "stateMutability": "view", 304 | "type": "function" 305 | }, 306 | { 307 | "constant": true, 308 | "inputs": [ 309 | { 310 | "name": "startingPeriod", 311 | "type": "uint256" 312 | } 313 | ], 314 | "name": "hasVotingPeriodExpired", 315 | "outputs": [ 316 | { 317 | "name": "", 318 | "type": "bool" 319 | } 320 | ], 321 | "payable": false, 322 | "stateMutability": "view", 323 | "type": "function" 324 | }, 325 | { 326 | "constant": false, 327 | "inputs": [ 328 | { 329 | "name": "applicant", 330 | "type": "address" 331 | }, 332 | { 333 | "name": "tokenTribute", 334 | "type": "uint256" 335 | }, 336 | { 337 | "name": "sharesRequested", 338 | "type": "uint256" 339 | }, 340 | { 341 | "name": "details", 342 | "type": "string" 343 | } 344 | ], 345 | "name": "submitProposal", 346 | "outputs": [], 347 | "payable": false, 348 | "stateMutability": "nonpayable", 349 | "type": "function" 350 | }, 351 | { 352 | "constant": false, 353 | "inputs": [ 354 | { 355 | "name": "proposalIndex", 356 | "type": "uint256" 357 | }, 358 | { 359 | "name": "uintVote", 360 | "type": "uint8" 361 | } 362 | ], 363 | "name": "submitVote", 364 | "outputs": [], 365 | "payable": false, 366 | "stateMutability": "nonpayable", 367 | "type": "function" 368 | }, 369 | { 370 | "constant": true, 371 | "inputs": [ 372 | { 373 | "name": "highestIndexYesVote", 374 | "type": "uint256" 375 | } 376 | ], 377 | "name": "canRagequit", 378 | "outputs": [ 379 | { 380 | "name": "", 381 | "type": "bool" 382 | } 383 | ], 384 | "payable": false, 385 | "stateMutability": "view", 386 | "type": "function" 387 | }, 388 | { 389 | "constant": true, 390 | "inputs": [], 391 | "name": "guildBank", 392 | "outputs": [ 393 | { 394 | "name": "", 395 | "type": "address" 396 | } 397 | ], 398 | "payable": false, 399 | "stateMutability": "view", 400 | "type": "function" 401 | }, 402 | { 403 | "constant": true, 404 | "inputs": [], 405 | "name": "dilutionBound", 406 | "outputs": [ 407 | { 408 | "name": "", 409 | "type": "uint256" 410 | } 411 | ], 412 | "payable": false, 413 | "stateMutability": "view", 414 | "type": "function" 415 | }, 416 | { 417 | "constant": true, 418 | "inputs": [], 419 | "name": "periodDuration", 420 | "outputs": [ 421 | { 422 | "name": "", 423 | "type": "uint256" 424 | } 425 | ], 426 | "payable": false, 427 | "stateMutability": "view", 428 | "type": "function" 429 | }, 430 | { 431 | "constant": true, 432 | "inputs": [], 433 | "name": "approvedToken", 434 | "outputs": [ 435 | { 436 | "name": "", 437 | "type": "address" 438 | } 439 | ], 440 | "payable": false, 441 | "stateMutability": "view", 442 | "type": "function" 443 | }, 444 | { 445 | "constant": false, 446 | "inputs": [ 447 | { 448 | "name": "proposalIndex", 449 | "type": "uint256" 450 | } 451 | ], 452 | "name": "abort", 453 | "outputs": [], 454 | "payable": false, 455 | "stateMutability": "nonpayable", 456 | "type": "function" 457 | }, 458 | { 459 | "constant": false, 460 | "inputs": [ 461 | { 462 | "name": "proposalIndex", 463 | "type": "uint256" 464 | } 465 | ], 466 | "name": "processProposal", 467 | "outputs": [], 468 | "payable": false, 469 | "stateMutability": "nonpayable", 470 | "type": "function" 471 | }, 472 | { 473 | "inputs": [ 474 | { 475 | "name": "summoner", 476 | "type": "address" 477 | }, 478 | { 479 | "name": "_approvedToken", 480 | "type": "address" 481 | }, 482 | { 483 | "name": "_periodDuration", 484 | "type": "uint256" 485 | }, 486 | { 487 | "name": "_votingPeriodLength", 488 | "type": "uint256" 489 | }, 490 | { 491 | "name": "_gracePeriodLength", 492 | "type": "uint256" 493 | }, 494 | { 495 | "name": "_abortWindow", 496 | "type": "uint256" 497 | }, 498 | { 499 | "name": "_proposalDeposit", 500 | "type": "uint256" 501 | }, 502 | { 503 | "name": "_dilutionBound", 504 | "type": "uint256" 505 | }, 506 | { 507 | "name": "_processingReward", 508 | "type": "uint256" 509 | } 510 | ], 511 | "payable": false, 512 | "stateMutability": "nonpayable", 513 | "type": "constructor" 514 | }, 515 | { 516 | "anonymous": false, 517 | "inputs": [ 518 | { 519 | "indexed": false, 520 | "name": "proposalIndex", 521 | "type": "uint256" 522 | }, 523 | { 524 | "indexed": true, 525 | "name": "delegateKey", 526 | "type": "address" 527 | }, 528 | { 529 | "indexed": true, 530 | "name": "memberAddress", 531 | "type": "address" 532 | }, 533 | { 534 | "indexed": true, 535 | "name": "applicant", 536 | "type": "address" 537 | }, 538 | { 539 | "indexed": false, 540 | "name": "tokenTribute", 541 | "type": "uint256" 542 | }, 543 | { 544 | "indexed": false, 545 | "name": "sharesRequested", 546 | "type": "uint256" 547 | } 548 | ], 549 | "name": "SubmitProposal", 550 | "type": "event" 551 | }, 552 | { 553 | "anonymous": false, 554 | "inputs": [ 555 | { 556 | "indexed": true, 557 | "name": "proposalIndex", 558 | "type": "uint256" 559 | }, 560 | { 561 | "indexed": true, 562 | "name": "delegateKey", 563 | "type": "address" 564 | }, 565 | { 566 | "indexed": true, 567 | "name": "memberAddress", 568 | "type": "address" 569 | }, 570 | { 571 | "indexed": false, 572 | "name": "uintVote", 573 | "type": "uint8" 574 | } 575 | ], 576 | "name": "SubmitVote", 577 | "type": "event" 578 | }, 579 | { 580 | "anonymous": false, 581 | "inputs": [ 582 | { 583 | "indexed": true, 584 | "name": "proposalIndex", 585 | "type": "uint256" 586 | }, 587 | { 588 | "indexed": true, 589 | "name": "applicant", 590 | "type": "address" 591 | }, 592 | { 593 | "indexed": true, 594 | "name": "memberAddress", 595 | "type": "address" 596 | }, 597 | { 598 | "indexed": false, 599 | "name": "tokenTribute", 600 | "type": "uint256" 601 | }, 602 | { 603 | "indexed": false, 604 | "name": "sharesRequested", 605 | "type": "uint256" 606 | }, 607 | { 608 | "indexed": false, 609 | "name": "didPass", 610 | "type": "bool" 611 | } 612 | ], 613 | "name": "ProcessProposal", 614 | "type": "event" 615 | }, 616 | { 617 | "anonymous": false, 618 | "inputs": [ 619 | { 620 | "indexed": true, 621 | "name": "memberAddress", 622 | "type": "address" 623 | }, 624 | { 625 | "indexed": false, 626 | "name": "sharesToBurn", 627 | "type": "uint256" 628 | } 629 | ], 630 | "name": "Ragequit", 631 | "type": "event" 632 | }, 633 | { 634 | "anonymous": false, 635 | "inputs": [ 636 | { 637 | "indexed": true, 638 | "name": "proposalIndex", 639 | "type": "uint256" 640 | }, 641 | { 642 | "indexed": false, 643 | "name": "applicantAddress", 644 | "type": "address" 645 | } 646 | ], 647 | "name": "Abort", 648 | "type": "event" 649 | }, 650 | { 651 | "anonymous": false, 652 | "inputs": [ 653 | { 654 | "indexed": true, 655 | "name": "memberAddress", 656 | "type": "address" 657 | }, 658 | { 659 | "indexed": false, 660 | "name": "newDelegateKey", 661 | "type": "address" 662 | } 663 | ], 664 | "name": "UpdateDelegateKey", 665 | "type": "event" 666 | }, 667 | { 668 | "anonymous": false, 669 | "inputs": [ 670 | { 671 | "indexed": true, 672 | "name": "summoner", 673 | "type": "address" 674 | }, 675 | { 676 | "indexed": false, 677 | "name": "shares", 678 | "type": "uint256" 679 | } 680 | ], 681 | "name": "SummonComplete", 682 | "type": "event" 683 | } 684 | ] 685 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 107 | 494 | -------------------------------------------------------------------------------- /src/abi/ens_registrar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "contract ENS", 6 | "name": "_ens", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "bytes32", 11 | "name": "_baseNode", 12 | "type": "bytes32" 13 | } 14 | ], 15 | "payable": false, 16 | "stateMutability": "nonpayable", 17 | "type": "constructor" 18 | }, 19 | { 20 | "anonymous": false, 21 | "inputs": [ 22 | { 23 | "indexed": true, 24 | "internalType": "address", 25 | "name": "owner", 26 | "type": "address" 27 | }, 28 | { 29 | "indexed": true, 30 | "internalType": "address", 31 | "name": "approved", 32 | "type": "address" 33 | }, 34 | { 35 | "indexed": true, 36 | "internalType": "uint256", 37 | "name": "tokenId", 38 | "type": "uint256" 39 | } 40 | ], 41 | "name": "Approval", 42 | "type": "event" 43 | }, 44 | { 45 | "anonymous": false, 46 | "inputs": [ 47 | { 48 | "indexed": true, 49 | "internalType": "address", 50 | "name": "owner", 51 | "type": "address" 52 | }, 53 | { 54 | "indexed": true, 55 | "internalType": "address", 56 | "name": "operator", 57 | "type": "address" 58 | }, 59 | { 60 | "indexed": false, 61 | "internalType": "bool", 62 | "name": "approved", 63 | "type": "bool" 64 | } 65 | ], 66 | "name": "ApprovalForAll", 67 | "type": "event" 68 | }, 69 | { 70 | "anonymous": false, 71 | "inputs": [ 72 | { 73 | "indexed": true, 74 | "internalType": "address", 75 | "name": "controller", 76 | "type": "address" 77 | } 78 | ], 79 | "name": "ControllerAdded", 80 | "type": "event" 81 | }, 82 | { 83 | "anonymous": false, 84 | "inputs": [ 85 | { 86 | "indexed": true, 87 | "internalType": "address", 88 | "name": "controller", 89 | "type": "address" 90 | } 91 | ], 92 | "name": "ControllerRemoved", 93 | "type": "event" 94 | }, 95 | { 96 | "anonymous": false, 97 | "inputs": [ 98 | { 99 | "indexed": true, 100 | "internalType": "uint256", 101 | "name": "id", 102 | "type": "uint256" 103 | }, 104 | { 105 | "indexed": true, 106 | "internalType": "address", 107 | "name": "owner", 108 | "type": "address" 109 | }, 110 | { 111 | "indexed": false, 112 | "internalType": "uint256", 113 | "name": "expires", 114 | "type": "uint256" 115 | } 116 | ], 117 | "name": "NameMigrated", 118 | "type": "event" 119 | }, 120 | { 121 | "anonymous": false, 122 | "inputs": [ 123 | { 124 | "indexed": true, 125 | "internalType": "uint256", 126 | "name": "id", 127 | "type": "uint256" 128 | }, 129 | { 130 | "indexed": true, 131 | "internalType": "address", 132 | "name": "owner", 133 | "type": "address" 134 | }, 135 | { 136 | "indexed": false, 137 | "internalType": "uint256", 138 | "name": "expires", 139 | "type": "uint256" 140 | } 141 | ], 142 | "name": "NameRegistered", 143 | "type": "event" 144 | }, 145 | { 146 | "anonymous": false, 147 | "inputs": [ 148 | { 149 | "indexed": true, 150 | "internalType": "uint256", 151 | "name": "id", 152 | "type": "uint256" 153 | }, 154 | { 155 | "indexed": false, 156 | "internalType": "uint256", 157 | "name": "expires", 158 | "type": "uint256" 159 | } 160 | ], 161 | "name": "NameRenewed", 162 | "type": "event" 163 | }, 164 | { 165 | "anonymous": false, 166 | "inputs": [ 167 | { 168 | "indexed": true, 169 | "internalType": "address", 170 | "name": "previousOwner", 171 | "type": "address" 172 | }, 173 | { 174 | "indexed": true, 175 | "internalType": "address", 176 | "name": "newOwner", 177 | "type": "address" 178 | } 179 | ], 180 | "name": "OwnershipTransferred", 181 | "type": "event" 182 | }, 183 | { 184 | "anonymous": false, 185 | "inputs": [ 186 | { 187 | "indexed": true, 188 | "internalType": "address", 189 | "name": "from", 190 | "type": "address" 191 | }, 192 | { 193 | "indexed": true, 194 | "internalType": "address", 195 | "name": "to", 196 | "type": "address" 197 | }, 198 | { 199 | "indexed": true, 200 | "internalType": "uint256", 201 | "name": "tokenId", 202 | "type": "uint256" 203 | } 204 | ], 205 | "name": "Transfer", 206 | "type": "event" 207 | }, 208 | { 209 | "constant": true, 210 | "inputs": [], 211 | "name": "GRACE_PERIOD", 212 | "outputs": [ 213 | { 214 | "internalType": "uint256", 215 | "name": "", 216 | "type": "uint256" 217 | } 218 | ], 219 | "payable": false, 220 | "stateMutability": "view", 221 | "type": "function" 222 | }, 223 | { 224 | "constant": false, 225 | "inputs": [ 226 | { 227 | "internalType": "address", 228 | "name": "controller", 229 | "type": "address" 230 | } 231 | ], 232 | "name": "addController", 233 | "outputs": [], 234 | "payable": false, 235 | "stateMutability": "nonpayable", 236 | "type": "function" 237 | }, 238 | { 239 | "constant": false, 240 | "inputs": [ 241 | { 242 | "internalType": "address", 243 | "name": "to", 244 | "type": "address" 245 | }, 246 | { 247 | "internalType": "uint256", 248 | "name": "tokenId", 249 | "type": "uint256" 250 | } 251 | ], 252 | "name": "approve", 253 | "outputs": [], 254 | "payable": false, 255 | "stateMutability": "nonpayable", 256 | "type": "function" 257 | }, 258 | { 259 | "constant": true, 260 | "inputs": [ 261 | { 262 | "internalType": "uint256", 263 | "name": "id", 264 | "type": "uint256" 265 | } 266 | ], 267 | "name": "available", 268 | "outputs": [ 269 | { 270 | "internalType": "bool", 271 | "name": "", 272 | "type": "bool" 273 | } 274 | ], 275 | "payable": false, 276 | "stateMutability": "view", 277 | "type": "function" 278 | }, 279 | { 280 | "constant": true, 281 | "inputs": [ 282 | { 283 | "internalType": "address", 284 | "name": "owner", 285 | "type": "address" 286 | } 287 | ], 288 | "name": "balanceOf", 289 | "outputs": [ 290 | { 291 | "internalType": "uint256", 292 | "name": "", 293 | "type": "uint256" 294 | } 295 | ], 296 | "payable": false, 297 | "stateMutability": "view", 298 | "type": "function" 299 | }, 300 | { 301 | "constant": true, 302 | "inputs": [], 303 | "name": "baseNode", 304 | "outputs": [ 305 | { 306 | "internalType": "bytes32", 307 | "name": "", 308 | "type": "bytes32" 309 | } 310 | ], 311 | "payable": false, 312 | "stateMutability": "view", 313 | "type": "function" 314 | }, 315 | { 316 | "constant": true, 317 | "inputs": [ 318 | { 319 | "internalType": "address", 320 | "name": "", 321 | "type": "address" 322 | } 323 | ], 324 | "name": "controllers", 325 | "outputs": [ 326 | { 327 | "internalType": "bool", 328 | "name": "", 329 | "type": "bool" 330 | } 331 | ], 332 | "payable": false, 333 | "stateMutability": "view", 334 | "type": "function" 335 | }, 336 | { 337 | "constant": true, 338 | "inputs": [], 339 | "name": "ens", 340 | "outputs": [ 341 | { 342 | "internalType": "contract ENS", 343 | "name": "", 344 | "type": "address" 345 | } 346 | ], 347 | "payable": false, 348 | "stateMutability": "view", 349 | "type": "function" 350 | }, 351 | { 352 | "constant": true, 353 | "inputs": [ 354 | { 355 | "internalType": "uint256", 356 | "name": "tokenId", 357 | "type": "uint256" 358 | } 359 | ], 360 | "name": "getApproved", 361 | "outputs": [ 362 | { 363 | "internalType": "address", 364 | "name": "", 365 | "type": "address" 366 | } 367 | ], 368 | "payable": false, 369 | "stateMutability": "view", 370 | "type": "function" 371 | }, 372 | { 373 | "constant": true, 374 | "inputs": [ 375 | { 376 | "internalType": "address", 377 | "name": "owner", 378 | "type": "address" 379 | }, 380 | { 381 | "internalType": "address", 382 | "name": "operator", 383 | "type": "address" 384 | } 385 | ], 386 | "name": "isApprovedForAll", 387 | "outputs": [ 388 | { 389 | "internalType": "bool", 390 | "name": "", 391 | "type": "bool" 392 | } 393 | ], 394 | "payable": false, 395 | "stateMutability": "view", 396 | "type": "function" 397 | }, 398 | { 399 | "constant": true, 400 | "inputs": [], 401 | "name": "isOwner", 402 | "outputs": [ 403 | { 404 | "internalType": "bool", 405 | "name": "", 406 | "type": "bool" 407 | } 408 | ], 409 | "payable": false, 410 | "stateMutability": "view", 411 | "type": "function" 412 | }, 413 | { 414 | "constant": true, 415 | "inputs": [ 416 | { 417 | "internalType": "uint256", 418 | "name": "id", 419 | "type": "uint256" 420 | } 421 | ], 422 | "name": "nameExpires", 423 | "outputs": [ 424 | { 425 | "internalType": "uint256", 426 | "name": "", 427 | "type": "uint256" 428 | } 429 | ], 430 | "payable": false, 431 | "stateMutability": "view", 432 | "type": "function" 433 | }, 434 | { 435 | "constant": true, 436 | "inputs": [], 437 | "name": "owner", 438 | "outputs": [ 439 | { 440 | "internalType": "address", 441 | "name": "", 442 | "type": "address" 443 | } 444 | ], 445 | "payable": false, 446 | "stateMutability": "view", 447 | "type": "function" 448 | }, 449 | { 450 | "constant": true, 451 | "inputs": [ 452 | { 453 | "internalType": "uint256", 454 | "name": "tokenId", 455 | "type": "uint256" 456 | } 457 | ], 458 | "name": "ownerOf", 459 | "outputs": [ 460 | { 461 | "internalType": "address", 462 | "name": "", 463 | "type": "address" 464 | } 465 | ], 466 | "payable": false, 467 | "stateMutability": "view", 468 | "type": "function" 469 | }, 470 | { 471 | "constant": false, 472 | "inputs": [ 473 | { 474 | "internalType": "uint256", 475 | "name": "id", 476 | "type": "uint256" 477 | }, 478 | { 479 | "internalType": "address", 480 | "name": "owner", 481 | "type": "address" 482 | } 483 | ], 484 | "name": "reclaim", 485 | "outputs": [], 486 | "payable": false, 487 | "stateMutability": "nonpayable", 488 | "type": "function" 489 | }, 490 | { 491 | "constant": false, 492 | "inputs": [ 493 | { 494 | "internalType": "uint256", 495 | "name": "id", 496 | "type": "uint256" 497 | }, 498 | { 499 | "internalType": "address", 500 | "name": "owner", 501 | "type": "address" 502 | }, 503 | { 504 | "internalType": "uint256", 505 | "name": "duration", 506 | "type": "uint256" 507 | } 508 | ], 509 | "name": "register", 510 | "outputs": [ 511 | { 512 | "internalType": "uint256", 513 | "name": "", 514 | "type": "uint256" 515 | } 516 | ], 517 | "payable": false, 518 | "stateMutability": "nonpayable", 519 | "type": "function" 520 | }, 521 | { 522 | "constant": false, 523 | "inputs": [ 524 | { 525 | "internalType": "uint256", 526 | "name": "id", 527 | "type": "uint256" 528 | }, 529 | { 530 | "internalType": "address", 531 | "name": "owner", 532 | "type": "address" 533 | }, 534 | { 535 | "internalType": "uint256", 536 | "name": "duration", 537 | "type": "uint256" 538 | } 539 | ], 540 | "name": "registerOnly", 541 | "outputs": [ 542 | { 543 | "internalType": "uint256", 544 | "name": "", 545 | "type": "uint256" 546 | } 547 | ], 548 | "payable": false, 549 | "stateMutability": "nonpayable", 550 | "type": "function" 551 | }, 552 | { 553 | "constant": false, 554 | "inputs": [ 555 | { 556 | "internalType": "address", 557 | "name": "controller", 558 | "type": "address" 559 | } 560 | ], 561 | "name": "removeController", 562 | "outputs": [], 563 | "payable": false, 564 | "stateMutability": "nonpayable", 565 | "type": "function" 566 | }, 567 | { 568 | "constant": false, 569 | "inputs": [ 570 | { 571 | "internalType": "uint256", 572 | "name": "id", 573 | "type": "uint256" 574 | }, 575 | { 576 | "internalType": "uint256", 577 | "name": "duration", 578 | "type": "uint256" 579 | } 580 | ], 581 | "name": "renew", 582 | "outputs": [ 583 | { 584 | "internalType": "uint256", 585 | "name": "", 586 | "type": "uint256" 587 | } 588 | ], 589 | "payable": false, 590 | "stateMutability": "nonpayable", 591 | "type": "function" 592 | }, 593 | { 594 | "constant": false, 595 | "inputs": [], 596 | "name": "renounceOwnership", 597 | "outputs": [], 598 | "payable": false, 599 | "stateMutability": "nonpayable", 600 | "type": "function" 601 | }, 602 | { 603 | "constant": false, 604 | "inputs": [ 605 | { 606 | "internalType": "address", 607 | "name": "from", 608 | "type": "address" 609 | }, 610 | { 611 | "internalType": "address", 612 | "name": "to", 613 | "type": "address" 614 | }, 615 | { 616 | "internalType": "uint256", 617 | "name": "tokenId", 618 | "type": "uint256" 619 | } 620 | ], 621 | "name": "safeTransferFrom", 622 | "outputs": [], 623 | "payable": false, 624 | "stateMutability": "nonpayable", 625 | "type": "function" 626 | }, 627 | { 628 | "constant": false, 629 | "inputs": [ 630 | { 631 | "internalType": "address", 632 | "name": "from", 633 | "type": "address" 634 | }, 635 | { 636 | "internalType": "address", 637 | "name": "to", 638 | "type": "address" 639 | }, 640 | { 641 | "internalType": "uint256", 642 | "name": "tokenId", 643 | "type": "uint256" 644 | }, 645 | { 646 | "internalType": "bytes", 647 | "name": "_data", 648 | "type": "bytes" 649 | } 650 | ], 651 | "name": "safeTransferFrom", 652 | "outputs": [], 653 | "payable": false, 654 | "stateMutability": "nonpayable", 655 | "type": "function" 656 | }, 657 | { 658 | "constant": false, 659 | "inputs": [ 660 | { 661 | "internalType": "address", 662 | "name": "to", 663 | "type": "address" 664 | }, 665 | { 666 | "internalType": "bool", 667 | "name": "approved", 668 | "type": "bool" 669 | } 670 | ], 671 | "name": "setApprovalForAll", 672 | "outputs": [], 673 | "payable": false, 674 | "stateMutability": "nonpayable", 675 | "type": "function" 676 | }, 677 | { 678 | "constant": false, 679 | "inputs": [ 680 | { 681 | "internalType": "address", 682 | "name": "resolver", 683 | "type": "address" 684 | } 685 | ], 686 | "name": "setResolver", 687 | "outputs": [], 688 | "payable": false, 689 | "stateMutability": "nonpayable", 690 | "type": "function" 691 | }, 692 | { 693 | "constant": true, 694 | "inputs": [ 695 | { 696 | "internalType": "bytes4", 697 | "name": "interfaceID", 698 | "type": "bytes4" 699 | } 700 | ], 701 | "name": "supportsInterface", 702 | "outputs": [ 703 | { 704 | "internalType": "bool", 705 | "name": "", 706 | "type": "bool" 707 | } 708 | ], 709 | "payable": false, 710 | "stateMutability": "view", 711 | "type": "function" 712 | }, 713 | { 714 | "constant": false, 715 | "inputs": [ 716 | { 717 | "internalType": "address", 718 | "name": "from", 719 | "type": "address" 720 | }, 721 | { 722 | "internalType": "address", 723 | "name": "to", 724 | "type": "address" 725 | }, 726 | { 727 | "internalType": "uint256", 728 | "name": "tokenId", 729 | "type": "uint256" 730 | } 731 | ], 732 | "name": "transferFrom", 733 | "outputs": [], 734 | "payable": false, 735 | "stateMutability": "nonpayable", 736 | "type": "function" 737 | }, 738 | { 739 | "constant": false, 740 | "inputs": [ 741 | { 742 | "internalType": "address", 743 | "name": "newOwner", 744 | "type": "address" 745 | } 746 | ], 747 | "name": "transferOwnership", 748 | "outputs": [], 749 | "payable": false, 750 | "stateMutability": "nonpayable", 751 | "type": "function" 752 | } 753 | ] 754 | -------------------------------------------------------------------------------- /tests/contracts/minion_integration.spec.ts: -------------------------------------------------------------------------------- 1 | import { waffle } from "@nomiclabs/buidler"; 2 | import chai from "chai"; 3 | import { ethers } from "ethers"; 4 | import { deployContract, solidity } from "ethereum-waffle"; 5 | 6 | import MinionArtifact from "../../build/artifacts/Minion.json"; 7 | import MolochArtifact from "../../build/artifacts/Moloch.json"; 8 | import TokenArtifact from "../../build/artifacts/Token.json"; 9 | import TargetMockArtifact from "../../build/artifacts/TargetMock.json"; 10 | import RevertingMolochArtifact from "../../build/artifacts/RevertingMoloch.json"; 11 | import { Minion } from "../../build/types/Minion"; 12 | import { Moloch } from "../../build/types/Moloch"; 13 | import { Token } from "../../build/types/Token"; 14 | import { TargetMock } from "../../build/types/TargetMock"; 15 | import { RevertingMoloch } from "../../build/types/RevertingMoloch"; 16 | 17 | import { Action, Proposal } from "./utils/types"; 18 | import Constants from "./utils/constants"; 19 | import Utils from "./utils/utils"; 20 | 21 | chai.use(solidity); 22 | const { expect } = chai; 23 | 24 | describe("Minion integration", () => { 25 | const provider = waffle.provider; 26 | const [wallet, eoa] = provider.getWallets(); 27 | 28 | let minion: Minion; 29 | let moloch: Moloch; 30 | let token: Token; 31 | let target: TargetMock; 32 | 33 | beforeEach(async () => { 34 | token = (await deployContract(wallet, TokenArtifact, [ 35 | Constants.MaxUint256 36 | ])) as Token; 37 | 38 | moloch = (await deployContract( 39 | wallet, 40 | MolochArtifact, 41 | [ 42 | wallet.address, 43 | [token.address], 44 | Constants.molochConfig.PERIOD_DURATION_IN_SECONDS, 45 | Constants.molochConfig.VOTING_DURATON_IN_PERIODS, 46 | Constants.molochConfig.GRACE_DURATON_IN_PERIODS, 47 | Constants.molochConfig.PROPOSAL_DEPOSIT, 48 | Constants.molochConfig.DILUTION_BOUND, 49 | Constants.molochConfig.PROCESSING_REWARD 50 | ], 51 | { gasLimit: 9500000 } 52 | )) as Moloch; 53 | 54 | minion = (await deployContract(wallet, MinionArtifact, [ 55 | moloch.address 56 | ])) as Minion; 57 | 58 | target = (await deployContract(wallet, TargetMockArtifact)) as TargetMock; 59 | await token.approve(moloch.address, Constants.MaxUint256); 60 | }); 61 | 62 | it("deploys correctly", async () => { 63 | expect(minion.address).to.not.eq(Constants.AddressZero); 64 | expect(await minion.moloch()).to.eq(moloch.address); 65 | expect(await minion.molochApprovedToken()).to.eq(token.address); 66 | expect(await minion.MINION_ACTION_DETAILS()).to.eq( 67 | Constants.MINION_ACTION_DETAILS 68 | ); 69 | }); 70 | 71 | describe("proposeAction", () => { 72 | describe("success cases", () => { 73 | let action: Action; 74 | let proposal: Proposal; 75 | 76 | beforeEach(async () => { 77 | action = { 78 | to: target.address, 79 | value: ethers.utils.parseEther("1"), 80 | data: ethers.utils.hexlify(ethers.utils.randomBytes(50)), 81 | description: "foo", 82 | proposalId: 0, 83 | queueIndex: 0 84 | }; 85 | proposal = { 86 | applicant: minion.address, 87 | proposer: minion.address, 88 | sharesRequested: 0, 89 | lootRequested: 0, 90 | tributeOffered: 0, 91 | tributeToken: token.address, 92 | paymentRequested: 0, 93 | paymentToken: token.address, 94 | details: Utils.encodeDetailsString(action.description) 95 | }; 96 | await minion.proposeAction( 97 | action.to, 98 | action.value, 99 | action.data, 100 | action.description 101 | ); 102 | }); 103 | 104 | it("stores the correct action", async () => { 105 | const storedAction = await minion.actions(action.proposalId); 106 | expect(storedAction.to).to.equal(action.to); 107 | expect(storedAction.value).to.equal(action.value); 108 | expect(storedAction.data).to.equal(action.data); 109 | expect(storedAction.proposer).to.equal(wallet.address); 110 | expect(storedAction.executed).to.equal(false); 111 | }); 112 | 113 | it("submits the correct proposal to parent moloch", async () => { 114 | const storedProposal = await moloch.proposals(action.proposalId); 115 | const proposalFlags = await moloch.getProposalFlags(action.proposalId); 116 | expect(proposalFlags).to.deep.equal([ 117 | false, 118 | false, 119 | false, 120 | false, 121 | false, 122 | false 123 | ]); 124 | expect(storedProposal.applicant).to.equal(proposal.applicant); 125 | expect(storedProposal.proposer).to.equal(proposal.proposer); 126 | expect(storedProposal.sponsor).to.equal(Constants.AddressZero); 127 | expect(storedProposal.sharesRequested).to.equal( 128 | proposal.sharesRequested 129 | ); 130 | expect(storedProposal.lootRequested).to.equal(proposal.lootRequested); 131 | expect(storedProposal.tributeOffered).to.equal(proposal.tributeOffered); 132 | expect(storedProposal.tributeToken).to.equal(proposal.tributeToken); 133 | expect(storedProposal.paymentRequested).to.equal( 134 | proposal.paymentRequested 135 | ); 136 | expect(storedProposal.paymentToken).to.equal(proposal.paymentToken); 137 | expect(storedProposal.details).to.equal(proposal.details); 138 | }); 139 | 140 | it("emits expected events", async () => { 141 | const proposalId = 1; 142 | await expect( 143 | minion.proposeAction( 144 | action.to, 145 | action.value, 146 | action.data, 147 | action.description 148 | ) 149 | ) 150 | .to.emit(minion, "ActionProposed") 151 | .withArgs(proposalId, wallet.address) 152 | .to.emit(moloch, "SubmitProposal") 153 | .withArgs( 154 | proposal.applicant, 155 | proposal.sharesRequested, 156 | proposal.lootRequested, 157 | proposal.tributeOffered, 158 | proposal.tributeToken, 159 | proposal.paymentRequested, 160 | proposal.paymentToken, 161 | proposal.details, 162 | [false, false, false, false, false], 163 | proposalId, 164 | minion.address, 165 | Constants.AddressZero 166 | ); 167 | }); 168 | }); 169 | 170 | describe("failure cases", () => { 171 | it("reverts proposal to zero address", async () => { 172 | const badAction = { 173 | to: Constants.AddressZero, 174 | value: ethers.utils.parseEther("1"), 175 | data: ethers.utils.hexlify(ethers.utils.randomBytes(50)), 176 | description: "foo" 177 | }; 178 | await expect( 179 | minion.proposeAction( 180 | badAction.to, 181 | badAction.value, 182 | badAction.data, 183 | badAction.description 184 | ) 185 | ).to.be.revertedWith(Constants.revertStrings.INVALID_PROP_TARGET); 186 | }); 187 | 188 | it("reverts if moloch proposal fails", async () => { 189 | const action = { 190 | to: target.address, 191 | value: ethers.utils.parseEther("1"), 192 | data: ethers.utils.hexlify(ethers.utils.randomBytes(50)), 193 | description: "foo" 194 | }; 195 | const revertingMoloch = (await deployContract( 196 | wallet, 197 | RevertingMolochArtifact 198 | )) as Moloch; 199 | const revertingMinion = (await deployContract(wallet, MinionArtifact, [ 200 | revertingMoloch.address 201 | ])) as Minion; 202 | await expect( 203 | revertingMinion.proposeAction( 204 | action.to, 205 | action.value, 206 | action.data, 207 | action.description 208 | ) 209 | ).to.be.revertedWith(Constants.revertStrings.none); 210 | }); 211 | }); 212 | }); 213 | 214 | describe("executeAction", () => { 215 | describe("success cases", () => { 216 | let action1: Action, action2: Action, emptyAddressAction: Action; 217 | 218 | beforeEach(async () => { 219 | await Utils.incProposalCount(moloch, 1); 220 | action1 = { 221 | to: target.address, 222 | value: ethers.utils.parseEther("0"), 223 | data: "0x", 224 | description: "foo", 225 | proposalId: 1, 226 | queueIndex: 0 227 | }; 228 | action2 = { 229 | to: target.address, 230 | value: ethers.utils.parseEther("1"), 231 | data: ethers.utils.hexlify(ethers.utils.randomBytes(50)), 232 | description: "foo", 233 | proposalId: 2, 234 | queueIndex: 1 235 | }; 236 | emptyAddressAction = { 237 | to: eoa.address, 238 | value: ethers.utils.parseEther("0"), 239 | data: ethers.utils.hexlify(ethers.utils.randomBytes(50)), 240 | description: "foo", 241 | proposalId: 3, 242 | queueIndex: 2 243 | }; 244 | await Utils.proposeAndPass(minion, moloch, action1); 245 | await Utils.proposeAndPass(minion, moloch, action2); 246 | await Utils.proposeAndPass(minion, moloch, emptyAddressAction); 247 | }); 248 | 249 | it("executes a passed proposal", async () => { 250 | await expect(minion.executeAction(action1.proposalId)) 251 | .to.emit(minion, "ActionExecuted") 252 | .withArgs(action1.proposalId, wallet.address) 253 | .to.emit(target, "Called") 254 | .withArgs(minion.address, action1.value, action1.data); 255 | expect((await minion.actions(action1.proposalId)).executed).to.be.true; 256 | }); 257 | 258 | it("executes proposal with data and value", async () => { 259 | await wallet.sendTransaction({ 260 | to: minion.address, 261 | value: action2.value 262 | }); 263 | await expect(minion.executeAction(action2.proposalId)) 264 | .to.emit(minion, "ActionExecuted") 265 | .withArgs(action2.proposalId, wallet.address) 266 | .to.emit(target, "Called") 267 | .withArgs(minion.address, action2.value, action2.data); 268 | expect((await minion.actions(action2.proposalId)).executed).to.be.true; 269 | expect(await provider.getBalance(target.address)).to.equal( 270 | action2.value 271 | ); 272 | }); 273 | 274 | it("executes actions in any order", async () => { 275 | await wallet.sendTransaction({ 276 | to: minion.address, 277 | value: action2.value 278 | }); 279 | await expect(minion.executeAction(action2.proposalId)) 280 | .to.emit(minion, "ActionExecuted") 281 | .withArgs(action2.proposalId, wallet.address) 282 | .to.emit(target, "Called") 283 | .withArgs(minion.address, action2.value, action2.data); 284 | expect((await minion.actions(action2.proposalId)).executed).to.be.true; 285 | 286 | await expect(minion.executeAction(action1.proposalId)) 287 | .to.emit(minion, "ActionExecuted") 288 | .withArgs(action1.proposalId, wallet.address) 289 | .to.emit(target, "Called") 290 | .withArgs(minion.address, action1.value, action1.data); 291 | expect((await minion.actions(action1.proposalId)).executed).to.be.true; 292 | }); 293 | 294 | // *** Be aware that calls to empty addresses should succeed, 295 | // even if they contain data. 296 | it("SUCCESSFULLY sends data to an EMPTY address", async () => { 297 | await minion.executeAction(emptyAddressAction.proposalId); 298 | }); 299 | }); 300 | 301 | describe("failure cases", () => { 302 | let unpassedAction: Action, 303 | valueAction: Action, 304 | actionToMoloch: Action, 305 | executedAction: Action, 306 | failingCallAction: Action; 307 | 308 | beforeEach(async () => { 309 | unpassedAction = { 310 | to: target.address, 311 | value: ethers.utils.parseEther("0"), 312 | data: "0x", 313 | description: "foo", 314 | proposalId: 0, 315 | queueIndex: 0 316 | }; 317 | valueAction = { 318 | to: target.address, 319 | value: ethers.utils.parseEther("1"), 320 | data: "0x", 321 | description: "foo", 322 | proposalId: 1, 323 | queueIndex: 0 324 | }; 325 | actionToMoloch = { 326 | to: moloch.address, 327 | value: ethers.utils.parseEther("0"), 328 | data: "0x", 329 | description: "foo", 330 | proposalId: 2, 331 | queueIndex: 1 332 | }; 333 | executedAction = { 334 | to: target.address, 335 | value: ethers.utils.parseEther("0"), 336 | data: "0x", 337 | description: "foo", 338 | proposalId: 3, 339 | queueIndex: 2 340 | }; 341 | failingCallAction = { 342 | to: target.address, 343 | value: ethers.utils.parseEther("0"), 344 | data: new ethers.utils.Interface(TargetMockArtifact.abi).functions 345 | .fail.sighash, 346 | description: "foo", 347 | proposalId: 4, 348 | queueIndex: 3 349 | }; 350 | 351 | // these executions need to stay in order to line up with the 352 | // proposalIds and queueIndices above. Sorry.. 353 | await minion.proposeAction( 354 | unpassedAction.to, 355 | unpassedAction.value, 356 | unpassedAction.data, 357 | unpassedAction.description 358 | ); 359 | await Utils.proposeAndPass(minion, moloch, valueAction); 360 | await Utils.proposeAndPass(minion, moloch, actionToMoloch); 361 | await Utils.proposeAndPass(minion, moloch, executedAction); 362 | await Utils.proposeAndPass(minion, moloch, failingCallAction); 363 | 364 | // execute the "executed action" 365 | await minion.executeAction(executedAction.proposalId); 366 | }); 367 | 368 | it("reverts if insufficient eth", async () => { 369 | await expect( 370 | minion.executeAction(valueAction.proposalId) 371 | ).to.be.revertedWith(Constants.revertStrings.NO_ETH); 372 | }); 373 | 374 | it("reverts on un-passed proposal", async () => { 375 | await expect( 376 | minion.executeAction(unpassedAction.proposalId) 377 | ).to.be.revertedWith(Constants.revertStrings.NOT_PASSED); 378 | }); 379 | 380 | it("reverts action to moloch", async () => { 381 | await expect( 382 | minion.executeAction(actionToMoloch.proposalId) 383 | ).to.be.revertedWith(Constants.revertStrings.INVALID_EXEC_TARGET); 384 | }); 385 | 386 | it("reverts a previously executed action", async () => { 387 | await expect( 388 | minion.executeAction(executedAction.proposalId) 389 | ).to.be.revertedWith(Constants.revertStrings.IS_EXECUTED); 390 | }); 391 | 392 | it("reverts a proposal created by another source", async () => { 393 | // submit a proposal directly to the moloch, not through the minion 394 | await moloch.submitProposal( 395 | minion.address, 396 | 0, 397 | 0, 398 | 0, 399 | token.address, 400 | 0, 401 | token.address, 402 | "" 403 | ); 404 | const proposalId = (await moloch.proposalCount()).sub(1).toNumber(); 405 | const falseAction: Action = { 406 | to: target.address, 407 | value: ethers.utils.parseEther("0"), 408 | data: "0x", 409 | description: "foo", 410 | proposalId: proposalId, 411 | queueIndex: proposalId - 1 412 | }; 413 | await Utils.passProposal(moloch, falseAction); 414 | await expect( 415 | minion.executeAction(falseAction.proposalId) 416 | ).to.be.revertedWith(Constants.revertStrings.INVALID_EXEC_ID); 417 | }); 418 | 419 | it("fails if action call reverts", async () => { 420 | await expect( 421 | minion.executeAction(failingCallAction.proposalId) 422 | ).to.be.revertedWith(Constants.revertStrings.CALL_FAIL); 423 | }); 424 | }); 425 | }); 426 | 427 | // TODO: Add an interface to withdrawBalances? 428 | describe("doWithdraw", () => { 429 | it("withdraws funds from parent moloch", async () => { 430 | const amount = ethers.utils.parseEther("1"); 431 | await token.transfer(moloch.address, amount); 432 | 433 | // add tokens to guild bank balance 434 | await moloch.submitProposal( 435 | wallet.address, 436 | 0, 437 | 0, 438 | amount, 439 | token.address, 440 | 0, 441 | token.address, 442 | "" 443 | ); 444 | // pay minion 445 | await moloch.submitProposal( 446 | minion.address, 447 | 0, 448 | 0, 449 | 0, 450 | token.address, 451 | amount, 452 | token.address, 453 | "" 454 | ); 455 | 456 | // pass and process both proposals 457 | const fillGuildBankAction = { 458 | to: "", 459 | value: new ethers.utils.BigNumber(0), 460 | data: "0x", 461 | description: "", 462 | proposalId: 0, 463 | queueIndex: 0 464 | }; 465 | const payMinionAction = { 466 | to: "", 467 | value: new ethers.utils.BigNumber(0), 468 | data: "0x", 469 | description: "", 470 | proposalId: 1, 471 | queueIndex: 1 472 | }; 473 | await Utils.passProposal(moloch, fillGuildBankAction); 474 | await Utils.passProposal(moloch, payMinionAction); 475 | 476 | // withdraw minion balance 477 | await minion.doWithdraw(token.address, amount); 478 | }); 479 | }); 480 | }); 481 | -------------------------------------------------------------------------------- /src/abi/uniswap_v2_router.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "name": "WETH", 5 | "outputs": [ 6 | { 7 | "internalType": "address", 8 | "name": "", 9 | "type": "address" 10 | } 11 | ], 12 | "stateMutability": "pure", 13 | "type": "function" 14 | }, 15 | { 16 | "inputs": [ 17 | { 18 | "internalType": "address", 19 | "name": "tokenA", 20 | "type": "address" 21 | }, 22 | { 23 | "internalType": "address", 24 | "name": "tokenB", 25 | "type": "address" 26 | }, 27 | { 28 | "internalType": "uint256", 29 | "name": "amountADesired", 30 | "type": "uint256" 31 | }, 32 | { 33 | "internalType": "uint256", 34 | "name": "amountBDesired", 35 | "type": "uint256" 36 | }, 37 | { 38 | "internalType": "uint256", 39 | "name": "amountAMin", 40 | "type": "uint256" 41 | }, 42 | { 43 | "internalType": "uint256", 44 | "name": "amountBMin", 45 | "type": "uint256" 46 | }, 47 | { 48 | "internalType": "address", 49 | "name": "to", 50 | "type": "address" 51 | }, 52 | { 53 | "internalType": "uint256", 54 | "name": "deadline", 55 | "type": "uint256" 56 | } 57 | ], 58 | "name": "addLiquidity", 59 | "outputs": [ 60 | { 61 | "internalType": "uint256", 62 | "name": "amountA", 63 | "type": "uint256" 64 | }, 65 | { 66 | "internalType": "uint256", 67 | "name": "amountB", 68 | "type": "uint256" 69 | }, 70 | { 71 | "internalType": "uint256", 72 | "name": "liquidity", 73 | "type": "uint256" 74 | } 75 | ], 76 | "stateMutability": "nonpayable", 77 | "type": "function" 78 | }, 79 | { 80 | "inputs": [ 81 | { 82 | "internalType": "address", 83 | "name": "token", 84 | "type": "address" 85 | }, 86 | { 87 | "internalType": "uint256", 88 | "name": "amountTokenDesired", 89 | "type": "uint256" 90 | }, 91 | { 92 | "internalType": "uint256", 93 | "name": "amountTokenMin", 94 | "type": "uint256" 95 | }, 96 | { 97 | "internalType": "uint256", 98 | "name": "amountETHMin", 99 | "type": "uint256" 100 | }, 101 | { 102 | "internalType": "address", 103 | "name": "to", 104 | "type": "address" 105 | }, 106 | { 107 | "internalType": "uint256", 108 | "name": "deadline", 109 | "type": "uint256" 110 | } 111 | ], 112 | "name": "addLiquidityETH", 113 | "outputs": [ 114 | { 115 | "internalType": "uint256", 116 | "name": "amountToken", 117 | "type": "uint256" 118 | }, 119 | { 120 | "internalType": "uint256", 121 | "name": "amountETH", 122 | "type": "uint256" 123 | }, 124 | { 125 | "internalType": "uint256", 126 | "name": "liquidity", 127 | "type": "uint256" 128 | } 129 | ], 130 | "stateMutability": "payable", 131 | "type": "function" 132 | }, 133 | { 134 | "inputs": [], 135 | "name": "factory", 136 | "outputs": [ 137 | { 138 | "internalType": "address", 139 | "name": "", 140 | "type": "address" 141 | } 142 | ], 143 | "stateMutability": "pure", 144 | "type": "function" 145 | }, 146 | { 147 | "inputs": [ 148 | { 149 | "internalType": "uint256", 150 | "name": "amountOut", 151 | "type": "uint256" 152 | }, 153 | { 154 | "internalType": "uint256", 155 | "name": "reserveIn", 156 | "type": "uint256" 157 | }, 158 | { 159 | "internalType": "uint256", 160 | "name": "reserveOut", 161 | "type": "uint256" 162 | } 163 | ], 164 | "name": "getAmountIn", 165 | "outputs": [ 166 | { 167 | "internalType": "uint256", 168 | "name": "amountIn", 169 | "type": "uint256" 170 | } 171 | ], 172 | "stateMutability": "pure", 173 | "type": "function" 174 | }, 175 | { 176 | "inputs": [ 177 | { 178 | "internalType": "uint256", 179 | "name": "amountIn", 180 | "type": "uint256" 181 | }, 182 | { 183 | "internalType": "uint256", 184 | "name": "reserveIn", 185 | "type": "uint256" 186 | }, 187 | { 188 | "internalType": "uint256", 189 | "name": "reserveOut", 190 | "type": "uint256" 191 | } 192 | ], 193 | "name": "getAmountOut", 194 | "outputs": [ 195 | { 196 | "internalType": "uint256", 197 | "name": "amountOut", 198 | "type": "uint256" 199 | } 200 | ], 201 | "stateMutability": "pure", 202 | "type": "function" 203 | }, 204 | { 205 | "inputs": [ 206 | { 207 | "internalType": "uint256", 208 | "name": "amountOut", 209 | "type": "uint256" 210 | }, 211 | { 212 | "internalType": "address[]", 213 | "name": "path", 214 | "type": "address[]" 215 | } 216 | ], 217 | "name": "getAmountsIn", 218 | "outputs": [ 219 | { 220 | "internalType": "uint256[]", 221 | "name": "amounts", 222 | "type": "uint256[]" 223 | } 224 | ], 225 | "stateMutability": "view", 226 | "type": "function" 227 | }, 228 | { 229 | "inputs": [ 230 | { 231 | "internalType": "uint256", 232 | "name": "amountIn", 233 | "type": "uint256" 234 | }, 235 | { 236 | "internalType": "address[]", 237 | "name": "path", 238 | "type": "address[]" 239 | } 240 | ], 241 | "name": "getAmountsOut", 242 | "outputs": [ 243 | { 244 | "internalType": "uint256[]", 245 | "name": "amounts", 246 | "type": "uint256[]" 247 | } 248 | ], 249 | "stateMutability": "view", 250 | "type": "function" 251 | }, 252 | { 253 | "inputs": [ 254 | { 255 | "internalType": "uint256", 256 | "name": "amountA", 257 | "type": "uint256" 258 | }, 259 | { 260 | "internalType": "uint256", 261 | "name": "reserveA", 262 | "type": "uint256" 263 | }, 264 | { 265 | "internalType": "uint256", 266 | "name": "reserveB", 267 | "type": "uint256" 268 | } 269 | ], 270 | "name": "quote", 271 | "outputs": [ 272 | { 273 | "internalType": "uint256", 274 | "name": "amountB", 275 | "type": "uint256" 276 | } 277 | ], 278 | "stateMutability": "pure", 279 | "type": "function" 280 | }, 281 | { 282 | "inputs": [ 283 | { 284 | "internalType": "address", 285 | "name": "tokenA", 286 | "type": "address" 287 | }, 288 | { 289 | "internalType": "address", 290 | "name": "tokenB", 291 | "type": "address" 292 | }, 293 | { 294 | "internalType": "uint256", 295 | "name": "liquidity", 296 | "type": "uint256" 297 | }, 298 | { 299 | "internalType": "uint256", 300 | "name": "amountAMin", 301 | "type": "uint256" 302 | }, 303 | { 304 | "internalType": "uint256", 305 | "name": "amountBMin", 306 | "type": "uint256" 307 | }, 308 | { 309 | "internalType": "address", 310 | "name": "to", 311 | "type": "address" 312 | }, 313 | { 314 | "internalType": "uint256", 315 | "name": "deadline", 316 | "type": "uint256" 317 | } 318 | ], 319 | "name": "removeLiquidity", 320 | "outputs": [ 321 | { 322 | "internalType": "uint256", 323 | "name": "amountA", 324 | "type": "uint256" 325 | }, 326 | { 327 | "internalType": "uint256", 328 | "name": "amountB", 329 | "type": "uint256" 330 | } 331 | ], 332 | "stateMutability": "nonpayable", 333 | "type": "function" 334 | }, 335 | { 336 | "inputs": [ 337 | { 338 | "internalType": "address", 339 | "name": "token", 340 | "type": "address" 341 | }, 342 | { 343 | "internalType": "uint256", 344 | "name": "liquidity", 345 | "type": "uint256" 346 | }, 347 | { 348 | "internalType": "uint256", 349 | "name": "amountTokenMin", 350 | "type": "uint256" 351 | }, 352 | { 353 | "internalType": "uint256", 354 | "name": "amountETHMin", 355 | "type": "uint256" 356 | }, 357 | { 358 | "internalType": "address", 359 | "name": "to", 360 | "type": "address" 361 | }, 362 | { 363 | "internalType": "uint256", 364 | "name": "deadline", 365 | "type": "uint256" 366 | } 367 | ], 368 | "name": "removeLiquidityETH", 369 | "outputs": [ 370 | { 371 | "internalType": "uint256", 372 | "name": "amountToken", 373 | "type": "uint256" 374 | }, 375 | { 376 | "internalType": "uint256", 377 | "name": "amountETH", 378 | "type": "uint256" 379 | } 380 | ], 381 | "stateMutability": "nonpayable", 382 | "type": "function" 383 | }, 384 | { 385 | "inputs": [ 386 | { 387 | "internalType": "address", 388 | "name": "token", 389 | "type": "address" 390 | }, 391 | { 392 | "internalType": "uint256", 393 | "name": "liquidity", 394 | "type": "uint256" 395 | }, 396 | { 397 | "internalType": "uint256", 398 | "name": "amountTokenMin", 399 | "type": "uint256" 400 | }, 401 | { 402 | "internalType": "uint256", 403 | "name": "amountETHMin", 404 | "type": "uint256" 405 | }, 406 | { 407 | "internalType": "address", 408 | "name": "to", 409 | "type": "address" 410 | }, 411 | { 412 | "internalType": "uint256", 413 | "name": "deadline", 414 | "type": "uint256" 415 | }, 416 | { 417 | "internalType": "bool", 418 | "name": "approveMax", 419 | "type": "bool" 420 | }, 421 | { 422 | "internalType": "uint8", 423 | "name": "v", 424 | "type": "uint8" 425 | }, 426 | { 427 | "internalType": "bytes32", 428 | "name": "r", 429 | "type": "bytes32" 430 | }, 431 | { 432 | "internalType": "bytes32", 433 | "name": "s", 434 | "type": "bytes32" 435 | } 436 | ], 437 | "name": "removeLiquidityETHWithPermit", 438 | "outputs": [ 439 | { 440 | "internalType": "uint256", 441 | "name": "amountToken", 442 | "type": "uint256" 443 | }, 444 | { 445 | "internalType": "uint256", 446 | "name": "amountETH", 447 | "type": "uint256" 448 | } 449 | ], 450 | "stateMutability": "nonpayable", 451 | "type": "function" 452 | }, 453 | { 454 | "inputs": [ 455 | { 456 | "internalType": "address", 457 | "name": "tokenA", 458 | "type": "address" 459 | }, 460 | { 461 | "internalType": "address", 462 | "name": "tokenB", 463 | "type": "address" 464 | }, 465 | { 466 | "internalType": "uint256", 467 | "name": "liquidity", 468 | "type": "uint256" 469 | }, 470 | { 471 | "internalType": "uint256", 472 | "name": "amountAMin", 473 | "type": "uint256" 474 | }, 475 | { 476 | "internalType": "uint256", 477 | "name": "amountBMin", 478 | "type": "uint256" 479 | }, 480 | { 481 | "internalType": "address", 482 | "name": "to", 483 | "type": "address" 484 | }, 485 | { 486 | "internalType": "uint256", 487 | "name": "deadline", 488 | "type": "uint256" 489 | }, 490 | { 491 | "internalType": "bool", 492 | "name": "approveMax", 493 | "type": "bool" 494 | }, 495 | { 496 | "internalType": "uint8", 497 | "name": "v", 498 | "type": "uint8" 499 | }, 500 | { 501 | "internalType": "bytes32", 502 | "name": "r", 503 | "type": "bytes32" 504 | }, 505 | { 506 | "internalType": "bytes32", 507 | "name": "s", 508 | "type": "bytes32" 509 | } 510 | ], 511 | "name": "removeLiquidityWithPermit", 512 | "outputs": [ 513 | { 514 | "internalType": "uint256", 515 | "name": "amountA", 516 | "type": "uint256" 517 | }, 518 | { 519 | "internalType": "uint256", 520 | "name": "amountB", 521 | "type": "uint256" 522 | } 523 | ], 524 | "stateMutability": "nonpayable", 525 | "type": "function" 526 | }, 527 | { 528 | "inputs": [ 529 | { 530 | "internalType": "uint256", 531 | "name": "amountOut", 532 | "type": "uint256" 533 | }, 534 | { 535 | "internalType": "address[]", 536 | "name": "path", 537 | "type": "address[]" 538 | }, 539 | { 540 | "internalType": "address", 541 | "name": "to", 542 | "type": "address" 543 | }, 544 | { 545 | "internalType": "uint256", 546 | "name": "deadline", 547 | "type": "uint256" 548 | } 549 | ], 550 | "name": "swapETHForExactTokens", 551 | "outputs": [ 552 | { 553 | "internalType": "uint256[]", 554 | "name": "amounts", 555 | "type": "uint256[]" 556 | } 557 | ], 558 | "stateMutability": "payable", 559 | "type": "function" 560 | }, 561 | { 562 | "inputs": [ 563 | { 564 | "internalType": "uint256", 565 | "name": "amountOutMin", 566 | "type": "uint256" 567 | }, 568 | { 569 | "internalType": "address[]", 570 | "name": "path", 571 | "type": "address[]" 572 | }, 573 | { 574 | "internalType": "address", 575 | "name": "to", 576 | "type": "address" 577 | }, 578 | { 579 | "internalType": "uint256", 580 | "name": "deadline", 581 | "type": "uint256" 582 | } 583 | ], 584 | "name": "swapExactETHForTokens", 585 | "outputs": [ 586 | { 587 | "internalType": "uint256[]", 588 | "name": "amounts", 589 | "type": "uint256[]" 590 | } 591 | ], 592 | "stateMutability": "payable", 593 | "type": "function" 594 | }, 595 | { 596 | "inputs": [ 597 | { 598 | "internalType": "uint256", 599 | "name": "amountIn", 600 | "type": "uint256" 601 | }, 602 | { 603 | "internalType": "uint256", 604 | "name": "amountOutMin", 605 | "type": "uint256" 606 | }, 607 | { 608 | "internalType": "address[]", 609 | "name": "path", 610 | "type": "address[]" 611 | }, 612 | { 613 | "internalType": "address", 614 | "name": "to", 615 | "type": "address" 616 | }, 617 | { 618 | "internalType": "uint256", 619 | "name": "deadline", 620 | "type": "uint256" 621 | } 622 | ], 623 | "name": "swapExactTokensForETH", 624 | "outputs": [ 625 | { 626 | "internalType": "uint256[]", 627 | "name": "amounts", 628 | "type": "uint256[]" 629 | } 630 | ], 631 | "stateMutability": "nonpayable", 632 | "type": "function" 633 | }, 634 | { 635 | "inputs": [ 636 | { 637 | "internalType": "uint256", 638 | "name": "amountIn", 639 | "type": "uint256" 640 | }, 641 | { 642 | "internalType": "uint256", 643 | "name": "amountOutMin", 644 | "type": "uint256" 645 | }, 646 | { 647 | "internalType": "address[]", 648 | "name": "path", 649 | "type": "address[]" 650 | }, 651 | { 652 | "internalType": "address", 653 | "name": "to", 654 | "type": "address" 655 | }, 656 | { 657 | "internalType": "uint256", 658 | "name": "deadline", 659 | "type": "uint256" 660 | } 661 | ], 662 | "name": "swapExactTokensForTokens", 663 | "outputs": [ 664 | { 665 | "internalType": "uint256[]", 666 | "name": "amounts", 667 | "type": "uint256[]" 668 | } 669 | ], 670 | "stateMutability": "nonpayable", 671 | "type": "function" 672 | }, 673 | { 674 | "inputs": [ 675 | { 676 | "internalType": "uint256", 677 | "name": "amountOut", 678 | "type": "uint256" 679 | }, 680 | { 681 | "internalType": "uint256", 682 | "name": "amountInMax", 683 | "type": "uint256" 684 | }, 685 | { 686 | "internalType": "address[]", 687 | "name": "path", 688 | "type": "address[]" 689 | }, 690 | { 691 | "internalType": "address", 692 | "name": "to", 693 | "type": "address" 694 | }, 695 | { 696 | "internalType": "uint256", 697 | "name": "deadline", 698 | "type": "uint256" 699 | } 700 | ], 701 | "name": "swapTokensForExactETH", 702 | "outputs": [ 703 | { 704 | "internalType": "uint256[]", 705 | "name": "amounts", 706 | "type": "uint256[]" 707 | } 708 | ], 709 | "stateMutability": "nonpayable", 710 | "type": "function" 711 | }, 712 | { 713 | "inputs": [ 714 | { 715 | "internalType": "uint256", 716 | "name": "amountOut", 717 | "type": "uint256" 718 | }, 719 | { 720 | "internalType": "uint256", 721 | "name": "amountInMax", 722 | "type": "uint256" 723 | }, 724 | { 725 | "internalType": "address[]", 726 | "name": "path", 727 | "type": "address[]" 728 | }, 729 | { 730 | "internalType": "address", 731 | "name": "to", 732 | "type": "address" 733 | }, 734 | { 735 | "internalType": "uint256", 736 | "name": "deadline", 737 | "type": "uint256" 738 | } 739 | ], 740 | "name": "swapTokensForExactTokens", 741 | "outputs": [ 742 | { 743 | "internalType": "uint256[]", 744 | "name": "amounts", 745 | "type": "uint256[]" 746 | } 747 | ], 748 | "stateMutability": "nonpayable", 749 | "type": "function" 750 | } 751 | ] 752 | --------------------------------------------------------------------------------