├── .gitignore ├── LICENSE ├── README-CN.md ├── README.md ├── app.html ├── assets ├── css │ ├── theme-antd.less │ └── theme.scss └── img │ └── common │ └── close.png ├── build ├── module │ ├── scss.txt │ ├── ts.txt │ └── vue.txt └── page.js ├── components ├── business │ └── TransactionDetail.vue └── ui │ ├── ZonCard.vue │ └── ZonModal.vue ├── jest.config.js ├── jsconfig.json ├── layouts └── default.vue ├── nuxt.config.js ├── package.json ├── pages ├── index.vue ├── newTransaction.vue └── tokenContract.vue ├── plugins ├── antd-ui.js ├── app.ts ├── filter.ts └── polyfill.ts ├── static └── favicon.ico ├── store ├── contract.ts └── index.ts ├── test └── Logo.spec.js ├── timelock ├── abi │ ├── cETH-abi.json │ ├── cToken-abi.json │ ├── comptroller-abi.json │ ├── timelock-abi.json │ └── unitroller-abi.json ├── constants.ts ├── contracts.ts ├── dataStorage.ts ├── error.ts ├── interface.ts ├── provider.ts ├── timelock.ts └── wallet.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | /logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE / Editor 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | 86 | # macOS 87 | .DS_Store 88 | 89 | # Vim swap files 90 | *.swp 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 unizon-blockchain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | # Unizon timelock admin 2 | 3 | ## 目标 4 | 5 | Timelock已经成为高质量DeFi项目的标配,是治理体系不可或缺的一部分,通过Timelock接管/限制超级用户对系统参数的修改,一方面可以避免管理员作恶或者攻击者获取管理员权限后对系统造成严重破坏,另一方面也可以给用户以更大的权限,在用户不同意某些治理措施时有足够的时间提前行动,避免资产遭受损失。 6 | 7 | 目前业内普遍采纳了一个标准timelock合约,如同本项目所包含的,包括Compound、SushiSwap等项目均采用。但是,合约的使用与管理却没有一个比较简单、通行的方案,目前比较典型的有两类:一种是Sushiswap采用的简单查询方式,即把timelock合约所涉及的所有交易查询出来,按时间顺序展示,而不关心具体业务的操作逻辑。参见:https://sushi-timelock.txs.wtf/ 。另一种是与治理体系结合的比较完整的方式,如:Compound官网上展现的。 8 | 9 | 目前我们尚未看到一个完整的、面向timelock使用和管理的开源项目,能够帮助DeFi开发者快速使用和管理timelock。这种情况下,一个DeFi项目的管理者,想要有效使用timelock,会遇到两个主要的问题。一是要有相当的开发量,自己合约对应的所有函数都要自己来编写对应的timelock调用,开发工作量大,正确性难以有保障。二是如果参考sushiswap这种流水账式的组织方式,则无法从业务的角度去使用和管理timelock,比如:发起一个timelock交易修改平台的某个参数,并且在两天后timelock允许生效时对这个交易进行确认,这是一个典型的场景。但在Sushiswap这种原始的查询方式中,无法知道当前timelock中有哪些待执行交易、内容是什么,必须去浏览全部的,混杂在一起的各种交易(发起、确认、取消等),找到当初发起的交易再执行。 10 | 11 | 我们认为,一个有效的timelock管理框架,应当做到两点:一方面应当让项目通过配置的方式就可以将自己需要管理的方法交由timelock实现,无需大量的开发工作。另一方面数据组织形式应该更贴合业务逻辑,采用基于业务的组织方式,将QueueTransaction与ExecuteTransaction/CancelTransaction匹配、组织起来,简化管理员的工作。 12 | 13 | 这就是Unizon timelock Admin项目的来源。 14 | 15 | ## 功能简介 16 | 17 | 通用的timelock管理DAPP,通过修改配置文件即可实现timelock交易展示、queueTransaction、executeTransaction、cancelTransaction功能 18 | 19 | 修改/timelock/constants.ts文件更改配置文件(本配置以compound为例): 20 | 21 | ```javascript 22 | /** 23 | * timelock管理的合约地址,本配置以compound为例 24 | */ 25 | export const contract_address : any = { 26 | 3: { 27 | 'unitroller': '0x52Ab60E7F463B73C6A90ee116dBB18ac61DC63FF', 28 | 'comptroller': '0x52Ab60E7F463B73C6A90ee116dBB18ac61DC63FF', 29 | 'cToken1': '', 30 | 'cToken2': '', 31 | 'cTokenn': '' 32 | }, 33 | 1: { 34 | 'unitroller': '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B', 35 | 'comptroller': '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B', 36 | 'cToken1': '', 37 | 'cToken2': '', 38 | 'cTokenn': '' 39 | } 40 | } 41 | 42 | /** 43 | * timelock管理的合约所对应的abi文件, abi文件需拷贝至/timelock/abi目录 44 | */ 45 | 46 | export const contract_abi_file : any = { 47 | 'unitroller': 'unitroller-abi.json', 48 | 'comptroller': 'comptroller-abi.json', 49 | 'cToken1': 'cToken-abi.json', 50 | 'cToken2': 'cToken-abi.json', 51 | 'cTokenn': 'cToken-abi.json' 52 | } 53 | 54 | /** 55 | * deplay Offset, unit: seconds 56 | */ 57 | export const delay_offset = 300; 58 | 59 | /** 60 | * timelock合约地址, 分别为mainnet和ropsten,其中主网为compound timelock 合约地址 61 | */ 62 | export const timelock_address : any = { 63 | 1: '0x6d903f6003cca6255D85CcA4D3B5E5146dC33925', 64 | 3: '0x4168FE8179C5e99074068244413909F40c4301B2' 65 | } 66 | 67 | /** 68 | * timelock管理的合约需要执行queueTransaction的函数列表 69 | */ 70 | 71 | export const queue_functions : any = { 72 | 'unitroller': ['_acceptAdmin', '_setPendingAdmin', '_setPendingImplementation'], 73 | 'comptroller': ['_become', '_setBorrowPaused', '_setMiningBuff', '_setCompRate', '_setMintPaused', '_supportMarket', '_dropCompMarket', '_setPriceOracle', '_setCollateralFactor'], 74 | 'cToken1': ['_acceptAdmin', '_setReserveFactor'], 75 | 'cToken2': ['_acceptAdmin', '_setReserveFactor'], 76 | 'cTokenn': ['_acceptAdmin', '_setReserveFactor'] 77 | } 78 | 79 | ``` 80 | ## 运行及部署 81 | 82 | ### 运行: 83 | 84 | 在项目根目录执行 85 | 86 | ```shell 87 | yarn 88 | yarn dev 89 | ``` 90 | 91 | ### 部署: 92 | 93 | 在项目根目录执行 94 | 95 | ```shell 96 | yarn build 97 | ``` 98 | 通过nginx/apache部署./dist目录即可 99 | 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unizon timelock admin 2 | Through the Timelock admin dapp interface, editing these settings below can allow for timelocked transactions via the queueTransaction, executeTransaction, and cancelTransaction functions. 3 | 4 | Please edit the /timelock/constants.ts file for the contract you wish to support - the original settings are designed for compound as an example 5 | 6 | 7 | ```javascript 8 | /** 9 | * Timelock admin smart contract address 10 | */ 11 | export const contract_address : any = { 12 | 3: { 13 | 'unitroller': '0x52Ab60E7F463B73C6A90ee116dBB18ac61DC63FF', 14 | 'comptroller': '0x52Ab60E7F463B73C6A90ee116dBB18ac61DC63FF', 15 | 'cToken1': '', 16 | 'cToken2': '', 17 | 'cTokenn': '' 18 | }, 19 | 1: { 20 | 'unitroller': '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B', 21 | 'comptroller': '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B', 22 | 'cToken1': '', 23 | 'cToken2': '', 24 | 'cTokenn': '' 25 | } 26 | } 27 | 28 | /** 29 | * all abi’s that the timelock admin contract interacts with (/timelock/abi) 30 | */ 31 | 32 | export const contract_abi_file : any = { 33 | 'unitroller': 'unitroller-abi.json', 34 | 'comptroller': 'comptroller-abi.json', 35 | 'cToken1': 'cToken-abi.json', 36 | 'cToken2': 'cToken-abi.json', 37 | 'cTokenn': 'cToken-abi.json' 38 | } 39 | 40 | /** 41 | * deplay Offset, unit: seconds 42 | */ 43 | export const delay_offset = 300; 44 | 45 | /** 46 | * timelock contract address dictionary for mainnet and ropsten (add other chains if necessary, compound addresses * added as example) 47 | */ 48 | export const timelock_address : any = { 49 | 1: '0x6d903f6003cca6255D85CcA4D3B5E5146dC33925', 50 | 3: '0x4168FE8179C5e99074068244413909F40c4301B2' 51 | } 52 | 53 | /** 54 | * Timelock admin contact requires the execution of the queueTransaction function using the specified parameters 55 | */ 56 | 57 | export const queue_functions : any = { 58 | 'unitroller': ['_acceptAdmin', '_setPendingAdmin', '_setPendingImplementation'], 59 | 'comptroller': ['_become', '_setBorrowPaused', '_setMiningBuff', '_setCompRate', '_setMintPaused', '_supportMarket', '_dropCompMarket', '_setPriceOracle', '_setCollateralFactor'], 60 | 'cToken1': ['_acceptAdmin', '_setReserveFactor'], 61 | 'cToken2': ['_acceptAdmin', '_setReserveFactor'], 62 | 'cTokenn': ['_acceptAdmin', '_setReserveFactor'] 63 | } 64 | 65 | ``` 66 | ## Run and deploy 67 | 68 | ### Run: 69 | 70 | Execute in the project root directory 71 | 72 | ```shell 73 | yarn 74 | yarn dev 75 | ``` 76 | 77 | ### Deploy: 78 | 79 | Execute in the project root directory 80 | 81 | ```shell 82 | yarn build 83 | ``` 84 | Deploy the ./dist directory through nginx/apache 85 | 86 | ## Support Languages 87 | 88 | ### [CN](./README-CN.md) 89 | 90 | -------------------------------------------------------------------------------- /app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ HEAD }} 9 | 10 | 11 | 12 | {{ APP }} 13 | 14 | 15 | -------------------------------------------------------------------------------- /assets/css/theme-antd.less: -------------------------------------------------------------------------------- 1 | // @import '~ant-design-vue/dist/antd.less'; // 引入官方提供的 less 样式入口文件 2 | 3 | @import '~/node_modules/ant-design-vue/lib/button/style/index.less'; 4 | @import '~/node_modules/ant-design-vue/lib/steps/style/index.less'; 5 | @import '~/node_modules/ant-design-vue/lib/form/style/index.less'; 6 | @import '~/node_modules/ant-design-vue/lib/input/style/index.less'; 7 | @import '~/node_modules/ant-design-vue/lib/select/style/index.less'; 8 | @import '~/node_modules/ant-design-vue/lib/progress/style/index.less'; 9 | @import '~/node_modules/ant-design-vue/lib/avatar/style/index.less'; 10 | @import '~/node_modules/ant-design-vue/lib/table/style/index.less'; 11 | @import '~/node_modules/ant-design-vue/lib/dropdown/style/index.less'; 12 | @import '~/node_modules/ant-design-vue/lib/menu/style/index.less'; 13 | @import '~/node_modules/ant-design-vue/lib/message/style/index.less'; 14 | @import '~/node_modules/ant-design-vue/lib/modal/style/index.less'; 15 | @import '~/node_modules/ant-design-vue/lib/form-model/style/index.less'; 16 | @import '~/node_modules/ant-design-vue/lib/drawer/style/index.less'; 17 | @import '~/node_modules/ant-design-vue/lib/slider/style/index.less'; 18 | @import '~/node_modules/ant-design-vue/lib/switch/style/index.less'; 19 | @import '~/node_modules/ant-design-vue/lib/spin/style/index.less'; 20 | @import '~/node_modules/ant-design-vue/lib/input-number/style/index.less'; 21 | @import '~/node_modules/ant-design-vue/lib/notification/style/index.less'; 22 | @import '~/node_modules/ant-design-vue/lib/skeleton/style/index.less'; 23 | @import '~/node_modules/ant-design-vue/lib/tooltip/style/index.less'; 24 | @import '~/node_modules/ant-design-vue/lib/collapse/style/index.less'; 25 | @import '~/node_modules/ant-design-vue/lib/tag/style/index.less'; 26 | 27 | .ant-skeleton.ant-skeleton-active 28 | .ant-skeleton-content 29 | .ant-skeleton-paragraph 30 | > li { 31 | background: linear-gradient(90deg, #242424 65%, #262626 47%, #2e2e2e 83%); 32 | background-size: 400% 100%; 33 | -webkit-animation: ant-skeleton-loading 1.4s ease infinite; 34 | animation: ant-skeleton-loading 1.4s ease infinite; 35 | } 36 | 37 | html, 38 | body { 39 | /* 苹方-简 中黑体 */ 40 | font-family: PingFangSC-Medium, sans-serif; 41 | font-size: 15px; 42 | word-spacing: 1px; 43 | -ms-text-size-adjust: 100%; 44 | -webkit-text-size-adjust: 100%; 45 | -moz-osx-font-smoothing: grayscale; 46 | -webkit-font-smoothing: antialiased; 47 | box-sizing: border-box; 48 | overflow: auto; 49 | background-color: #080808; 50 | } 51 | 52 | body { 53 | min-height: 100vh; 54 | scroll-behavior: smooth; 55 | text-rendering: optimizeSpeed; 56 | } 57 | 58 | *, 59 | *::before, 60 | *::after { 61 | box-sizing: border-box; 62 | margin: 0; 63 | padding: 0; 64 | } 65 | 66 | /* Box sizing rules */ 67 | *, 68 | *::before, 69 | *::after { 70 | box-sizing: border-box; 71 | } 72 | 73 | /* Remove default padding */ 74 | ul[class], 75 | ol[class] { 76 | padding: 0; 77 | } 78 | 79 | /* Remove default margin */ 80 | body, 81 | h1, 82 | h2, 83 | h3, 84 | h4, 85 | p, 86 | ul[class], 87 | ol[class], 88 | figure, 89 | blockquote, 90 | dl, 91 | dd { 92 | margin: 0; 93 | } 94 | 95 | /* Remove list styles on ul, ol elements with a class attribute */ 96 | ul[class], 97 | ol[class] { 98 | list-style: none; 99 | } 100 | 101 | ul, 102 | ol { 103 | list-style: none; 104 | margin: 0; 105 | padding: 0; 106 | } 107 | 108 | p { 109 | margin: 0; 110 | } 111 | 112 | /* A elements that don't have a class get default styles */ 113 | a:not([class]) { 114 | text-decoration-skip-ink: auto; 115 | } 116 | 117 | /* Make images easier to work with */ 118 | img { 119 | max-width: 100%; 120 | display: block; 121 | } 122 | 123 | /* Natural flow and rhythm in articles by default */ 124 | article > * + * { 125 | margin-top: 1em; 126 | } 127 | 128 | /* Inherit fonts for inputs and buttons */ 129 | input, 130 | button, 131 | textarea, 132 | select { 133 | font: inherit; 134 | } 135 | 136 | /* Remove all animations and transitions for people that prefer not to see them */ 137 | @media (prefers-reduced-motion: reduce) { 138 | * { 139 | animation-duration: 0.01ms !important; 140 | animation-iteration-count: 1 !important; 141 | transition-duration: 0.01ms !important; 142 | scroll-behavior: auto !important; 143 | } 144 | } 145 | 146 | /* 自定义滚动条(chrome) */ 147 | .z-scroll::-webkit-scrollbar { 148 | width: 6px; 149 | height: 4px; 150 | background: #eeeeee; 151 | /* 整个滚条背景 */ 152 | } 153 | 154 | .z-scroll::-webkit-scrollbar-thumb { 155 | border-radius: 0px; 156 | background: #bbbbbb; 157 | /* 滚条内嵌颜色 */ 158 | } 159 | 160 | .z-scroll::-webkit-scrollbar-button { 161 | background-color: #bbbbbb; 162 | width: 0; 163 | height: 0; 164 | /* 两边端按钮颜色 */ 165 | } 166 | 167 | *::-webkit-scrollbar { 168 | width: 6px; 169 | height: 4px; 170 | background: #eeeeee; 171 | /* 整个滚条背景 */ 172 | } 173 | 174 | *::-webkit-scrollbar-thumb { 175 | border-radius: 0px; 176 | background: #bbbbbb; 177 | /* 滚条内嵌颜色 */ 178 | } 179 | 180 | *::-webkit-scrollbar-button { 181 | background-color: #bbbbbb; 182 | width: 0; 183 | height: 0; 184 | /* 两边端按钮颜色 */ 185 | } 186 | 187 | /* 布局控制 */ 188 | .is-pc { 189 | display: block; 190 | } 191 | .is-mobile { 192 | display: none; 193 | } 194 | 195 | 196 | @media only screen and (max-width: 880px) { 197 | .is-pc { 198 | display: none; 199 | } 200 | .is-mobile { 201 | display: block; 202 | } 203 | .t-default-main--padding { 204 | padding: 0 !important; 205 | } 206 | .ant-modal { 207 | width: 90% !important; 208 | } 209 | } 210 | /* ******** */ 211 | 212 | /* antd-reload */ 213 | .ant-table-placeholder { 214 | background: transparent; 215 | color: rgba(255, 255, 255, 0.6); 216 | border: none; 217 | } 218 | 219 | .ant-select-dropdown-menu { 220 | border-radius: 2px; 221 | 222 | .ant-select-dropdown-menu-item { 223 | background-color: #000000; 224 | color: #ffffff; 225 | font-size: 14px; 226 | box-sizing: border-box; 227 | padding: 8px 12px; 228 | } 229 | .ant-select-dropdown-menu-item:active { 230 | background-color: rgba(0, 0, 0, 0.9); 231 | } 232 | .ant-select-dropdown-menu-item:hover { 233 | background-color: rgba(0, 0, 0, 0.9); 234 | } 235 | .ant-select-dropdown-menu-item-selected { 236 | background-color: rgba(0, 0, 0, 0.9); 237 | } 238 | } 239 | 240 | .ant-dropdown-menu { 241 | .ant-dropdown-menu-item { 242 | background-color: #000000; 243 | color: #ffffff; 244 | font-size: 14px; 245 | box-sizing: border-box; 246 | padding: 8px 12px; 247 | } 248 | .ant-dropdown-menu-item:active { 249 | background-color: rgba(0, 0, 0, 0.9); 250 | } 251 | .ant-dropdown-menu-item:hover { 252 | background-color: rgba(0, 0, 0, 0.9); 253 | } 254 | } 255 | 256 | .ant-btn-primary { 257 | color: #565656 !important; 258 | } 259 | 260 | /* =========================== */ -------------------------------------------------------------------------------- /assets/css/theme.scss: -------------------------------------------------------------------------------- 1 | /* mixin */ 2 | @function vpx($px) { 3 | // @return $px / (19.2) * 1vw; 4 | @return $px * 0.9px; 5 | } 6 | 7 | @function rpx($px) { 8 | @return $px / (7.5) * 1vw; 9 | // @return $px / 2 * 1px; 10 | } 11 | -------------------------------------------------------------------------------- /assets/img/common/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unizon-blockchain/timelock/0c5788dd7229dc69ff00e81387955470f4c9abcf/assets/img/common/close.png -------------------------------------------------------------------------------- /build/module/scss.txt: -------------------------------------------------------------------------------- 1 | // scss -------------------------------------------------------------------------------- /build/module/ts.txt: -------------------------------------------------------------------------------- 1 | import { Vue, Component } from 'vue-property-decorator' 2 | 3 | @Component 4 | class #component# extends Vue { 5 | // props 6 | } 7 | 8 | export default #component# 9 | -------------------------------------------------------------------------------- /build/module/vue.txt: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /build/page.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const nodePath = require('path') 3 | const color = require('colors') 4 | 5 | const stat = fs.stat; 6 | 7 | console.log('根路径:', process.env.INIT_CWD) 8 | 9 | function pathResolve(path) { 10 | return nodePath.resolve(__dirname, path) 11 | } 12 | 13 | function wrapPromise(fn) { 14 | return new Promise((resolve, reject) => { 15 | fn(resolve, reject) 16 | }) 17 | } 18 | 19 | function firstToUpperCase(str) { 20 | return str.replace(str[0], str[0].toUpperCase()) 21 | } 22 | 23 | const options = process.argv.splice(2) 24 | const targetPath = options[0] 25 | 26 | 27 | console.log(`\nCreate file: ${targetPath}\n`.green) 28 | 29 | const modulePath = '../build/module' 30 | const outputPath = '../pages' 31 | 32 | let moduleFile = { 33 | vue: `${modulePath}\\vue.txt`, 34 | ts: `${modulePath}\\ts.txt`, 35 | scss: `${modulePath}\\scss.txt` 36 | } 37 | 38 | // yarn p user/login 39 | 40 | const targetPathSplit = targetPath.split('/') 41 | 42 | const fileNamePrefix = outputPath + '/' + (targetPath.indexOf('/') > -1 ? targetPath.substring(0, targetPath.lastIndexOf("/")) : targetPath) 43 | const filename = targetPathSplit.length > 0 ? targetPathSplit[targetPathSplit.length - 1] : targetPath 44 | 45 | const outputFile = { 46 | vue: `${outputPath}\\${targetPath}.vue`, 47 | ts: `${outputPath}\\${targetPath}.ts`, 48 | scss: `${outputPath}\\${targetPath}.scss` 49 | } 50 | 51 | /** 52 | * 替换 vue 模板内容 53 | * @param {*} data 54 | */ 55 | function replaceVue(content) { 56 | content = content.replace(/#path#/g, filename) 57 | return content 58 | } 59 | 60 | /** 61 | * 替换模板 ts 内容 62 | * @param {*} data 63 | */ 64 | function replaceTs(content) { 65 | content = content.replace(/#component#/g, firstToUpperCase(filename)) 66 | return content 67 | } 68 | 69 | /** 70 | * 文件是否已存在 71 | * @param {*} output 72 | */ 73 | async function exists(output) { 74 | return await wrapPromise(resolve => { 75 | //测试某个路径下文件是否存在 76 | fs.exists(pathResolve(output), function (exists) { 77 | if (exists) {//存在 78 | resolve(true) 79 | } else {//不存在 80 | resolve(false) 81 | } 82 | }) 83 | }) 84 | } 85 | 86 | /** 87 | * 创建文件夹 88 | * @param {*} path 89 | */ 90 | async function createDir(path) { 91 | return await wrapPromise(resolve => { 92 | fs.mkdir(path, { recursive: true }, (err) => {//创建目录 93 | if (err) { 94 | resolve(false) 95 | } 96 | resolve(true) 97 | }) 98 | }) 99 | } 100 | 101 | /** 102 | * 读取文件内容 103 | * @param {*} path 104 | */ 105 | async function readFile(path) { 106 | return await wrapPromise(resolve => { 107 | fs.readFile(nodePath.join(__dirname, path), 'utf8', (err, data) => { 108 | if (err) { resolve(null) } 109 | resolve(data) 110 | }) 111 | }) 112 | } 113 | 114 | /** 115 | * 创建并写入文件 116 | * @param {*} path 117 | * @param {*} data 118 | */ 119 | async function writeFile(path, data) { 120 | return await wrapPromise(resolve => { 121 | fs.writeFile(nodePath.join(__dirname, path), data, 'utf8', (err) => { 122 | if (err) return false; 123 | resolve(true) 124 | }) 125 | }) 126 | } 127 | 128 | /** 129 | * 是否存在原文件,true: 替换模板文件路径为已存在文件路径 130 | */ 131 | async function isExistsOriginalFile() { 132 | const isVueExists = await exists(outputFile.vue) 133 | moduleFile.vue = isVueExists ? outputFile.vue : moduleFile.vue 134 | const isTsExists = await exists(outputFile.ts) 135 | moduleFile.ts = isTsExists ? outputFile.ts : moduleFile.ts 136 | const isScssExists = await exists(outputFile.scss) 137 | moduleFile.scss = isScssExists ? outputFile.scss : moduleFile.scss 138 | } 139 | 140 | /** 141 | * 数据读取并生成文件 142 | */ 143 | async function generateFile() { 144 | await isExistsOriginalFile() 145 | let vuePath = moduleFile.vue 146 | const tsPath = moduleFile.ts 147 | const scssPath = moduleFile.scss 148 | 149 | const vueData = await readFile(vuePath) 150 | vueData && await writeFile(outputFile.vue, replaceVue(vueData)) 151 | const tsData = await readFile(tsPath) 152 | tsData && await writeFile(outputFile.ts, replaceTs(tsData)) 153 | const scssData = await readFile(scssPath) 154 | scssData && await writeFile(outputFile.scss, scssData) 155 | 156 | return true 157 | } 158 | 159 | /** 160 | * 初始化 161 | */ 162 | async function initialize() { 163 | const filePath = pathResolve(`${fileNamePrefix}`) 164 | 165 | const isExists = await exists(filePath) 166 | if (!isExists) { 167 | await createDir(filePath) 168 | } 169 | await generateFile() 170 | 171 | console.log('√ Generated Successful!'.green) 172 | } 173 | 174 | initialize() -------------------------------------------------------------------------------- /components/business/TransactionDetail.vue: -------------------------------------------------------------------------------- 1 | 82 | 83 | 192 | 193 | -------------------------------------------------------------------------------- /components/ui/ZonCard.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /components/ui/ZonModal.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 71 | 72 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | '^@/(.*)$': '/$1', 4 | '^~/(.*)$': '/$1', 5 | '^vue$': 'vue/dist/vue.common.js', 6 | }, 7 | moduleFileExtensions: ['ts', 'js', 'vue', 'json'], 8 | transform: { 9 | '^.+\\.ts$': 'ts-jest', 10 | '^.+\\.js$': 'babel-jest', 11 | '.*\\.(vue)$': 'vue-jest', 12 | }, 13 | collectCoverage: true, 14 | collectCoverageFrom: [ 15 | '/components/**/*.vue', 16 | '/pages/**/*.vue', 17 | ], 18 | } 19 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "~/*": ["./*"], 6 | "@/*": ["./*"], 7 | "~~/*": ["./*"], 8 | "@@/*": ["./*"] 9 | } 10 | }, 11 | "exclude": ["node_modules", ".nuxt", "dist"] 12 | } 13 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 44 | 94 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | /* 3 | ** Nuxt rendering mode 4 | ** See https://nuxtjs.org/api/configuration-mode 5 | */ 6 | mode: 'spa', 7 | /* 8 | ** Nuxt target 9 | ** See https://nuxtjs.org/api/configuration-target 10 | */ 11 | target: 'server', 12 | /* 13 | ** Headers of the page 14 | ** See https://nuxtjs.org/api/configuration-head 15 | */ 16 | server: { 17 | port: 3001, // default: 3000 18 | host: '0.0.0.0' // default: localhost, 19 | }, 20 | head: { 21 | title: 'Unizon Timelock Admin', 22 | meta: [ 23 | { charset: 'utf-8' }, 24 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 25 | { 26 | hid: 'description', 27 | name: 'description', 28 | content: process.env.npm_package_description || '', 29 | }, 30 | ], 31 | link: [ 32 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, 33 | ], 34 | // vendor: ['vue-i18n'], 35 | }, 36 | /* 37 | ** Global CSS 38 | */ 39 | css: [ 40 | '@/assets/css/theme-antd.less' 41 | ], 42 | /** 43 | * global scss 44 | */ 45 | styleResources: { 46 | scss: './assets/css/theme.scss', 47 | }, 48 | /* 49 | ** Plugins to load before mounting the App 50 | ** https://nuxtjs.org/guide/plugins 51 | */ 52 | plugins: [ 53 | '@/plugins/polyfill.ts', 54 | '@/plugins/antd-ui.js', 55 | '@/plugins/filter.ts', 56 | '@/plugins/app.ts', 57 | ], 58 | /* 59 | ** Auto import components 60 | ** See https://nuxtjs.org/api/configuration-components 61 | */ 62 | components: true, 63 | /* 64 | ** Nuxt.js dev-modules 65 | */ 66 | buildModules: ['@nuxt/typescript-build'], 67 | /* 68 | ** Nuxt.js modules 69 | */ 70 | modules: [ 71 | // Doc: https://axios.nuxtjs.org/usage 72 | '@nuxtjs/axios', 73 | '@nuxtjs/style-resources' 74 | ], 75 | /* 76 | ** Axios module configuration 77 | ** See https://axios.nuxtjs.org/options 78 | */ 79 | axios: {}, 80 | /* 81 | ** Build configuration 82 | ** See https://nuxtjs.org/api/configuration-build/ 83 | */ 84 | build: { 85 | analyze: false, 86 | assetFilter: function (assetFilename) { 87 | return assetFilename.endsWith('.js'); 88 | }, 89 | maxChunkSize: 30000, 90 | loaders: { 91 | less: { 92 | lessOptions: { 93 | javascriptEnabled: true, 94 | modifyVars: { 95 | 'primary-color': '#ddbd31' 96 | } 97 | } 98 | } 99 | }, 100 | extend (config, { isDev, isClient }) { 101 | if (isClient && !isDev) { 102 | config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true 103 | } 104 | } 105 | }, 106 | loading: false, 107 | resourceHints: false 108 | } 109 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unizon-timelock-admin", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxt", 7 | "build": "nuxt-ts build", 8 | "start": "nuxt-ts start", 9 | "export": "nuxt-ts export", 10 | "serve": "nuxt-ts serve", 11 | "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .", 12 | "lint": "yarn lint:js", 13 | "test": "jest", 14 | "page": "node build/page.js user/login", 15 | "p": "node build/page.js" 16 | }, 17 | "dependencies": { 18 | "@nuxt/typescript-runtime": "^0.4.10", 19 | "@nuxtjs/axios": "^5.11.0", 20 | "abi-decoder": "^2.3.0", 21 | "ant-design-vue": "^1.6.4", 22 | "bignumber.js": "^9.0.1", 23 | "date-fns": "^2.16.1", 24 | "ethers": "^5.0.14", 25 | "nuxt": "^2.13.0", 26 | "vue-i18n": "^8.21.0", 27 | "vue-rx": "^6.2.0" 28 | }, 29 | "devDependencies": { 30 | "@nuxt/typescript-build": "^1.0.3", 31 | "@nuxtjs/eslint-config": "^3.0.0", 32 | "@nuxtjs/eslint-config-typescript": "^2.0.0", 33 | "@nuxtjs/eslint-module": "^2.0.0", 34 | "@nuxtjs/style-resources": "^1.0.0", 35 | "@vue/test-utils": "^1.0.3", 36 | "antd-scss-theme-plugin": "^1.0.8", 37 | "babel-core": "7.0.0-bridge.0", 38 | "babel-eslint": "^10.1.0", 39 | "babel-jest": "^26.0.1", 40 | "babel-polyfill": "^6.26.0", 41 | "babel-preset-stage-3": "^6.24.1", 42 | "dart-sass": "^1.25.0", 43 | "eslint": "^7.2.0", 44 | "eslint-config-prettier": "^6.11.0", 45 | "eslint-plugin-nuxt": "^1.0.0", 46 | "eslint-plugin-prettier": "^3.1.4", 47 | "jest": "^26.0.1", 48 | "less": "^3.12.2", 49 | "less-loader": "^6.2.0", 50 | "prettier": "^2.0.5", 51 | "sass": "^1.26.10", 52 | "sass-loader": "^9.0.3", 53 | "ts-jest": "^26.1.0", 54 | "vue-class-component": "^7.2.5", 55 | "vue-jest": "^3.0.4", 56 | "vue-property-decorator": "^9.0.0" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 80 | 81 | 220 | 221 | 239 | -------------------------------------------------------------------------------- /pages/newTransaction.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 84 | 85 | -------------------------------------------------------------------------------- /pages/tokenContract.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 149 | 150 | -------------------------------------------------------------------------------- /plugins/antd-ui.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import { 4 | Button, 5 | Steps, 6 | Form, 7 | Input, 8 | Select, 9 | Progress, 10 | Avatar, 11 | Row, 12 | Col, 13 | Table, 14 | Menu, 15 | Dropdown, 16 | Icon, 17 | Modal, 18 | FormModel, 19 | Drawer, 20 | Slider, 21 | Switch, 22 | Spin, 23 | InputNumber, 24 | Skeleton, 25 | Tooltip, 26 | Popconfirm, 27 | Collapse, 28 | message, 29 | notification, 30 | Tag 31 | } from 'ant-design-vue' 32 | 33 | import 'ant-design-vue/lib/row/style' 34 | import 'ant-design-vue/lib/col/style' 35 | import 'ant-design-vue/lib/popconfirm/style' 36 | 37 | Vue.use(Button) 38 | Vue.use(Steps) // 步骤条 39 | Vue.use(Form) 40 | Vue.use(Form.Item) 41 | Vue.use(Input) 42 | Vue.use(Select) 43 | Vue.use(Progress) 44 | Vue.use(Avatar) 45 | Vue.use(Row) 46 | Vue.use(Col) 47 | Vue.use(Table) 48 | Vue.use(Menu) 49 | Vue.use(Dropdown) 50 | Vue.use(Icon) 51 | Vue.use(Modal) 52 | Vue.use(FormModel) 53 | Vue.use(FormModel.Item) 54 | Vue.use(Drawer) 55 | Vue.use(Slider) 56 | Vue.use(Switch) 57 | Vue.use(Skeleton) 58 | Vue.use(Spin) 59 | Vue.use(InputNumber) 60 | Vue.use(Tooltip) 61 | Vue.use(Popconfirm) 62 | Vue.use(Collapse) 63 | Vue.use(Tag) 64 | 65 | Vue.prototype.$message = message 66 | Vue.prototype.$notification = notification -------------------------------------------------------------------------------- /plugins/app.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import EthereumProvider from '~/timelock/provider'; 3 | 4 | declare module 'vue/types/vue' { 5 | interface Vue { 6 | $useEthereumProvider(callback: any): void; 7 | $ethereumProvider: EthereumProvider; 8 | $useConnectWallet(): void; 9 | $getEtherScanUrl(txHash: any): string; 10 | $getNetworkName(): string; 11 | } 12 | } 13 | 14 | let ethereumProvider: EthereumProvider; 15 | 16 | export default ({ app, store }: any) => { 17 | if ('undefined' === typeof ethereumProvider) { 18 | ethereumProvider = new EthereumProvider(); 19 | } 20 | 21 | async function useConnectWallet() { 22 | const account: string | null = await ethereumProvider.connect(); 23 | store.commit('SET_ACCOUNT', account); 24 | } 25 | 26 | Vue.prototype.$useConnectWallet = useConnectWallet; 27 | 28 | Vue.prototype.$useEthereumProvider = async function (callback: any) { 29 | try { 30 | ethereumProvider.monitor({ 31 | accountChanged: async (account: any) => { 32 | store.commit('SET_ACCOUNT', account); 33 | 'function' === typeof callback && callback(); 34 | }, 35 | chainChanged: async (chainId: any) => { 36 | store.commit('SET_CHAIN_ID', chainId); 37 | 'function' === typeof callback && callback(); 38 | }, 39 | }); 40 | 41 | Vue.prototype.$ethereumProvider = ethereumProvider; 42 | 43 | useConnectWallet(); 44 | } catch (e) {} 45 | } 46 | 47 | Vue.prototype.$getEtherScanUrl = function(txHash: any): string { 48 | let res : string = `https://etherscan.io/tx/${txHash}`; 49 | 50 | if(3 == ethereumProvider.chainId) { 51 | res = `https://ropsten.etherscan.io/tx/${txHash}`; 52 | } 53 | if(4 == ethereumProvider.chainId) { 54 | res = `https://rinkeby.etherscan.io/tx/${txHash}`; 55 | } 56 | if(42 == ethereumProvider.chainId) { 57 | res = `https://kovan.etherscan.io/tx/${txHash}`; 58 | } 59 | 60 | return res; 61 | } 62 | 63 | Vue.prototype.$getNetworkName = function() { 64 | let res : string = ''; 65 | switch(ethereumProvider.chainId) { 66 | case 1: 67 | res = ''; 68 | break; 69 | case 3: 70 | res = 'ropsten'; 71 | break; 72 | case 4: 73 | res = 'rinkeby'; 74 | break; 75 | case 42: 76 | res = 'kovan'; 77 | break; 78 | default: 79 | res = 'unknown'; 80 | break; 81 | } 82 | 83 | return res; 84 | } 85 | 86 | 87 | }; 88 | -------------------------------------------------------------------------------- /plugins/filter.ts: -------------------------------------------------------------------------------- 1 | import { Vue } from 'vue-property-decorator' 2 | 3 | declare module 'vue/types/vue' { 4 | interface Vue { 5 | $filter: any 6 | } 7 | } 8 | 9 | export default ({ app, store }: any) => { 10 | Vue.filter('parseLocalDateTime', function (value: number) { 11 | const dt = new Date(value * 1000); 12 | return dt.toUTCString(); 13 | }) 14 | 15 | const addressFormat = (value: string, Digits: number = 4) => { 16 | let data = 17 | '0x' + 18 | value.toString().substring(2, Digits + 2) + 19 | '...' + 20 | value.substring(value.length, value.length - Digits) 21 | return data 22 | } 23 | Vue.filter('addressFormat', addressFormat) 24 | 25 | Vue.prototype.$filter = { 26 | addressFormat 27 | } 28 | } -------------------------------------------------------------------------------- /plugins/polyfill.ts: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill' 2 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unizon-blockchain/timelock/0c5788dd7229dc69ff00e81387955470f4c9abcf/static/favicon.ico -------------------------------------------------------------------------------- /store/contract.ts: -------------------------------------------------------------------------------- 1 | import { ITokenContract } from '~/timelock/interface'; 2 | 3 | export const state = () => ({ 4 | tokenContract: {} 5 | }) 6 | 7 | export const mutations = { 8 | SET_TOKEN_CONTRACT(state: any, value: ITokenContract) { 9 | state.tokenContract = { ...value }; 10 | } 11 | } -------------------------------------------------------------------------------- /store/index.ts: -------------------------------------------------------------------------------- 1 | export const state = () => ({ 2 | account: '', 3 | chainId: '' 4 | }) 5 | export const mutations = { 6 | SET_ACCOUNT(state: any, account: any): void { 7 | state.account = account || '' 8 | }, 9 | SET_CHAIN_ID(state: any, chainId: any): void { 10 | state.chainId = chainId || '' 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /test/Logo.spec.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils' 2 | import Logo from '@/components/Logo.vue' 3 | 4 | describe('Logo', () => { 5 | test('is a Vue instance', () => { 6 | const wrapper = mount(Logo) 7 | expect(wrapper.vm).toBeTruthy() 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /timelock/abi/cETH-abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant":true, 4 | "inputs":[ 5 | 6 | ], 7 | "name":"name", 8 | "outputs":[ 9 | { 10 | "name":"", 11 | "type":"string" 12 | } 13 | ], 14 | "payable":false, 15 | "stateMutability":"view", 16 | "type":"function", 17 | "signature":"0x06fdde03" 18 | }, 19 | { 20 | "constant":false, 21 | "inputs":[ 22 | { 23 | "name":"spender", 24 | "type":"address" 25 | }, 26 | { 27 | "name":"amount", 28 | "type":"uint256" 29 | } 30 | ], 31 | "name":"approve", 32 | "outputs":[ 33 | { 34 | "name":"", 35 | "type":"bool" 36 | } 37 | ], 38 | "payable":false, 39 | "stateMutability":"nonpayable", 40 | "type":"function", 41 | "signature":"0x095ea7b3" 42 | }, 43 | { 44 | "constant":false, 45 | "inputs":[ 46 | 47 | ], 48 | "name":"mint", 49 | "outputs":[ 50 | 51 | ], 52 | "payable":true, 53 | "stateMutability":"payable", 54 | "type":"function", 55 | "signature":"0x1249c58b" 56 | }, 57 | { 58 | "constant":true, 59 | "inputs":[ 60 | 61 | ], 62 | "name":"reserveFactorMantissa", 63 | "outputs":[ 64 | { 65 | "name":"", 66 | "type":"uint256" 67 | } 68 | ], 69 | "payable":false, 70 | "stateMutability":"view", 71 | "type":"function", 72 | "signature":"0x173b9904" 73 | }, 74 | { 75 | "constant":false, 76 | "inputs":[ 77 | { 78 | "name":"account", 79 | "type":"address" 80 | } 81 | ], 82 | "name":"borrowBalanceCurrent", 83 | "outputs":[ 84 | { 85 | "name":"", 86 | "type":"uint256" 87 | } 88 | ], 89 | "payable":false, 90 | "stateMutability":"nonpayable", 91 | "type":"function", 92 | "signature":"0x17bfdfbc" 93 | }, 94 | { 95 | "constant":true, 96 | "inputs":[ 97 | 98 | ], 99 | "name":"totalSupply", 100 | "outputs":[ 101 | { 102 | "name":"", 103 | "type":"uint256" 104 | } 105 | ], 106 | "payable":false, 107 | "stateMutability":"view", 108 | "type":"function", 109 | "signature":"0x18160ddd" 110 | }, 111 | { 112 | "constant":true, 113 | "inputs":[ 114 | 115 | ], 116 | "name":"exchangeRateStored", 117 | "outputs":[ 118 | { 119 | "name":"", 120 | "type":"uint256" 121 | } 122 | ], 123 | "payable":false, 124 | "stateMutability":"view", 125 | "type":"function", 126 | "signature":"0x182df0f5" 127 | }, 128 | { 129 | "constant":false, 130 | "inputs":[ 131 | { 132 | "name":"src", 133 | "type":"address" 134 | }, 135 | { 136 | "name":"dst", 137 | "type":"address" 138 | }, 139 | { 140 | "name":"amount", 141 | "type":"uint256" 142 | } 143 | ], 144 | "name":"transferFrom", 145 | "outputs":[ 146 | { 147 | "name":"", 148 | "type":"bool" 149 | } 150 | ], 151 | "payable":false, 152 | "stateMutability":"nonpayable", 153 | "type":"function", 154 | "signature":"0x23b872dd" 155 | }, 156 | { 157 | "constant":true, 158 | "inputs":[ 159 | 160 | ], 161 | "name":"pendingAdmin", 162 | "outputs":[ 163 | { 164 | "name":"", 165 | "type":"address" 166 | } 167 | ], 168 | "payable":false, 169 | "stateMutability":"view", 170 | "type":"function", 171 | "signature":"0x26782247" 172 | }, 173 | { 174 | "constant":true, 175 | "inputs":[ 176 | 177 | ], 178 | "name":"decimals", 179 | "outputs":[ 180 | { 181 | "name":"", 182 | "type":"uint256" 183 | } 184 | ], 185 | "payable":false, 186 | "stateMutability":"view", 187 | "type":"function", 188 | "signature":"0x313ce567" 189 | }, 190 | { 191 | "constant":false, 192 | "inputs":[ 193 | { 194 | "name":"owner", 195 | "type":"address" 196 | } 197 | ], 198 | "name":"balanceOfUnderlying", 199 | "outputs":[ 200 | { 201 | "name":"", 202 | "type":"uint256" 203 | } 204 | ], 205 | "payable":false, 206 | "stateMutability":"nonpayable", 207 | "type":"function", 208 | "signature":"0x3af9e669" 209 | }, 210 | { 211 | "constant":true, 212 | "inputs":[ 213 | 214 | ], 215 | "name":"getCash", 216 | "outputs":[ 217 | { 218 | "name":"", 219 | "type":"uint256" 220 | } 221 | ], 222 | "payable":false, 223 | "stateMutability":"view", 224 | "type":"function", 225 | "signature":"0x3b1d21a2" 226 | }, 227 | { 228 | "constant":false, 229 | "inputs":[ 230 | { 231 | "name":"newComptroller", 232 | "type":"address" 233 | } 234 | ], 235 | "name":"_setComptroller", 236 | "outputs":[ 237 | { 238 | "name":"", 239 | "type":"uint256" 240 | } 241 | ], 242 | "payable":false, 243 | "stateMutability":"nonpayable", 244 | "type":"function", 245 | "signature":"0x4576b5db" 246 | }, 247 | { 248 | "constant":true, 249 | "inputs":[ 250 | 251 | ], 252 | "name":"totalBorrows", 253 | "outputs":[ 254 | { 255 | "name":"", 256 | "type":"uint256" 257 | } 258 | ], 259 | "payable":false, 260 | "stateMutability":"view", 261 | "type":"function", 262 | "signature":"0x47bd3718" 263 | }, 264 | { 265 | "constant":false, 266 | "inputs":[ 267 | 268 | ], 269 | "name":"repayBorrow", 270 | "outputs":[ 271 | 272 | ], 273 | "payable":true, 274 | "stateMutability":"payable", 275 | "type":"function", 276 | "signature":"0x4e4d9fea" 277 | }, 278 | { 279 | "constant":true, 280 | "inputs":[ 281 | 282 | ], 283 | "name":"comptroller", 284 | "outputs":[ 285 | { 286 | "name":"", 287 | "type":"address" 288 | } 289 | ], 290 | "payable":false, 291 | "stateMutability":"view", 292 | "type":"function", 293 | "signature":"0x5fe3b567" 294 | }, 295 | { 296 | "constant":false, 297 | "inputs":[ 298 | { 299 | "name":"reduceAmount", 300 | "type":"uint256" 301 | } 302 | ], 303 | "name":"_reduceReserves", 304 | "outputs":[ 305 | { 306 | "name":"", 307 | "type":"uint256" 308 | } 309 | ], 310 | "payable":false, 311 | "stateMutability":"nonpayable", 312 | "type":"function", 313 | "signature":"0x601a0bf1" 314 | }, 315 | { 316 | "constant":true, 317 | "inputs":[ 318 | 319 | ], 320 | "name":"initialExchangeRateMantissa", 321 | "outputs":[ 322 | { 323 | "name":"", 324 | "type":"uint256" 325 | } 326 | ], 327 | "payable":false, 328 | "stateMutability":"view", 329 | "type":"function", 330 | "signature":"0x675d972c" 331 | }, 332 | { 333 | "constant":true, 334 | "inputs":[ 335 | 336 | ], 337 | "name":"accrualBlockNumber", 338 | "outputs":[ 339 | { 340 | "name":"", 341 | "type":"uint256" 342 | } 343 | ], 344 | "payable":false, 345 | "stateMutability":"view", 346 | "type":"function", 347 | "signature":"0x6c540baf" 348 | }, 349 | { 350 | "constant":true, 351 | "inputs":[ 352 | { 353 | "name":"owner", 354 | "type":"address" 355 | } 356 | ], 357 | "name":"balanceOf", 358 | "outputs":[ 359 | { 360 | "name":"", 361 | "type":"uint256" 362 | } 363 | ], 364 | "payable":false, 365 | "stateMutability":"view", 366 | "type":"function", 367 | "signature":"0x70a08231" 368 | }, 369 | { 370 | "constant":false, 371 | "inputs":[ 372 | 373 | ], 374 | "name":"totalBorrowsCurrent", 375 | "outputs":[ 376 | { 377 | "name":"", 378 | "type":"uint256" 379 | } 380 | ], 381 | "payable":false, 382 | "stateMutability":"nonpayable", 383 | "type":"function", 384 | "signature":"0x73acee98" 385 | }, 386 | { 387 | "constant":false, 388 | "inputs":[ 389 | { 390 | "name":"redeemAmount", 391 | "type":"uint256" 392 | } 393 | ], 394 | "name":"redeemUnderlying", 395 | "outputs":[ 396 | { 397 | "name":"", 398 | "type":"uint256" 399 | } 400 | ], 401 | "payable":false, 402 | "stateMutability":"nonpayable", 403 | "type":"function", 404 | "signature":"0x852a12e3" 405 | }, 406 | { 407 | "constant":true, 408 | "inputs":[ 409 | 410 | ], 411 | "name":"totalReserves", 412 | "outputs":[ 413 | { 414 | "name":"", 415 | "type":"uint256" 416 | } 417 | ], 418 | "payable":false, 419 | "stateMutability":"view", 420 | "type":"function", 421 | "signature":"0x8f840ddd" 422 | }, 423 | { 424 | "constant":true, 425 | "inputs":[ 426 | 427 | ], 428 | "name":"symbol", 429 | "outputs":[ 430 | { 431 | "name":"", 432 | "type":"string" 433 | } 434 | ], 435 | "payable":false, 436 | "stateMutability":"view", 437 | "type":"function", 438 | "signature":"0x95d89b41" 439 | }, 440 | { 441 | "constant":true, 442 | "inputs":[ 443 | { 444 | "name":"account", 445 | "type":"address" 446 | } 447 | ], 448 | "name":"borrowBalanceStored", 449 | "outputs":[ 450 | { 451 | "name":"", 452 | "type":"uint256" 453 | } 454 | ], 455 | "payable":false, 456 | "stateMutability":"view", 457 | "type":"function", 458 | "signature":"0x95dd9193" 459 | }, 460 | { 461 | "constant":false, 462 | "inputs":[ 463 | 464 | ], 465 | "name":"accrueInterest", 466 | "outputs":[ 467 | { 468 | "name":"", 469 | "type":"uint256" 470 | } 471 | ], 472 | "payable":false, 473 | "stateMutability":"nonpayable", 474 | "type":"function", 475 | "signature":"0xa6afed95" 476 | }, 477 | { 478 | "constant":false, 479 | "inputs":[ 480 | { 481 | "name":"dst", 482 | "type":"address" 483 | }, 484 | { 485 | "name":"amount", 486 | "type":"uint256" 487 | } 488 | ], 489 | "name":"transfer", 490 | "outputs":[ 491 | { 492 | "name":"", 493 | "type":"bool" 494 | } 495 | ], 496 | "payable":false, 497 | "stateMutability":"nonpayable", 498 | "type":"function", 499 | "signature":"0xa9059cbb" 500 | }, 501 | { 502 | "constant":true, 503 | "inputs":[ 504 | 505 | ], 506 | "name":"borrowIndex", 507 | "outputs":[ 508 | { 509 | "name":"", 510 | "type":"uint256" 511 | } 512 | ], 513 | "payable":false, 514 | "stateMutability":"view", 515 | "type":"function", 516 | "signature":"0xaa5af0fd" 517 | }, 518 | { 519 | "constant":false, 520 | "inputs":[ 521 | { 522 | "name":"borrower", 523 | "type":"address" 524 | }, 525 | { 526 | "name":"cTokenCollateral", 527 | "type":"address" 528 | } 529 | ], 530 | "name":"liquidateBorrow", 531 | "outputs":[ 532 | 533 | ], 534 | "payable":true, 535 | "stateMutability":"payable", 536 | "type":"function", 537 | "signature":"0xaae40a2a" 538 | }, 539 | { 540 | "constant":true, 541 | "inputs":[ 542 | 543 | ], 544 | "name":"supplyRatePerBlock", 545 | "outputs":[ 546 | { 547 | "name":"", 548 | "type":"uint256" 549 | } 550 | ], 551 | "payable":false, 552 | "stateMutability":"view", 553 | "type":"function", 554 | "signature":"0xae9d70b0" 555 | }, 556 | { 557 | "constant":false, 558 | "inputs":[ 559 | { 560 | "name":"liquidator", 561 | "type":"address" 562 | }, 563 | { 564 | "name":"borrower", 565 | "type":"address" 566 | }, 567 | { 568 | "name":"seizeTokens", 569 | "type":"uint256" 570 | } 571 | ], 572 | "name":"seize", 573 | "outputs":[ 574 | { 575 | "name":"", 576 | "type":"uint256" 577 | } 578 | ], 579 | "payable":false, 580 | "stateMutability":"nonpayable", 581 | "type":"function", 582 | "signature":"0xb2a02ff1" 583 | }, 584 | { 585 | "constant":false, 586 | "inputs":[ 587 | { 588 | "name":"newPendingAdmin", 589 | "type":"address" 590 | } 591 | ], 592 | "name":"_setPendingAdmin", 593 | "outputs":[ 594 | { 595 | "name":"", 596 | "type":"uint256" 597 | } 598 | ], 599 | "payable":false, 600 | "stateMutability":"nonpayable", 601 | "type":"function", 602 | "signature":"0xb71d1a0c" 603 | }, 604 | { 605 | "constant":false, 606 | "inputs":[ 607 | 608 | ], 609 | "name":"exchangeRateCurrent", 610 | "outputs":[ 611 | { 612 | "name":"", 613 | "type":"uint256" 614 | } 615 | ], 616 | "payable":false, 617 | "stateMutability":"nonpayable", 618 | "type":"function", 619 | "signature":"0xbd6d894d" 620 | }, 621 | { 622 | "constant":true, 623 | "inputs":[ 624 | { 625 | "name":"account", 626 | "type":"address" 627 | } 628 | ], 629 | "name":"getAccountSnapshot", 630 | "outputs":[ 631 | { 632 | "name":"", 633 | "type":"uint256" 634 | }, 635 | { 636 | "name":"", 637 | "type":"uint256" 638 | }, 639 | { 640 | "name":"", 641 | "type":"uint256" 642 | }, 643 | { 644 | "name":"", 645 | "type":"uint256" 646 | } 647 | ], 648 | "payable":false, 649 | "stateMutability":"view", 650 | "type":"function", 651 | "signature":"0xc37f68e2" 652 | }, 653 | { 654 | "constant":false, 655 | "inputs":[ 656 | { 657 | "name":"borrowAmount", 658 | "type":"uint256" 659 | } 660 | ], 661 | "name":"borrow", 662 | "outputs":[ 663 | { 664 | "name":"", 665 | "type":"uint256" 666 | } 667 | ], 668 | "payable":false, 669 | "stateMutability":"nonpayable", 670 | "type":"function", 671 | "signature":"0xc5ebeaec" 672 | }, 673 | { 674 | "constant":false, 675 | "inputs":[ 676 | { 677 | "name":"redeemTokens", 678 | "type":"uint256" 679 | } 680 | ], 681 | "name":"redeem", 682 | "outputs":[ 683 | { 684 | "name":"", 685 | "type":"uint256" 686 | } 687 | ], 688 | "payable":false, 689 | "stateMutability":"nonpayable", 690 | "type":"function", 691 | "signature":"0xdb006a75" 692 | }, 693 | { 694 | "constant":true, 695 | "inputs":[ 696 | { 697 | "name":"owner", 698 | "type":"address" 699 | }, 700 | { 701 | "name":"spender", 702 | "type":"address" 703 | } 704 | ], 705 | "name":"allowance", 706 | "outputs":[ 707 | { 708 | "name":"", 709 | "type":"uint256" 710 | } 711 | ], 712 | "payable":false, 713 | "stateMutability":"view", 714 | "type":"function", 715 | "signature":"0xdd62ed3e" 716 | }, 717 | { 718 | "constant":false, 719 | "inputs":[ 720 | { 721 | "name":"borrower", 722 | "type":"address" 723 | } 724 | ], 725 | "name":"repayBorrowBehalf", 726 | "outputs":[ 727 | 728 | ], 729 | "payable":true, 730 | "stateMutability":"payable", 731 | "type":"function", 732 | "signature":"0xe5974619" 733 | }, 734 | { 735 | "constant":false, 736 | "inputs":[ 737 | 738 | ], 739 | "name":"_acceptAdmin", 740 | "outputs":[ 741 | { 742 | "name":"", 743 | "type":"uint256" 744 | } 745 | ], 746 | "payable":false, 747 | "stateMutability":"nonpayable", 748 | "type":"function", 749 | "signature":"0xe9c714f2" 750 | }, 751 | { 752 | "constant":false, 753 | "inputs":[ 754 | { 755 | "name":"newInterestRateModel", 756 | "type":"address" 757 | } 758 | ], 759 | "name":"_setInterestRateModel", 760 | "outputs":[ 761 | { 762 | "name":"", 763 | "type":"uint256" 764 | } 765 | ], 766 | "payable":false, 767 | "stateMutability":"nonpayable", 768 | "type":"function", 769 | "signature":"0xf2b3abbd" 770 | }, 771 | { 772 | "constant":true, 773 | "inputs":[ 774 | 775 | ], 776 | "name":"interestRateModel", 777 | "outputs":[ 778 | { 779 | "name":"", 780 | "type":"address" 781 | } 782 | ], 783 | "payable":false, 784 | "stateMutability":"view", 785 | "type":"function", 786 | "signature":"0xf3fdb15a" 787 | }, 788 | { 789 | "constant":true, 790 | "inputs":[ 791 | 792 | ], 793 | "name":"admin", 794 | "outputs":[ 795 | { 796 | "name":"", 797 | "type":"address" 798 | } 799 | ], 800 | "payable":false, 801 | "stateMutability":"view", 802 | "type":"function", 803 | "signature":"0xf851a440" 804 | }, 805 | { 806 | "constant":true, 807 | "inputs":[ 808 | 809 | ], 810 | "name":"borrowRatePerBlock", 811 | "outputs":[ 812 | { 813 | "name":"", 814 | "type":"uint256" 815 | } 816 | ], 817 | "payable":false, 818 | "stateMutability":"view", 819 | "type":"function", 820 | "signature":"0xf8f9da28" 821 | }, 822 | { 823 | "constant":false, 824 | "inputs":[ 825 | { 826 | "name":"newReserveFactorMantissa", 827 | "type":"uint256" 828 | } 829 | ], 830 | "name":"_setReserveFactor", 831 | "outputs":[ 832 | { 833 | "name":"", 834 | "type":"uint256" 835 | } 836 | ], 837 | "payable":false, 838 | "stateMutability":"nonpayable", 839 | "type":"function", 840 | "signature":"0xfca7820b" 841 | }, 842 | { 843 | "constant":true, 844 | "inputs":[ 845 | 846 | ], 847 | "name":"isCToken", 848 | "outputs":[ 849 | { 850 | "name":"", 851 | "type":"bool" 852 | } 853 | ], 854 | "payable":false, 855 | "stateMutability":"view", 856 | "type":"function", 857 | "signature":"0xfe9c44ae" 858 | }, 859 | { 860 | "inputs":[ 861 | { 862 | "name":"comptroller_", 863 | "type":"address" 864 | }, 865 | { 866 | "name":"interestRateModel_", 867 | "type":"address" 868 | }, 869 | { 870 | "name":"initialExchangeRateMantissa_", 871 | "type":"uint256" 872 | }, 873 | { 874 | "name":"name_", 875 | "type":"string" 876 | }, 877 | { 878 | "name":"symbol_", 879 | "type":"string" 880 | }, 881 | { 882 | "name":"decimals_", 883 | "type":"uint256" 884 | } 885 | ], 886 | "payable":false, 887 | "stateMutability":"nonpayable", 888 | "type":"constructor", 889 | "signature":"constructor" 890 | }, 891 | { 892 | "payable":true, 893 | "stateMutability":"payable", 894 | "type":"fallback" 895 | }, 896 | { 897 | "anonymous":false, 898 | "inputs":[ 899 | { 900 | "indexed":false, 901 | "name":"interestAccumulated", 902 | "type":"uint256" 903 | }, 904 | { 905 | "indexed":false, 906 | "name":"borrowIndex", 907 | "type":"uint256" 908 | }, 909 | { 910 | "indexed":false, 911 | "name":"totalBorrows", 912 | "type":"uint256" 913 | } 914 | ], 915 | "name":"AccrueInterest", 916 | "type":"event", 917 | "signature":"0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" 918 | }, 919 | { 920 | "anonymous":false, 921 | "inputs":[ 922 | { 923 | "indexed":false, 924 | "name":"minter", 925 | "type":"address" 926 | }, 927 | { 928 | "indexed":false, 929 | "name":"mintAmount", 930 | "type":"uint256" 931 | }, 932 | { 933 | "indexed":false, 934 | "name":"mintTokens", 935 | "type":"uint256" 936 | } 937 | ], 938 | "name":"Mint", 939 | "type":"event", 940 | "signature":"0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" 941 | }, 942 | { 943 | "anonymous":false, 944 | "inputs":[ 945 | { 946 | "indexed":false, 947 | "name":"redeemer", 948 | "type":"address" 949 | }, 950 | { 951 | "indexed":false, 952 | "name":"redeemAmount", 953 | "type":"uint256" 954 | }, 955 | { 956 | "indexed":false, 957 | "name":"redeemTokens", 958 | "type":"uint256" 959 | } 960 | ], 961 | "name":"Redeem", 962 | "type":"event", 963 | "signature":"0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" 964 | }, 965 | { 966 | "anonymous":false, 967 | "inputs":[ 968 | { 969 | "indexed":false, 970 | "name":"borrower", 971 | "type":"address" 972 | }, 973 | { 974 | "indexed":false, 975 | "name":"borrowAmount", 976 | "type":"uint256" 977 | }, 978 | { 979 | "indexed":false, 980 | "name":"accountBorrows", 981 | "type":"uint256" 982 | }, 983 | { 984 | "indexed":false, 985 | "name":"totalBorrows", 986 | "type":"uint256" 987 | } 988 | ], 989 | "name":"Borrow", 990 | "type":"event", 991 | "signature":"0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" 992 | }, 993 | { 994 | "anonymous":false, 995 | "inputs":[ 996 | { 997 | "indexed":false, 998 | "name":"payer", 999 | "type":"address" 1000 | }, 1001 | { 1002 | "indexed":false, 1003 | "name":"borrower", 1004 | "type":"address" 1005 | }, 1006 | { 1007 | "indexed":false, 1008 | "name":"repayAmount", 1009 | "type":"uint256" 1010 | }, 1011 | { 1012 | "indexed":false, 1013 | "name":"accountBorrows", 1014 | "type":"uint256" 1015 | }, 1016 | { 1017 | "indexed":false, 1018 | "name":"totalBorrows", 1019 | "type":"uint256" 1020 | } 1021 | ], 1022 | "name":"RepayBorrow", 1023 | "type":"event", 1024 | "signature":"0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" 1025 | }, 1026 | { 1027 | "anonymous":false, 1028 | "inputs":[ 1029 | { 1030 | "indexed":false, 1031 | "name":"liquidator", 1032 | "type":"address" 1033 | }, 1034 | { 1035 | "indexed":false, 1036 | "name":"borrower", 1037 | "type":"address" 1038 | }, 1039 | { 1040 | "indexed":false, 1041 | "name":"repayAmount", 1042 | "type":"uint256" 1043 | }, 1044 | { 1045 | "indexed":false, 1046 | "name":"cTokenCollateral", 1047 | "type":"address" 1048 | }, 1049 | { 1050 | "indexed":false, 1051 | "name":"seizeTokens", 1052 | "type":"uint256" 1053 | } 1054 | ], 1055 | "name":"LiquidateBorrow", 1056 | "type":"event", 1057 | "signature":"0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" 1058 | }, 1059 | { 1060 | "anonymous":false, 1061 | "inputs":[ 1062 | { 1063 | "indexed":false, 1064 | "name":"oldPendingAdmin", 1065 | "type":"address" 1066 | }, 1067 | { 1068 | "indexed":false, 1069 | "name":"newPendingAdmin", 1070 | "type":"address" 1071 | } 1072 | ], 1073 | "name":"NewPendingAdmin", 1074 | "type":"event", 1075 | "signature":"0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" 1076 | }, 1077 | { 1078 | "anonymous":false, 1079 | "inputs":[ 1080 | { 1081 | "indexed":false, 1082 | "name":"oldAdmin", 1083 | "type":"address" 1084 | }, 1085 | { 1086 | "indexed":false, 1087 | "name":"newAdmin", 1088 | "type":"address" 1089 | } 1090 | ], 1091 | "name":"NewAdmin", 1092 | "type":"event", 1093 | "signature":"0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" 1094 | }, 1095 | { 1096 | "anonymous":false, 1097 | "inputs":[ 1098 | { 1099 | "indexed":false, 1100 | "name":"oldComptroller", 1101 | "type":"address" 1102 | }, 1103 | { 1104 | "indexed":false, 1105 | "name":"newComptroller", 1106 | "type":"address" 1107 | } 1108 | ], 1109 | "name":"NewComptroller", 1110 | "type":"event", 1111 | "signature":"0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" 1112 | }, 1113 | { 1114 | "anonymous":false, 1115 | "inputs":[ 1116 | { 1117 | "indexed":false, 1118 | "name":"oldInterestRateModel", 1119 | "type":"address" 1120 | }, 1121 | { 1122 | "indexed":false, 1123 | "name":"newInterestRateModel", 1124 | "type":"address" 1125 | } 1126 | ], 1127 | "name":"NewMarketInterestRateModel", 1128 | "type":"event", 1129 | "signature":"0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" 1130 | }, 1131 | { 1132 | "anonymous":false, 1133 | "inputs":[ 1134 | { 1135 | "indexed":false, 1136 | "name":"oldReserveFactorMantissa", 1137 | "type":"uint256" 1138 | }, 1139 | { 1140 | "indexed":false, 1141 | "name":"newReserveFactorMantissa", 1142 | "type":"uint256" 1143 | } 1144 | ], 1145 | "name":"NewReserveFactor", 1146 | "type":"event", 1147 | "signature":"0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" 1148 | }, 1149 | { 1150 | "anonymous":false, 1151 | "inputs":[ 1152 | { 1153 | "indexed":false, 1154 | "name":"admin", 1155 | "type":"address" 1156 | }, 1157 | { 1158 | "indexed":false, 1159 | "name":"reduceAmount", 1160 | "type":"uint256" 1161 | }, 1162 | { 1163 | "indexed":false, 1164 | "name":"newTotalReserves", 1165 | "type":"uint256" 1166 | } 1167 | ], 1168 | "name":"ReservesReduced", 1169 | "type":"event", 1170 | "signature":"0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" 1171 | }, 1172 | { 1173 | "anonymous":false, 1174 | "inputs":[ 1175 | { 1176 | "indexed":false, 1177 | "name":"error", 1178 | "type":"uint256" 1179 | }, 1180 | { 1181 | "indexed":false, 1182 | "name":"info", 1183 | "type":"uint256" 1184 | }, 1185 | { 1186 | "indexed":false, 1187 | "name":"detail", 1188 | "type":"uint256" 1189 | } 1190 | ], 1191 | "name":"Failure", 1192 | "type":"event", 1193 | "signature":"0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" 1194 | }, 1195 | { 1196 | "anonymous":false, 1197 | "inputs":[ 1198 | { 1199 | "indexed":true, 1200 | "name":"from", 1201 | "type":"address" 1202 | }, 1203 | { 1204 | "indexed":true, 1205 | "name":"to", 1206 | "type":"address" 1207 | }, 1208 | { 1209 | "indexed":false, 1210 | "name":"amount", 1211 | "type":"uint256" 1212 | } 1213 | ], 1214 | "name":"Transfer", 1215 | "type":"event", 1216 | "signature":"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" 1217 | }, 1218 | { 1219 | "anonymous":false, 1220 | "inputs":[ 1221 | { 1222 | "indexed":true, 1223 | "name":"owner", 1224 | "type":"address" 1225 | }, 1226 | { 1227 | "indexed":true, 1228 | "name":"spender", 1229 | "type":"address" 1230 | }, 1231 | { 1232 | "indexed":false, 1233 | "name":"amount", 1234 | "type":"uint256" 1235 | } 1236 | ], 1237 | "name":"Approval", 1238 | "type":"event", 1239 | "signature":"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" 1240 | } 1241 | ] -------------------------------------------------------------------------------- /timelock/abi/cToken-abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant":true, 4 | "inputs":[ 5 | 6 | ], 7 | "name":"name", 8 | "outputs":[ 9 | { 10 | "name":"", 11 | "type":"string" 12 | } 13 | ], 14 | "payable":false, 15 | "stateMutability":"view", 16 | "type":"function", 17 | "signature":"0x06fdde03" 18 | }, 19 | { 20 | "constant":false, 21 | "inputs":[ 22 | { 23 | "name":"spender", 24 | "type":"address" 25 | }, 26 | { 27 | "name":"amount", 28 | "type":"uint256" 29 | } 30 | ], 31 | "name":"approve", 32 | "outputs":[ 33 | { 34 | "name":"", 35 | "type":"bool" 36 | } 37 | ], 38 | "payable":false, 39 | "stateMutability":"nonpayable", 40 | "type":"function", 41 | "signature":"0x095ea7b3" 42 | }, 43 | { 44 | "constant":false, 45 | "inputs":[ 46 | { 47 | "name":"repayAmount", 48 | "type":"uint256" 49 | } 50 | ], 51 | "name":"repayBorrow", 52 | "outputs":[ 53 | { 54 | "name":"", 55 | "type":"uint256" 56 | } 57 | ], 58 | "payable":false, 59 | "stateMutability":"nonpayable", 60 | "type":"function", 61 | "signature":"0x0e752702" 62 | }, 63 | { 64 | "constant":true, 65 | "inputs":[ 66 | 67 | ], 68 | "name":"reserveFactorMantissa", 69 | "outputs":[ 70 | { 71 | "name":"", 72 | "type":"uint256" 73 | } 74 | ], 75 | "payable":false, 76 | "stateMutability":"view", 77 | "type":"function", 78 | "signature":"0x173b9904" 79 | }, 80 | { 81 | "constant":false, 82 | "inputs":[ 83 | { 84 | "name":"account", 85 | "type":"address" 86 | } 87 | ], 88 | "name":"borrowBalanceCurrent", 89 | "outputs":[ 90 | { 91 | "name":"", 92 | "type":"uint256" 93 | } 94 | ], 95 | "payable":false, 96 | "stateMutability":"nonpayable", 97 | "type":"function", 98 | "signature":"0x17bfdfbc" 99 | }, 100 | { 101 | "constant":true, 102 | "inputs":[ 103 | 104 | ], 105 | "name":"totalSupply", 106 | "outputs":[ 107 | { 108 | "name":"", 109 | "type":"uint256" 110 | } 111 | ], 112 | "payable":false, 113 | "stateMutability":"view", 114 | "type":"function", 115 | "signature":"0x18160ddd" 116 | }, 117 | { 118 | "constant":true, 119 | "inputs":[ 120 | 121 | ], 122 | "name":"exchangeRateStored", 123 | "outputs":[ 124 | { 125 | "name":"", 126 | "type":"uint256" 127 | } 128 | ], 129 | "payable":false, 130 | "stateMutability":"view", 131 | "type":"function", 132 | "signature":"0x182df0f5" 133 | }, 134 | { 135 | "constant":false, 136 | "inputs":[ 137 | { 138 | "name":"src", 139 | "type":"address" 140 | }, 141 | { 142 | "name":"dst", 143 | "type":"address" 144 | }, 145 | { 146 | "name":"amount", 147 | "type":"uint256" 148 | } 149 | ], 150 | "name":"transferFrom", 151 | "outputs":[ 152 | { 153 | "name":"", 154 | "type":"bool" 155 | } 156 | ], 157 | "payable":false, 158 | "stateMutability":"nonpayable", 159 | "type":"function", 160 | "signature":"0x23b872dd" 161 | }, 162 | { 163 | "constant":false, 164 | "inputs":[ 165 | { 166 | "name":"borrower", 167 | "type":"address" 168 | }, 169 | { 170 | "name":"repayAmount", 171 | "type":"uint256" 172 | } 173 | ], 174 | "name":"repayBorrowBehalf", 175 | "outputs":[ 176 | { 177 | "name":"", 178 | "type":"uint256" 179 | } 180 | ], 181 | "payable":false, 182 | "stateMutability":"nonpayable", 183 | "type":"function", 184 | "signature":"0x2608f818" 185 | }, 186 | { 187 | "constant":true, 188 | "inputs":[ 189 | 190 | ], 191 | "name":"pendingAdmin", 192 | "outputs":[ 193 | { 194 | "name":"", 195 | "type":"address" 196 | } 197 | ], 198 | "payable":false, 199 | "stateMutability":"view", 200 | "type":"function", 201 | "signature":"0x26782247" 202 | }, 203 | { 204 | "constant":true, 205 | "inputs":[ 206 | 207 | ], 208 | "name":"decimals", 209 | "outputs":[ 210 | { 211 | "name":"", 212 | "type":"uint256" 213 | } 214 | ], 215 | "payable":false, 216 | "stateMutability":"view", 217 | "type":"function", 218 | "signature":"0x313ce567" 219 | }, 220 | { 221 | "constant":false, 222 | "inputs":[ 223 | { 224 | "name":"owner", 225 | "type":"address" 226 | } 227 | ], 228 | "name":"balanceOfUnderlying", 229 | "outputs":[ 230 | { 231 | "name":"", 232 | "type":"uint256" 233 | } 234 | ], 235 | "payable":false, 236 | "stateMutability":"nonpayable", 237 | "type":"function", 238 | "signature":"0x3af9e669" 239 | }, 240 | { 241 | "constant":true, 242 | "inputs":[ 243 | 244 | ], 245 | "name":"getCash", 246 | "outputs":[ 247 | { 248 | "name":"", 249 | "type":"uint256" 250 | } 251 | ], 252 | "payable":false, 253 | "stateMutability":"view", 254 | "type":"function", 255 | "signature":"0x3b1d21a2" 256 | }, 257 | { 258 | "constant":false, 259 | "inputs":[ 260 | { 261 | "name":"newComptroller", 262 | "type":"address" 263 | } 264 | ], 265 | "name":"_setComptroller", 266 | "outputs":[ 267 | { 268 | "name":"", 269 | "type":"uint256" 270 | } 271 | ], 272 | "payable":false, 273 | "stateMutability":"nonpayable", 274 | "type":"function", 275 | "signature":"0x4576b5db" 276 | }, 277 | { 278 | "constant":true, 279 | "inputs":[ 280 | 281 | ], 282 | "name":"totalBorrows", 283 | "outputs":[ 284 | { 285 | "name":"", 286 | "type":"uint256" 287 | } 288 | ], 289 | "payable":false, 290 | "stateMutability":"view", 291 | "type":"function", 292 | "signature":"0x47bd3718" 293 | }, 294 | { 295 | "constant":true, 296 | "inputs":[ 297 | 298 | ], 299 | "name":"comptroller", 300 | "outputs":[ 301 | { 302 | "name":"", 303 | "type":"address" 304 | } 305 | ], 306 | "payable":false, 307 | "stateMutability":"view", 308 | "type":"function", 309 | "signature":"0x5fe3b567" 310 | }, 311 | { 312 | "constant":false, 313 | "inputs":[ 314 | { 315 | "name":"reduceAmount", 316 | "type":"uint256" 317 | } 318 | ], 319 | "name":"_reduceReserves", 320 | "outputs":[ 321 | { 322 | "name":"", 323 | "type":"uint256" 324 | } 325 | ], 326 | "payable":false, 327 | "stateMutability":"nonpayable", 328 | "type":"function", 329 | "signature":"0x601a0bf1" 330 | }, 331 | { 332 | "constant":true, 333 | "inputs":[ 334 | 335 | ], 336 | "name":"initialExchangeRateMantissa", 337 | "outputs":[ 338 | { 339 | "name":"", 340 | "type":"uint256" 341 | } 342 | ], 343 | "payable":false, 344 | "stateMutability":"view", 345 | "type":"function", 346 | "signature":"0x675d972c" 347 | }, 348 | { 349 | "constant":true, 350 | "inputs":[ 351 | 352 | ], 353 | "name":"accrualBlockNumber", 354 | "outputs":[ 355 | { 356 | "name":"", 357 | "type":"uint256" 358 | } 359 | ], 360 | "payable":false, 361 | "stateMutability":"view", 362 | "type":"function", 363 | "signature":"0x6c540baf" 364 | }, 365 | { 366 | "constant":true, 367 | "inputs":[ 368 | 369 | ], 370 | "name":"underlying", 371 | "outputs":[ 372 | { 373 | "name":"", 374 | "type":"address" 375 | } 376 | ], 377 | "payable":false, 378 | "stateMutability":"view", 379 | "type":"function", 380 | "signature":"0x6f307dc3" 381 | }, 382 | { 383 | "constant":true, 384 | "inputs":[ 385 | { 386 | "name":"owner", 387 | "type":"address" 388 | } 389 | ], 390 | "name":"balanceOf", 391 | "outputs":[ 392 | { 393 | "name":"", 394 | "type":"uint256" 395 | } 396 | ], 397 | "payable":false, 398 | "stateMutability":"view", 399 | "type":"function", 400 | "signature":"0x70a08231" 401 | }, 402 | { 403 | "constant":false, 404 | "inputs":[ 405 | 406 | ], 407 | "name":"totalBorrowsCurrent", 408 | "outputs":[ 409 | { 410 | "name":"", 411 | "type":"uint256" 412 | } 413 | ], 414 | "payable":false, 415 | "stateMutability":"nonpayable", 416 | "type":"function", 417 | "signature":"0x73acee98" 418 | }, 419 | { 420 | "constant":false, 421 | "inputs":[ 422 | { 423 | "name":"redeemAmount", 424 | "type":"uint256" 425 | } 426 | ], 427 | "name":"redeemUnderlying", 428 | "outputs":[ 429 | { 430 | "name":"", 431 | "type":"uint256" 432 | } 433 | ], 434 | "payable":false, 435 | "stateMutability":"nonpayable", 436 | "type":"function", 437 | "signature":"0x852a12e3" 438 | }, 439 | { 440 | "constant":true, 441 | "inputs":[ 442 | 443 | ], 444 | "name":"totalReserves", 445 | "outputs":[ 446 | { 447 | "name":"", 448 | "type":"uint256" 449 | } 450 | ], 451 | "payable":false, 452 | "stateMutability":"view", 453 | "type":"function", 454 | "signature":"0x8f840ddd" 455 | }, 456 | { 457 | "constant":true, 458 | "inputs":[ 459 | 460 | ], 461 | "name":"symbol", 462 | "outputs":[ 463 | { 464 | "name":"", 465 | "type":"string" 466 | } 467 | ], 468 | "payable":false, 469 | "stateMutability":"view", 470 | "type":"function", 471 | "signature":"0x95d89b41" 472 | }, 473 | { 474 | "constant":true, 475 | "inputs":[ 476 | { 477 | "name":"account", 478 | "type":"address" 479 | } 480 | ], 481 | "name":"borrowBalanceStored", 482 | "outputs":[ 483 | { 484 | "name":"", 485 | "type":"uint256" 486 | } 487 | ], 488 | "payable":false, 489 | "stateMutability":"view", 490 | "type":"function", 491 | "signature":"0x95dd9193" 492 | }, 493 | { 494 | "constant":false, 495 | "inputs":[ 496 | { 497 | "name":"mintAmount", 498 | "type":"uint256" 499 | } 500 | ], 501 | "name":"mint", 502 | "outputs":[ 503 | { 504 | "name":"", 505 | "type":"uint256" 506 | } 507 | ], 508 | "payable":false, 509 | "stateMutability":"nonpayable", 510 | "type":"function", 511 | "signature":"0xa0712d68" 512 | }, 513 | { 514 | "constant":false, 515 | "inputs":[ 516 | 517 | ], 518 | "name":"accrueInterest", 519 | "outputs":[ 520 | { 521 | "name":"", 522 | "type":"uint256" 523 | } 524 | ], 525 | "payable":false, 526 | "stateMutability":"nonpayable", 527 | "type":"function", 528 | "signature":"0xa6afed95" 529 | }, 530 | { 531 | "constant":false, 532 | "inputs":[ 533 | { 534 | "name":"dst", 535 | "type":"address" 536 | }, 537 | { 538 | "name":"amount", 539 | "type":"uint256" 540 | } 541 | ], 542 | "name":"transfer", 543 | "outputs":[ 544 | { 545 | "name":"", 546 | "type":"bool" 547 | } 548 | ], 549 | "payable":false, 550 | "stateMutability":"nonpayable", 551 | "type":"function", 552 | "signature":"0xa9059cbb" 553 | }, 554 | { 555 | "constant":true, 556 | "inputs":[ 557 | 558 | ], 559 | "name":"borrowIndex", 560 | "outputs":[ 561 | { 562 | "name":"", 563 | "type":"uint256" 564 | } 565 | ], 566 | "payable":false, 567 | "stateMutability":"view", 568 | "type":"function", 569 | "signature":"0xaa5af0fd" 570 | }, 571 | { 572 | "constant":true, 573 | "inputs":[ 574 | 575 | ], 576 | "name":"supplyRatePerBlock", 577 | "outputs":[ 578 | { 579 | "name":"", 580 | "type":"uint256" 581 | } 582 | ], 583 | "payable":false, 584 | "stateMutability":"view", 585 | "type":"function", 586 | "signature":"0xae9d70b0" 587 | }, 588 | { 589 | "constant":false, 590 | "inputs":[ 591 | { 592 | "name":"liquidator", 593 | "type":"address" 594 | }, 595 | { 596 | "name":"borrower", 597 | "type":"address" 598 | }, 599 | { 600 | "name":"seizeTokens", 601 | "type":"uint256" 602 | } 603 | ], 604 | "name":"seize", 605 | "outputs":[ 606 | { 607 | "name":"", 608 | "type":"uint256" 609 | } 610 | ], 611 | "payable":false, 612 | "stateMutability":"nonpayable", 613 | "type":"function", 614 | "signature":"0xb2a02ff1" 615 | }, 616 | { 617 | "constant":false, 618 | "inputs":[ 619 | { 620 | "name":"newPendingAdmin", 621 | "type":"address" 622 | } 623 | ], 624 | "name":"_setPendingAdmin", 625 | "outputs":[ 626 | { 627 | "name":"", 628 | "type":"uint256" 629 | } 630 | ], 631 | "payable":false, 632 | "stateMutability":"nonpayable", 633 | "type":"function", 634 | "signature":"0xb71d1a0c" 635 | }, 636 | { 637 | "constant":false, 638 | "inputs":[ 639 | 640 | ], 641 | "name":"exchangeRateCurrent", 642 | "outputs":[ 643 | { 644 | "name":"", 645 | "type":"uint256" 646 | } 647 | ], 648 | "payable":false, 649 | "stateMutability":"nonpayable", 650 | "type":"function", 651 | "signature":"0xbd6d894d" 652 | }, 653 | { 654 | "constant":true, 655 | "inputs":[ 656 | { 657 | "name":"account", 658 | "type":"address" 659 | } 660 | ], 661 | "name":"getAccountSnapshot", 662 | "outputs":[ 663 | { 664 | "name":"", 665 | "type":"uint256" 666 | }, 667 | { 668 | "name":"", 669 | "type":"uint256" 670 | }, 671 | { 672 | "name":"", 673 | "type":"uint256" 674 | }, 675 | { 676 | "name":"", 677 | "type":"uint256" 678 | } 679 | ], 680 | "payable":false, 681 | "stateMutability":"view", 682 | "type":"function", 683 | "signature":"0xc37f68e2" 684 | }, 685 | { 686 | "constant":false, 687 | "inputs":[ 688 | { 689 | "name":"borrowAmount", 690 | "type":"uint256" 691 | } 692 | ], 693 | "name":"borrow", 694 | "outputs":[ 695 | { 696 | "name":"", 697 | "type":"uint256" 698 | } 699 | ], 700 | "payable":false, 701 | "stateMutability":"nonpayable", 702 | "type":"function", 703 | "signature":"0xc5ebeaec" 704 | }, 705 | { 706 | "constant":false, 707 | "inputs":[ 708 | { 709 | "name":"redeemTokens", 710 | "type":"uint256" 711 | } 712 | ], 713 | "name":"redeem", 714 | "outputs":[ 715 | { 716 | "name":"", 717 | "type":"uint256" 718 | } 719 | ], 720 | "payable":false, 721 | "stateMutability":"nonpayable", 722 | "type":"function", 723 | "signature":"0xdb006a75" 724 | }, 725 | { 726 | "constant":true, 727 | "inputs":[ 728 | { 729 | "name":"owner", 730 | "type":"address" 731 | }, 732 | { 733 | "name":"spender", 734 | "type":"address" 735 | } 736 | ], 737 | "name":"allowance", 738 | "outputs":[ 739 | { 740 | "name":"", 741 | "type":"uint256" 742 | } 743 | ], 744 | "payable":false, 745 | "stateMutability":"view", 746 | "type":"function", 747 | "signature":"0xdd62ed3e" 748 | }, 749 | { 750 | "constant":false, 751 | "inputs":[ 752 | 753 | ], 754 | "name":"_acceptAdmin", 755 | "outputs":[ 756 | { 757 | "name":"", 758 | "type":"uint256" 759 | } 760 | ], 761 | "payable":false, 762 | "stateMutability":"nonpayable", 763 | "type":"function", 764 | "signature":"0xe9c714f2" 765 | }, 766 | { 767 | "constant":false, 768 | "inputs":[ 769 | { 770 | "name":"newInterestRateModel", 771 | "type":"address" 772 | } 773 | ], 774 | "name":"_setInterestRateModel", 775 | "outputs":[ 776 | { 777 | "name":"", 778 | "type":"uint256" 779 | } 780 | ], 781 | "payable":false, 782 | "stateMutability":"nonpayable", 783 | "type":"function", 784 | "signature":"0xf2b3abbd" 785 | }, 786 | { 787 | "constant":true, 788 | "inputs":[ 789 | 790 | ], 791 | "name":"interestRateModel", 792 | "outputs":[ 793 | { 794 | "name":"", 795 | "type":"address" 796 | } 797 | ], 798 | "payable":false, 799 | "stateMutability":"view", 800 | "type":"function", 801 | "signature":"0xf3fdb15a" 802 | }, 803 | { 804 | "constant":false, 805 | "inputs":[ 806 | { 807 | "name":"borrower", 808 | "type":"address" 809 | }, 810 | { 811 | "name":"repayAmount", 812 | "type":"uint256" 813 | }, 814 | { 815 | "name":"cTokenCollateral", 816 | "type":"address" 817 | } 818 | ], 819 | "name":"liquidateBorrow", 820 | "outputs":[ 821 | { 822 | "name":"", 823 | "type":"uint256" 824 | } 825 | ], 826 | "payable":false, 827 | "stateMutability":"nonpayable", 828 | "type":"function", 829 | "signature":"0xf5e3c462" 830 | }, 831 | { 832 | "constant":true, 833 | "inputs":[ 834 | 835 | ], 836 | "name":"admin", 837 | "outputs":[ 838 | { 839 | "name":"", 840 | "type":"address" 841 | } 842 | ], 843 | "payable":false, 844 | "stateMutability":"view", 845 | "type":"function", 846 | "signature":"0xf851a440" 847 | }, 848 | { 849 | "constant":true, 850 | "inputs":[ 851 | 852 | ], 853 | "name":"borrowRatePerBlock", 854 | "outputs":[ 855 | { 856 | "name":"", 857 | "type":"uint256" 858 | } 859 | ], 860 | "payable":false, 861 | "stateMutability":"view", 862 | "type":"function", 863 | "signature":"0xf8f9da28" 864 | }, 865 | { 866 | "constant":false, 867 | "inputs":[ 868 | { 869 | "name":"newReserveFactorMantissa", 870 | "type":"uint256" 871 | } 872 | ], 873 | "name":"_setReserveFactor", 874 | "outputs":[ 875 | { 876 | "name":"", 877 | "type":"uint256" 878 | } 879 | ], 880 | "payable":false, 881 | "stateMutability":"nonpayable", 882 | "type":"function", 883 | "signature":"0xfca7820b" 884 | }, 885 | { 886 | "constant":true, 887 | "inputs":[ 888 | 889 | ], 890 | "name":"isCToken", 891 | "outputs":[ 892 | { 893 | "name":"", 894 | "type":"bool" 895 | } 896 | ], 897 | "payable":false, 898 | "stateMutability":"view", 899 | "type":"function", 900 | "signature":"0xfe9c44ae" 901 | }, 902 | { 903 | "inputs":[ 904 | { 905 | "name":"underlying_", 906 | "type":"address" 907 | }, 908 | { 909 | "name":"comptroller_", 910 | "type":"address" 911 | }, 912 | { 913 | "name":"interestRateModel_", 914 | "type":"address" 915 | }, 916 | { 917 | "name":"initialExchangeRateMantissa_", 918 | "type":"uint256" 919 | }, 920 | { 921 | "name":"name_", 922 | "type":"string" 923 | }, 924 | { 925 | "name":"symbol_", 926 | "type":"string" 927 | }, 928 | { 929 | "name":"decimals_", 930 | "type":"uint256" 931 | } 932 | ], 933 | "payable":false, 934 | "stateMutability":"nonpayable", 935 | "type":"constructor", 936 | "signature":"constructor" 937 | }, 938 | { 939 | "anonymous":false, 940 | "inputs":[ 941 | { 942 | "indexed":false, 943 | "name":"interestAccumulated", 944 | "type":"uint256" 945 | }, 946 | { 947 | "indexed":false, 948 | "name":"borrowIndex", 949 | "type":"uint256" 950 | }, 951 | { 952 | "indexed":false, 953 | "name":"totalBorrows", 954 | "type":"uint256" 955 | } 956 | ], 957 | "name":"AccrueInterest", 958 | "type":"event", 959 | "signature":"0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" 960 | }, 961 | { 962 | "anonymous":false, 963 | "inputs":[ 964 | { 965 | "indexed":false, 966 | "name":"minter", 967 | "type":"address" 968 | }, 969 | { 970 | "indexed":false, 971 | "name":"mintAmount", 972 | "type":"uint256" 973 | }, 974 | { 975 | "indexed":false, 976 | "name":"mintTokens", 977 | "type":"uint256" 978 | } 979 | ], 980 | "name":"Mint", 981 | "type":"event", 982 | "signature":"0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" 983 | }, 984 | { 985 | "anonymous":false, 986 | "inputs":[ 987 | { 988 | "indexed":false, 989 | "name":"redeemer", 990 | "type":"address" 991 | }, 992 | { 993 | "indexed":false, 994 | "name":"redeemAmount", 995 | "type":"uint256" 996 | }, 997 | { 998 | "indexed":false, 999 | "name":"redeemTokens", 1000 | "type":"uint256" 1001 | } 1002 | ], 1003 | "name":"Redeem", 1004 | "type":"event", 1005 | "signature":"0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" 1006 | }, 1007 | { 1008 | "anonymous":false, 1009 | "inputs":[ 1010 | { 1011 | "indexed":false, 1012 | "name":"borrower", 1013 | "type":"address" 1014 | }, 1015 | { 1016 | "indexed":false, 1017 | "name":"borrowAmount", 1018 | "type":"uint256" 1019 | }, 1020 | { 1021 | "indexed":false, 1022 | "name":"accountBorrows", 1023 | "type":"uint256" 1024 | }, 1025 | { 1026 | "indexed":false, 1027 | "name":"totalBorrows", 1028 | "type":"uint256" 1029 | } 1030 | ], 1031 | "name":"Borrow", 1032 | "type":"event", 1033 | "signature":"0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" 1034 | }, 1035 | { 1036 | "anonymous":false, 1037 | "inputs":[ 1038 | { 1039 | "indexed":false, 1040 | "name":"payer", 1041 | "type":"address" 1042 | }, 1043 | { 1044 | "indexed":false, 1045 | "name":"borrower", 1046 | "type":"address" 1047 | }, 1048 | { 1049 | "indexed":false, 1050 | "name":"repayAmount", 1051 | "type":"uint256" 1052 | }, 1053 | { 1054 | "indexed":false, 1055 | "name":"accountBorrows", 1056 | "type":"uint256" 1057 | }, 1058 | { 1059 | "indexed":false, 1060 | "name":"totalBorrows", 1061 | "type":"uint256" 1062 | } 1063 | ], 1064 | "name":"RepayBorrow", 1065 | "type":"event", 1066 | "signature":"0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" 1067 | }, 1068 | { 1069 | "anonymous":false, 1070 | "inputs":[ 1071 | { 1072 | "indexed":false, 1073 | "name":"liquidator", 1074 | "type":"address" 1075 | }, 1076 | { 1077 | "indexed":false, 1078 | "name":"borrower", 1079 | "type":"address" 1080 | }, 1081 | { 1082 | "indexed":false, 1083 | "name":"repayAmount", 1084 | "type":"uint256" 1085 | }, 1086 | { 1087 | "indexed":false, 1088 | "name":"cTokenCollateral", 1089 | "type":"address" 1090 | }, 1091 | { 1092 | "indexed":false, 1093 | "name":"seizeTokens", 1094 | "type":"uint256" 1095 | } 1096 | ], 1097 | "name":"LiquidateBorrow", 1098 | "type":"event", 1099 | "signature":"0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" 1100 | }, 1101 | { 1102 | "anonymous":false, 1103 | "inputs":[ 1104 | { 1105 | "indexed":false, 1106 | "name":"oldPendingAdmin", 1107 | "type":"address" 1108 | }, 1109 | { 1110 | "indexed":false, 1111 | "name":"newPendingAdmin", 1112 | "type":"address" 1113 | } 1114 | ], 1115 | "name":"NewPendingAdmin", 1116 | "type":"event", 1117 | "signature":"0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" 1118 | }, 1119 | { 1120 | "anonymous":false, 1121 | "inputs":[ 1122 | { 1123 | "indexed":false, 1124 | "name":"oldAdmin", 1125 | "type":"address" 1126 | }, 1127 | { 1128 | "indexed":false, 1129 | "name":"newAdmin", 1130 | "type":"address" 1131 | } 1132 | ], 1133 | "name":"NewAdmin", 1134 | "type":"event", 1135 | "signature":"0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" 1136 | }, 1137 | { 1138 | "anonymous":false, 1139 | "inputs":[ 1140 | { 1141 | "indexed":false, 1142 | "name":"oldComptroller", 1143 | "type":"address" 1144 | }, 1145 | { 1146 | "indexed":false, 1147 | "name":"newComptroller", 1148 | "type":"address" 1149 | } 1150 | ], 1151 | "name":"NewComptroller", 1152 | "type":"event", 1153 | "signature":"0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" 1154 | }, 1155 | { 1156 | "anonymous":false, 1157 | "inputs":[ 1158 | { 1159 | "indexed":false, 1160 | "name":"oldInterestRateModel", 1161 | "type":"address" 1162 | }, 1163 | { 1164 | "indexed":false, 1165 | "name":"newInterestRateModel", 1166 | "type":"address" 1167 | } 1168 | ], 1169 | "name":"NewMarketInterestRateModel", 1170 | "type":"event", 1171 | "signature":"0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" 1172 | }, 1173 | { 1174 | "anonymous":false, 1175 | "inputs":[ 1176 | { 1177 | "indexed":false, 1178 | "name":"oldReserveFactorMantissa", 1179 | "type":"uint256" 1180 | }, 1181 | { 1182 | "indexed":false, 1183 | "name":"newReserveFactorMantissa", 1184 | "type":"uint256" 1185 | } 1186 | ], 1187 | "name":"NewReserveFactor", 1188 | "type":"event", 1189 | "signature":"0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" 1190 | }, 1191 | { 1192 | "anonymous":false, 1193 | "inputs":[ 1194 | { 1195 | "indexed":false, 1196 | "name":"admin", 1197 | "type":"address" 1198 | }, 1199 | { 1200 | "indexed":false, 1201 | "name":"reduceAmount", 1202 | "type":"uint256" 1203 | }, 1204 | { 1205 | "indexed":false, 1206 | "name":"newTotalReserves", 1207 | "type":"uint256" 1208 | } 1209 | ], 1210 | "name":"ReservesReduced", 1211 | "type":"event", 1212 | "signature":"0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" 1213 | }, 1214 | { 1215 | "anonymous":false, 1216 | "inputs":[ 1217 | { 1218 | "indexed":false, 1219 | "name":"error", 1220 | "type":"uint256" 1221 | }, 1222 | { 1223 | "indexed":false, 1224 | "name":"info", 1225 | "type":"uint256" 1226 | }, 1227 | { 1228 | "indexed":false, 1229 | "name":"detail", 1230 | "type":"uint256" 1231 | } 1232 | ], 1233 | "name":"Failure", 1234 | "type":"event", 1235 | "signature":"0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" 1236 | }, 1237 | { 1238 | "anonymous":false, 1239 | "inputs":[ 1240 | { 1241 | "indexed":true, 1242 | "name":"from", 1243 | "type":"address" 1244 | }, 1245 | { 1246 | "indexed":true, 1247 | "name":"to", 1248 | "type":"address" 1249 | }, 1250 | { 1251 | "indexed":false, 1252 | "name":"amount", 1253 | "type":"uint256" 1254 | } 1255 | ], 1256 | "name":"Transfer", 1257 | "type":"event", 1258 | "signature":"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" 1259 | }, 1260 | { 1261 | "anonymous":false, 1262 | "inputs":[ 1263 | { 1264 | "indexed":true, 1265 | "name":"owner", 1266 | "type":"address" 1267 | }, 1268 | { 1269 | "indexed":true, 1270 | "name":"spender", 1271 | "type":"address" 1272 | }, 1273 | { 1274 | "indexed":false, 1275 | "name":"amount", 1276 | "type":"uint256" 1277 | } 1278 | ], 1279 | "name":"Approval", 1280 | "type":"event", 1281 | "signature":"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" 1282 | } 1283 | ] -------------------------------------------------------------------------------- /timelock/abi/timelock-abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { "internalType": "address", "name": "admin_", "type": "address" }, 5 | { "internalType": "uint256", "name": "delay_", "type": "uint256" } 6 | ], 7 | "stateMutability": "nonpayable", 8 | "type": "constructor" 9 | }, 10 | { 11 | "anonymous": false, 12 | "inputs": [ 13 | { 14 | "indexed": true, 15 | "internalType": "bytes32", 16 | "name": "txHash", 17 | "type": "bytes32" 18 | }, 19 | { 20 | "indexed": true, 21 | "internalType": "address", 22 | "name": "target", 23 | "type": "address" 24 | }, 25 | { 26 | "indexed": false, 27 | "internalType": "uint256", 28 | "name": "value", 29 | "type": "uint256" 30 | }, 31 | { 32 | "indexed": false, 33 | "internalType": "string", 34 | "name": "signature", 35 | "type": "string" 36 | }, 37 | { 38 | "indexed": false, 39 | "internalType": "bytes", 40 | "name": "data", 41 | "type": "bytes" 42 | }, 43 | { 44 | "indexed": false, 45 | "internalType": "uint256", 46 | "name": "eta", 47 | "type": "uint256" 48 | } 49 | ], 50 | "name": "CancelTransaction", 51 | "type": "event" 52 | }, 53 | { 54 | "anonymous": false, 55 | "inputs": [ 56 | { 57 | "indexed": true, 58 | "internalType": "bytes32", 59 | "name": "txHash", 60 | "type": "bytes32" 61 | }, 62 | { 63 | "indexed": true, 64 | "internalType": "address", 65 | "name": "target", 66 | "type": "address" 67 | }, 68 | { 69 | "indexed": false, 70 | "internalType": "uint256", 71 | "name": "value", 72 | "type": "uint256" 73 | }, 74 | { 75 | "indexed": false, 76 | "internalType": "string", 77 | "name": "signature", 78 | "type": "string" 79 | }, 80 | { 81 | "indexed": false, 82 | "internalType": "bytes", 83 | "name": "data", 84 | "type": "bytes" 85 | }, 86 | { 87 | "indexed": false, 88 | "internalType": "uint256", 89 | "name": "eta", 90 | "type": "uint256" 91 | } 92 | ], 93 | "name": "ExecuteTransaction", 94 | "type": "event" 95 | }, 96 | { 97 | "anonymous": false, 98 | "inputs": [ 99 | { 100 | "indexed": true, 101 | "internalType": "address", 102 | "name": "newAdmin", 103 | "type": "address" 104 | } 105 | ], 106 | "name": "NewAdmin", 107 | "type": "event" 108 | }, 109 | { 110 | "anonymous": false, 111 | "inputs": [ 112 | { 113 | "indexed": true, 114 | "internalType": "uint256", 115 | "name": "newDelay", 116 | "type": "uint256" 117 | } 118 | ], 119 | "name": "NewDelay", 120 | "type": "event" 121 | }, 122 | { 123 | "anonymous": false, 124 | "inputs": [ 125 | { 126 | "indexed": true, 127 | "internalType": "address", 128 | "name": "newPendingAdmin", 129 | "type": "address" 130 | } 131 | ], 132 | "name": "NewPendingAdmin", 133 | "type": "event" 134 | }, 135 | { 136 | "anonymous": false, 137 | "inputs": [ 138 | { 139 | "indexed": true, 140 | "internalType": "bytes32", 141 | "name": "txHash", 142 | "type": "bytes32" 143 | }, 144 | { 145 | "indexed": true, 146 | "internalType": "address", 147 | "name": "target", 148 | "type": "address" 149 | }, 150 | { 151 | "indexed": false, 152 | "internalType": "uint256", 153 | "name": "value", 154 | "type": "uint256" 155 | }, 156 | { 157 | "indexed": false, 158 | "internalType": "string", 159 | "name": "signature", 160 | "type": "string" 161 | }, 162 | { 163 | "indexed": false, 164 | "internalType": "bytes", 165 | "name": "data", 166 | "type": "bytes" 167 | }, 168 | { 169 | "indexed": false, 170 | "internalType": "uint256", 171 | "name": "eta", 172 | "type": "uint256" 173 | } 174 | ], 175 | "name": "QueueTransaction", 176 | "type": "event" 177 | }, 178 | { 179 | "inputs": [], 180 | "name": "GRACE_PERIOD", 181 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], 182 | "stateMutability": "view", 183 | "type": "function" 184 | }, 185 | { 186 | "inputs": [], 187 | "name": "MAXIMUM_DELAY", 188 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], 189 | "stateMutability": "view", 190 | "type": "function" 191 | }, 192 | { 193 | "inputs": [], 194 | "name": "MINIMUM_DELAY", 195 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], 196 | "stateMutability": "view", 197 | "type": "function" 198 | }, 199 | { 200 | "inputs": [], 201 | "name": "acceptAdmin", 202 | "outputs": [], 203 | "stateMutability": "nonpayable", 204 | "type": "function" 205 | }, 206 | { 207 | "inputs": [], 208 | "name": "admin", 209 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }], 210 | "stateMutability": "view", 211 | "type": "function" 212 | }, 213 | { 214 | "inputs": [], 215 | "name": "admin_initialized", 216 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], 217 | "stateMutability": "view", 218 | "type": "function" 219 | }, 220 | { 221 | "inputs": [ 222 | { "internalType": "address", "name": "target", "type": "address" }, 223 | { "internalType": "uint256", "name": "value", "type": "uint256" }, 224 | { "internalType": "string", "name": "signature", "type": "string" }, 225 | { "internalType": "bytes", "name": "data", "type": "bytes" }, 226 | { "internalType": "uint256", "name": "eta", "type": "uint256" } 227 | ], 228 | "name": "cancelTransaction", 229 | "outputs": [], 230 | "stateMutability": "nonpayable", 231 | "type": "function" 232 | }, 233 | { 234 | "inputs": [], 235 | "name": "delay", 236 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], 237 | "stateMutability": "view", 238 | "type": "function" 239 | }, 240 | { 241 | "inputs": [ 242 | { "internalType": "address", "name": "target", "type": "address" }, 243 | { "internalType": "uint256", "name": "value", "type": "uint256" }, 244 | { "internalType": "string", "name": "signature", "type": "string" }, 245 | { "internalType": "bytes", "name": "data", "type": "bytes" }, 246 | { "internalType": "uint256", "name": "eta", "type": "uint256" } 247 | ], 248 | "name": "executeTransaction", 249 | "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], 250 | "stateMutability": "payable", 251 | "type": "function" 252 | }, 253 | { 254 | "inputs": [], 255 | "name": "pendingAdmin", 256 | "outputs": [{ "internalType": "address", "name": "", "type": "address" }], 257 | "stateMutability": "view", 258 | "type": "function" 259 | }, 260 | { 261 | "inputs": [ 262 | { "internalType": "address", "name": "target", "type": "address" }, 263 | { "internalType": "uint256", "name": "value", "type": "uint256" }, 264 | { "internalType": "string", "name": "signature", "type": "string" }, 265 | { "internalType": "bytes", "name": "data", "type": "bytes" }, 266 | { "internalType": "uint256", "name": "eta", "type": "uint256" } 267 | ], 268 | "name": "queueTransaction", 269 | "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], 270 | "stateMutability": "nonpayable", 271 | "type": "function" 272 | }, 273 | { 274 | "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], 275 | "name": "queuedTransactions", 276 | "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], 277 | "stateMutability": "view", 278 | "type": "function" 279 | }, 280 | { 281 | "inputs": [ 282 | { "internalType": "uint256", "name": "delay_", "type": "uint256" } 283 | ], 284 | "name": "setDelay", 285 | "outputs": [], 286 | "stateMutability": "nonpayable", 287 | "type": "function" 288 | }, 289 | { 290 | "inputs": [ 291 | { "internalType": "address", "name": "pendingAdmin_", "type": "address" } 292 | ], 293 | "name": "setPendingAdmin", 294 | "outputs": [], 295 | "stateMutability": "nonpayable", 296 | "type": "function" 297 | }, 298 | { "stateMutability": "payable", "type": "receive" } 299 | ] 300 | -------------------------------------------------------------------------------- /timelock/abi/unitroller-abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs":[ 4 | 5 | ], 6 | "payable":false, 7 | "stateMutability":"nonpayable", 8 | "type":"constructor" 9 | }, 10 | { 11 | "anonymous":false, 12 | "inputs":[ 13 | { 14 | "indexed":false, 15 | "internalType":"uint256", 16 | "name":"error", 17 | "type":"uint256" 18 | }, 19 | { 20 | "indexed":false, 21 | "internalType":"uint256", 22 | "name":"info", 23 | "type":"uint256" 24 | }, 25 | { 26 | "indexed":false, 27 | "internalType":"uint256", 28 | "name":"detail", 29 | "type":"uint256" 30 | } 31 | ], 32 | "name":"Failure", 33 | "type":"event" 34 | }, 35 | { 36 | "anonymous":false, 37 | "inputs":[ 38 | { 39 | "indexed":false, 40 | "internalType":"address", 41 | "name":"oldAdmin", 42 | "type":"address" 43 | }, 44 | { 45 | "indexed":false, 46 | "internalType":"address", 47 | "name":"newAdmin", 48 | "type":"address" 49 | } 50 | ], 51 | "name":"NewAdmin", 52 | "type":"event" 53 | }, 54 | { 55 | "anonymous":false, 56 | "inputs":[ 57 | { 58 | "indexed":false, 59 | "internalType":"address", 60 | "name":"oldImplementation", 61 | "type":"address" 62 | }, 63 | { 64 | "indexed":false, 65 | "internalType":"address", 66 | "name":"newImplementation", 67 | "type":"address" 68 | } 69 | ], 70 | "name":"NewImplementation", 71 | "type":"event" 72 | }, 73 | { 74 | "anonymous":false, 75 | "inputs":[ 76 | { 77 | "indexed":false, 78 | "internalType":"address", 79 | "name":"oldPendingAdmin", 80 | "type":"address" 81 | }, 82 | { 83 | "indexed":false, 84 | "internalType":"address", 85 | "name":"newPendingAdmin", 86 | "type":"address" 87 | } 88 | ], 89 | "name":"NewPendingAdmin", 90 | "type":"event" 91 | }, 92 | { 93 | "anonymous":false, 94 | "inputs":[ 95 | { 96 | "indexed":false, 97 | "internalType":"address", 98 | "name":"oldPendingImplementation", 99 | "type":"address" 100 | }, 101 | { 102 | "indexed":false, 103 | "internalType":"address", 104 | "name":"newPendingImplementation", 105 | "type":"address" 106 | } 107 | ], 108 | "name":"NewPendingImplementation", 109 | "type":"event" 110 | }, 111 | { 112 | "payable":true, 113 | "stateMutability":"payable", 114 | "type":"fallback" 115 | }, 116 | { 117 | "constant":false, 118 | "inputs":[ 119 | 120 | ], 121 | "name":"_acceptAdmin", 122 | "outputs":[ 123 | { 124 | "internalType":"uint256", 125 | "name":"", 126 | "type":"uint256" 127 | } 128 | ], 129 | "payable":false, 130 | "stateMutability":"nonpayable", 131 | "type":"function" 132 | }, 133 | { 134 | "constant":false, 135 | "inputs":[ 136 | 137 | ], 138 | "name":"_acceptImplementation", 139 | "outputs":[ 140 | { 141 | "internalType":"uint256", 142 | "name":"", 143 | "type":"uint256" 144 | } 145 | ], 146 | "payable":false, 147 | "stateMutability":"nonpayable", 148 | "type":"function" 149 | }, 150 | { 151 | "constant":false, 152 | "inputs":[ 153 | { 154 | "internalType":"address", 155 | "name":"newPendingAdmin", 156 | "type":"address" 157 | } 158 | ], 159 | "name":"_setPendingAdmin", 160 | "outputs":[ 161 | { 162 | "internalType":"uint256", 163 | "name":"", 164 | "type":"uint256" 165 | } 166 | ], 167 | "payable":false, 168 | "stateMutability":"nonpayable", 169 | "type":"function" 170 | }, 171 | { 172 | "constant":false, 173 | "inputs":[ 174 | { 175 | "internalType":"address", 176 | "name":"newPendingImplementation", 177 | "type":"address" 178 | } 179 | ], 180 | "name":"_setPendingImplementation", 181 | "outputs":[ 182 | { 183 | "internalType":"uint256", 184 | "name":"", 185 | "type":"uint256" 186 | } 187 | ], 188 | "payable":false, 189 | "stateMutability":"nonpayable", 190 | "type":"function" 191 | }, 192 | { 193 | "constant":true, 194 | "inputs":[ 195 | 196 | ], 197 | "name":"admin", 198 | "outputs":[ 199 | { 200 | "internalType":"address", 201 | "name":"", 202 | "type":"address" 203 | } 204 | ], 205 | "payable":false, 206 | "stateMutability":"view", 207 | "type":"function" 208 | }, 209 | { 210 | "constant":true, 211 | "inputs":[ 212 | 213 | ], 214 | "name":"comptrollerImplementation", 215 | "outputs":[ 216 | { 217 | "internalType":"address", 218 | "name":"", 219 | "type":"address" 220 | } 221 | ], 222 | "payable":false, 223 | "stateMutability":"view", 224 | "type":"function" 225 | }, 226 | { 227 | "constant":true, 228 | "inputs":[ 229 | 230 | ], 231 | "name":"pendingAdmin", 232 | "outputs":[ 233 | { 234 | "internalType":"address", 235 | "name":"", 236 | "type":"address" 237 | } 238 | ], 239 | "payable":false, 240 | "stateMutability":"view", 241 | "type":"function" 242 | }, 243 | { 244 | "constant":true, 245 | "inputs":[ 246 | 247 | ], 248 | "name":"pendingComptrollerImplementation", 249 | "outputs":[ 250 | { 251 | "internalType":"address", 252 | "name":"", 253 | "type":"address" 254 | } 255 | ], 256 | "payable":false, 257 | "stateMutability":"view", 258 | "type":"function" 259 | } 260 | ] -------------------------------------------------------------------------------- /timelock/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * timelock contract address 3 | */ 4 | export const contract_address : any = { 5 | 3: { 6 | 'unitroller': '0x52Ab60E7F463B73C6A90ee116dBB18ac61DC63FF', 7 | 'comptroller': '0x52Ab60E7F463B73C6A90ee116dBB18ac61DC63FF', 8 | 'cToken1': '', 9 | 'cToken2': '', 10 | 'cTokenn': '' 11 | }, 12 | 1: { 13 | 'unitroller': '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B', 14 | 'comptroller': '0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B', 15 | 'cToken1': '', 16 | 'cToken2': '', 17 | 'cTokenn': '' 18 | } 19 | } 20 | 21 | /** 22 | * contract abi file name 23 | */ 24 | export const contract_abi_file : any = { 25 | 'unitroller': 'unitroller-abi.json', 26 | 'comptroller': 'comptroller-abi.json', 27 | 'cToken1': 'cToken-abi.json', 28 | 'cToken2': 'cToken-abi.json', 29 | 'cTokenn': 'cToken-abi.json' 30 | } 31 | 32 | /** 33 | * deplay Offset, unit: seconds 34 | */ 35 | export const delay_offset = 300; 36 | 37 | /** 38 | * Current timelock address 39 | */ 40 | export const timelock_address : any = { 41 | 1: '0x6d903f6003cca6255D85CcA4D3B5E5146dC33925', 42 | 3: '0x4168FE8179C5e99074068244413909F40c4301B2' 43 | } 44 | 45 | /** 46 | * contract timelock queue transaction functions 47 | */ 48 | export const queue_functions : any = { 49 | 'unitroller': ['_acceptAdmin', '_setPendingAdmin', '_setPendingImplementation'], 50 | 'comptroller': ['_become', '_setBorrowPaused', '_setMiningBuff', '_setCompRate', '_setMintPaused', '_supportMarket', '_dropCompMarket', '_setPriceOracle', '_setCollateralFactor'], 51 | 'cToken1': ['_acceptAdmin', '_setReserveFactor'], 52 | 'cToken2': ['_acceptAdmin', '_setReserveFactor'], 53 | 'cTokenn': ['_acceptAdmin', '_setReserveFactor'] 54 | } 55 | 56 | -------------------------------------------------------------------------------- /timelock/contracts.ts: -------------------------------------------------------------------------------- 1 | import { contract_address, queue_functions, contract_abi_file } from './constants'; 2 | import { IABIFunction, ITokenContract } from './interface'; 3 | 4 | class Contracts { 5 | private contractsObject: any; 6 | constructor(chainId: number) { 7 | if(!contract_address.hasOwnProperty(chainId)) { 8 | throw new Error(`Don\'t support the current network ${chainId}`); 9 | } 10 | this.contractsObject = contract_address[chainId]; 11 | } 12 | 13 | private parseSignature(abiFunc: any) { 14 | let inputType : Array = []; 15 | for(let i = 0; i < abiFunc.inputs.length; i++) { 16 | inputType.push(abiFunc.inputs[i].type); 17 | } 18 | 19 | return `${abiFunc.name}(${inputType.join(',')})`; 20 | } 21 | 22 | private parseFunctions(abi: any, functions: Array) { 23 | let parsedFunctions : Array = []; 24 | for(let i = 0; i < functions.length; i++) { 25 | 26 | let abiFunctionObjList : Array = abi.filter((abiItem: any) => { 27 | return functions[i] == abiItem.name && 'function' == abiItem.type; 28 | }); 29 | 30 | if(abiFunctionObjList.length > 0) { 31 | const abiFunctionObj : any = abiFunctionObjList[0]; 32 | let abiFunction: IABIFunction = { 33 | name: abiFunctionObj.name, 34 | inputs: abiFunctionObj.inputs, 35 | signature: this.parseSignature(abiFunctionObj), 36 | 37 | abi: abiFunctionObj, 38 | inputValue: '' 39 | }; 40 | 41 | parsedFunctions.push(abiFunction); 42 | } 43 | } 44 | 45 | return parsedFunctions; 46 | } 47 | 48 | get timelockContracs() : Array { 49 | let res : Array = []; 50 | for(let key in this.contractsObject) { 51 | let tokenContract : ITokenContract = { 52 | name: key, 53 | address: this.contractsObject[key] 54 | } 55 | const abiFileName : string = contract_abi_file[key]; 56 | const abi = require(`~/timelock/abi/${abiFileName}`); 57 | const functions : Array = queue_functions[key]; 58 | tokenContract.functions = this.parseFunctions(abi, functions); 59 | 60 | res.push(tokenContract); 61 | } 62 | return res; 63 | } 64 | } 65 | 66 | export default Contracts; -------------------------------------------------------------------------------- /timelock/dataStorage.ts: -------------------------------------------------------------------------------- 1 | import { ITokenContract } from './interface'; 2 | 3 | class DataStorage { 4 | constructor() { 5 | 6 | } 7 | 8 | get tempTokenContract() : ITokenContract | null { 9 | const strTokenContract : string | null = window.localStorage.getItem('temp_token_contract'); 10 | if(strTokenContract) { 11 | try{ 12 | let res : ITokenContract = {}; 13 | const data : any = JSON.parse(strTokenContract); 14 | res = {...data}; 15 | 16 | return res; 17 | } 18 | catch(e) { 19 | return null; 20 | } 21 | } 22 | 23 | return null; 24 | } 25 | 26 | set tempTokenContract(value : ITokenContract | null) { 27 | if(null == value) { 28 | window.localStorage.removeItem('temp_token_contract'); 29 | } 30 | else { 31 | window.localStorage.setItem('temp_token_contract', JSON.stringify(value)); 32 | } 33 | } 34 | } 35 | 36 | export default DataStorage; -------------------------------------------------------------------------------- /timelock/error.ts: -------------------------------------------------------------------------------- 1 | class ErrorHelper { 2 | static parse(error: any) { 3 | if('object' == typeof error) { 4 | if(error.hasOwnProperty('error')) { 5 | if(error.error.hasOwnProperty('reason')) { 6 | return error.error.reason; 7 | } 8 | else { 9 | return error.error.message; 10 | } 11 | } 12 | else { 13 | if(error.hasOwnProperty('message')){ 14 | error = error.message; 15 | if(error.indexOf('(') > -1) { 16 | error = error.substr(0, error.indexOf('(')); 17 | } 18 | return error; 19 | } 20 | else { 21 | if(error.indexOf('(') > -1) { 22 | error = error.substr(error.indexOf('(')); 23 | } 24 | return error; 25 | } 26 | } 27 | } 28 | else { 29 | return error; 30 | } 31 | } 32 | } 33 | 34 | export default ErrorHelper; -------------------------------------------------------------------------------- /timelock/interface.ts: -------------------------------------------------------------------------------- 1 | export interface IABIFunction { 2 | signature?: string; 3 | name?: string; 4 | inputs?: Array; 5 | abi?: any; 6 | inputValue?: any; 7 | } 8 | 9 | export interface ITokenContract { 10 | name?: string; 11 | address?: string; 12 | functions?: Array; 13 | } 14 | 15 | export interface ITimelockTransaction { 16 | data?:string; 17 | txData?: string; 18 | txDataHash?: string; 19 | funcData?: string; 20 | from?: string; 21 | blockNumber?: number; 22 | timestamp?: any; 23 | hash?: string; 24 | decodedFunction?: any; 25 | isQueued?: any; 26 | targetInfo?: any; 27 | executeOrCancelTransaction?: ITimelockTransaction; 28 | } -------------------------------------------------------------------------------- /timelock/provider.ts: -------------------------------------------------------------------------------- 1 | import { accountsChanged, chainChanged } from '~/timelock/wallet' 2 | import BigNumber from 'bignumber.js'; 3 | 4 | declare var ethereum: any; 5 | 6 | class EthereumProvider { 7 | constructor() { 8 | if(ethereum && ethereum.isMetaMask) { 9 | console.log('ethereum provider init...'); 10 | } 11 | else { 12 | throw new Error('Don\'t support then current ethereum wallet.'); 13 | } 14 | } 15 | 16 | async connect(): Promise { 17 | const accounts = await ethereum.request({ 18 | method: 'eth_requestAccounts', 19 | }); 20 | return accounts.length > 0 ? accounts[0] : null; 21 | } 22 | 23 | monitor(options: any) { 24 | accountsChanged((account: string | null) => { 25 | if ('function' == typeof options.accountChanged) { 26 | options.accountChanged(account) 27 | } 28 | }) 29 | chainChanged((chainId: string | number) => { 30 | chainId = new BigNumber(chainId).toNumber() 31 | if ('function' == typeof options.chainChanged) { 32 | options.chainChanged(chainId) 33 | } 34 | }) 35 | } 36 | 37 | get provider() : any { 38 | return ethereum; 39 | } 40 | 41 | get chainId() : number { 42 | const res : any = new BigNumber(ethereum.chainId); 43 | return res.toNumber(); 44 | } 45 | } 46 | 47 | export default EthereumProvider; -------------------------------------------------------------------------------- /timelock/timelock.ts: -------------------------------------------------------------------------------- 1 | import EthereumProvider from './provider'; 2 | import ethers from 'ethers'; 3 | import timelockAbi from './abi/timelock-abi.json'; 4 | import { ITimelockTransaction } from './interface'; 5 | import { timelock_address, contract_address, contract_abi_file} from './constants' 6 | 7 | const abiDecoder = require('abi-decoder') 8 | 9 | abiDecoder.addABI(timelockAbi); 10 | 11 | function useAbiDecoder() { 12 | let contractFileNameList : Array = []; 13 | for(let key in contract_abi_file) { 14 | contractFileNameList.push(contract_abi_file[key]); 15 | } 16 | 17 | contractFileNameList = Array.from(new Set(contractFileNameList)); 18 | for(let i = 0;i < contractFileNameList.length; i++ ) { 19 | const abiFileName : string = contractFileNameList[i]; 20 | const abi = require(`~/timelock/abi/${abiFileName}`); 21 | abiDecoder.addABI(abi); 22 | } 23 | } 24 | 25 | useAbiDecoder(); 26 | 27 | const specialFunctionNames = [ 28 | "queueTransaction", 29 | "cancelTransaction", 30 | "executeTransaction", 31 | ]; 32 | 33 | class TimelockHelper { 34 | private ethereumProvider: EthereumProvider; 35 | private account: string | null = ''; 36 | private address: string = ''; 37 | private contractAddress: any = {}; 38 | 39 | constructor(ethereumProvider: EthereumProvider) { 40 | this.ethereumProvider = ethereumProvider; 41 | this.setAddress() 42 | } 43 | 44 | async connect() { 45 | this.account = await this.ethereumProvider.connect(); 46 | return this.account; 47 | } 48 | 49 | setAddress() { 50 | this.address = timelock_address[this.ethereumProvider.chainId]; 51 | this.contractAddress = contract_address[this.ethereumProvider.chainId]; 52 | } 53 | 54 | private trx(method: string, params: Array) { 55 | return new Promise(async (resolve, reject) => { 56 | const provider = new ethers.providers.Web3Provider(this.ethereumProvider.provider).getSigner(); 57 | const contract = new ethers.Contract(this.address, timelockAbi, provider); 58 | 59 | contract[method].apply(null, params).then((result : any) => { 60 | resolve(result); 61 | }).catch((error: any) => { 62 | reject({ 63 | message: 'Error occurred during [eth_sendTransaction]. See {error}.', 64 | error, 65 | method, 66 | params, 67 | }); 68 | }); 69 | }); 70 | } 71 | 72 | private qrx(method: string, params: Array) { 73 | return new Promise(async (resolve, reject) => { 74 | const provider = new ethers.providers.Web3Provider(this.ethereumProvider.provider).getSigner(); 75 | const contract = new ethers.Contract(this.address, timelockAbi, provider); 76 | 77 | contract.callStatic[method].apply(null, params).then((result) => { 78 | resolve(result); 79 | }).catch((error) => { 80 | reject({ 81 | message: 'Error occurred during [eth_call]. See {error}.', 82 | error, 83 | method, 84 | params, 85 | }); 86 | }); 87 | 88 | }); 89 | } 90 | 91 | async queueTransaction(params: Array) { 92 | return await this.trx('queueTransaction', params); 93 | } 94 | 95 | async executeTransaction(params: Array) { 96 | return await this.trx('executeTransaction', params); 97 | } 98 | 99 | async cancelTransaction(params: Array) { 100 | return await this.trx('cancelTransaction', params); 101 | } 102 | 103 | abiEncode(types: Array, params: Array) { 104 | return ethers.utils.defaultAbiCoder.encode(types, params); 105 | } 106 | 107 | async getDelay() : Promise { 108 | const delay : any = await this.qrx('delay', []); 109 | return delay.toNumber(); 110 | } 111 | 112 | async getTimestamp() : Promise { 113 | const provider = new ethers.providers.Web3Provider(this.ethereumProvider.provider); 114 | const block : any = await provider.getBlock('latest'); 115 | return block.timestamp; 116 | } 117 | 118 | async queuedTransactions(txHash: any) { 119 | return await this.qrx('queuedTransactions', [txHash]); 120 | } 121 | 122 | async getHistoryTransactions() { 123 | 124 | var getTargetKey = function(contractAddress: any, target: any) { 125 | let res = ''; 126 | for(let key in contractAddress) { 127 | if(contractAddress.hasOwnProperty(key)) { 128 | let value = contractAddress[key].toLowerCase(); 129 | if(value == target.toLowerCase()) { 130 | res = key; 131 | break; 132 | } 133 | } 134 | } 135 | return res; 136 | } 137 | 138 | const etherscanProvider = new ethers.providers.EtherscanProvider(this.ethereumProvider.chainId); 139 | const history = await etherscanProvider.getHistory(this.address); 140 | let newest = history.slice(1).reverse(); 141 | 142 | const decoded = newest.map( 143 | ({ data, from, blockNumber, timestamp, hash }) => { 144 | 145 | let item: ITimelockTransaction = {data, from, blockNumber, timestamp, hash}; 146 | if('undefined' === typeof data || '0x' == data) { 147 | item.txData = ''; 148 | item.txDataHash = ''; 149 | item.funcData = '0x' ; 150 | item.targetInfo = ''; 151 | item.decodedFunction = {}; 152 | return item; 153 | } 154 | else { 155 | const decodedFunction = abiDecoder.decodeMethod(data); 156 | if (specialFunctionNames.includes(decodedFunction.name)) { 157 | // target, value, signature, data, eta 158 | try{ 159 | const txData = this.abiEncode(['address','uint256','string','bytes','uint256'], [decodedFunction.params[0].value, decodedFunction.params[1].value, decodedFunction.params[2].value, null == decodedFunction.params[3].value ? '0x' : decodedFunction.params[3].value, decodedFunction.params[4].value]); 160 | const txDataHash = ethers.utils.keccak256(txData); 161 | 162 | item.txData = txData; 163 | item.txDataHash = txDataHash; 164 | } 165 | catch(e) { 166 | item.txData = ''; 167 | item.txDataHash = ''; 168 | } 169 | const funcData = decodedFunction.params[3].value; 170 | item.funcData = null == funcData ? '0x' : funcData; 171 | 172 | if(null !== funcData) { 173 | let decodedData = abiDecoder.decodeMethod(funcData); 174 | 175 | if('undefined' == typeof decodedData) { 176 | const signature = decodedFunction.params[2].value; 177 | const functionParams = signature 178 | .split("(")[1] 179 | .split(")")[0] 180 | .split(","); 181 | decodedData = ethers.utils.defaultAbiCoder.decode( 182 | functionParams, 183 | funcData 184 | ); 185 | decodedFunction.params[3].value = decodedData.length == 0 ? [] : "[" + decodedData.map((x : any) => x.toString()).join(", ") + "]"; 186 | } 187 | else { 188 | decodedFunction.params[3].value = decodedData.params.map ((_data: any) => { 189 | return _data.value; 190 | }); 191 | } 192 | 193 | const target = decodedFunction.params[0].value; 194 | item.targetInfo = getTargetKey(this.contractAddress, target); 195 | } 196 | 197 | item.decodedFunction = decodedFunction; 198 | return item; 199 | } 200 | 201 | } 202 | 203 | return item; 204 | } 205 | ); 206 | return decoded; 207 | } 208 | 209 | queuedTransaction(tx: ITimelockTransaction) { 210 | return new Promise(async (resolve) => { 211 | const isTxQueued : any = '' == tx.txDataHash ? true : await this.queuedTransactions(tx.txDataHash); 212 | tx.isQueued = isTxQueued; 213 | resolve(tx); 214 | }); 215 | } 216 | 217 | getHistoryTransactionsWithQueuedStatus(): Promise> { 218 | return new Promise(async (resolve, reject) => { 219 | const historyTxList : Array = await this.getHistoryTransactions(); 220 | let queuedTxList : Array = []; 221 | for(let i = 0; i < historyTxList.length; i++) { 222 | 223 | const tx = historyTxList[i]; 224 | queuedTxList.push(this.queuedTransaction(tx)); 225 | } 226 | Promise.all(queuedTxList).then(res => { 227 | resolve(res); 228 | }).catch((error: any) => { 229 | reject(error); 230 | }); 231 | }); 232 | } 233 | 234 | getHistoryQueueTransactions(): Promise> { 235 | return new Promise(async (resolve, reject) => { 236 | try{ 237 | const historyTransactionList : Array = await this.getHistoryTransactionsWithQueuedStatus(); 238 | let historyQueueTransactionList : Array = historyTransactionList.filter((tx: ITimelockTransaction) => { 239 | return 'queueTransaction' === tx.decodedFunction.name; 240 | }); 241 | 242 | const historyExecuteOrCancelTransactionList : Array = historyTransactionList.filter((tx: ITimelockTransaction) => { 243 | return 'queueTransaction' !== tx.decodedFunction.name; 244 | }); 245 | 246 | historyQueueTransactionList = historyQueueTransactionList.map((tx: ITimelockTransaction) => { 247 | const executeOrCancelTransactionList : Array = historyExecuteOrCancelTransactionList.filter((_tx: ITimelockTransaction) => { 248 | return tx.txDataHash == _tx.txDataHash; 249 | }); 250 | if(executeOrCancelTransactionList.length > 0) { 251 | tx.executeOrCancelTransaction = executeOrCancelTransactionList[0]; 252 | } 253 | return tx; 254 | }); 255 | 256 | resolve(historyQueueTransactionList); 257 | } 258 | catch(error) { 259 | reject(error); 260 | } 261 | }); 262 | } 263 | 264 | async getAdminAddress(): Promise { 265 | const address: any = await this.trx('admin', []); 266 | return address 267 | } 268 | 269 | } 270 | 271 | export default TimelockHelper; -------------------------------------------------------------------------------- /timelock/wallet.ts: -------------------------------------------------------------------------------- 1 | declare const ethereum: any 2 | 3 | export async function accountsChanged(cb: Function) { 4 | if (ethereum.isImToken) { 5 | return 6 | } 7 | ethereum.on('accountsChanged', (accounts: any) => { 8 | cb(accounts.length > 0 ? accounts[0] : null) 9 | }) 10 | } 11 | 12 | export async function chainChanged(cb: Function) { 13 | if (ethereum.isImToken) { 14 | return 15 | } 16 | ethereum.on('chainChanged', (chainId: string | number) => { 17 | cb(chainId) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "resolveJsonModule": true, 7 | "lib": [ 8 | "esnext", 9 | "esnext.asynciterable", 10 | "dom" 11 | ], 12 | "esModuleInterop": true, 13 | "allowJs": true, 14 | "sourceMap": true, 15 | "strict": true, 16 | "noEmit": true, 17 | "experimentalDecorators": true, 18 | "baseUrl": ".", 19 | "paths": { 20 | "~/*": [ 21 | "./*" 22 | ], 23 | "@/*": [ 24 | "./*" 25 | ] 26 | }, 27 | "types": [ 28 | "@types/node", 29 | "@nuxt/types" 30 | ] 31 | }, 32 | "exclude": [ 33 | "node_modules", 34 | ".nuxt", 35 | "dist" 36 | ] 37 | } 38 | --------------------------------------------------------------------------------