From f754de9acb1e8513acbfca2163b7ccef64822121 Mon Sep 17 00:00:00 2001 From: Jared Flatow Date: Mon, 26 Aug 2019 18:41:57 -0700 Subject: [PATCH] Initial Public Commit --- .circleci/config.yml | 173 + .dockerignore | 5 + .gitignore | 27 + .solcover.js | 8 + .soliumignore | 2 + .soliumrc.json | 16 + Dockerfile | 32 + LICENSE | 5 + README.md | 182 + contracts/CErc20.sol | 215 + contracts/CEther.sol | 168 + contracts/CToken.sol | 1572 ++ contracts/CarefulMath.sol | 85 + contracts/Comptroller.sol | 996 + contracts/ComptrollerInterface.sol | 75 + contracts/ComptrollerStorage.sol | 55 + contracts/EIP20Interface.sol | 59 + contracts/EIP20NonStandardInterface.sol | 70 + contracts/ErrorReporter.sol | 204 + contracts/Exponential.sol | 226 + contracts/InterestRateModel.sol | 29 + contracts/Maximillion.sol | 49 + contracts/PriceOracle.sol | 18 + contracts/PriceOracleProxy.sol | 88 + contracts/ReentrancyGuard.sol | 32 + contracts/SimplePriceOracle.sol | 26 + contracts/Unitroller.sol | 152 + contracts/WhitePaperInterestRateModel.sol | 133 + docs/CompoundProtocol.pdf | Bin 0 -> 1324870 bytes docs/CompoundWhitepaper.pdf | Bin 0 -> 192934 bytes migrations/.gitkeep | 0 networks/.gitkeep | 0 networks/README.md | 26 + networks/goerli-abi.json | 13952 ++++++++++++++ networks/goerli.json | 296 + networks/kovan-abi.json | 13952 ++++++++++++++ networks/kovan.json | 296 + networks/mainnet-abi.json | 13598 ++++++++++++++ networks/mainnet.json | 269 + networks/rinkeby-abi.json | 15614 ++++++++++++++++ networks/rinkeby.json | 291 + networks/ropsten-abi.json | 13952 ++++++++++++++ networks/ropsten.json | 296 + package.json | 38 + reporterConfig.json | 3 + scenario/Grammar.pegjs | 318 + scenario/SCENARIO.md | 219 + scenario/package.json | 30 + scenario/script/generate_parser | 11 + scenario/script/repl | 78 + scenario/script/tsc | 14 + scenario/script/webpack | 16 + scenario/src/Accounts.ts | 48 + scenario/src/Action.ts | 15 + scenario/src/Artifact.ts | 5 + scenario/src/Assert.ts | 21 + scenario/src/Builder/CTokenBuilder.ts | 244 + .../src/Builder/ComptrollerImplBuilder.ts | 175 + scenario/src/Builder/Erc20Builder.ts | 185 + .../src/Builder/InterestRateModelBuilder.ts | 100 + scenario/src/Builder/MaximillionBuilder.ts | 64 + scenario/src/Builder/PriceOracleBuilder.ts | 165 + .../src/Builder/PriceOracleProxyBuilder.ts | 70 + scenario/src/Builder/UnitrollerBuilder.ts | 58 + scenario/src/Command.ts | 248 + scenario/src/Completer.ts | 36 + scenario/src/Contract.ts | 221 + scenario/src/Contract/CToken.ts | 57 + scenario/src/Contract/Comptroller.ts | 40 + scenario/src/Contract/ComptrollerImpl.ts | 11 + scenario/src/Contract/Erc20.ts | 24 + scenario/src/Contract/InterestRateModel.ts | 12 + scenario/src/Contract/Maximillion.ts | 11 + scenario/src/Contract/PriceOracle.ts | 29 + scenario/src/Contract/PriceOracleProxy.ts | 10 + scenario/src/Contract/Unitroller.ts | 12 + scenario/src/ContractLookup.ts | 158 + scenario/src/CoreEvent.ts | 565 + scenario/src/CoreValue.ts | 547 + scenario/src/Encoding.ts | 37 + scenario/src/ErrorReporter.ts | 98 + scenario/src/ErrorReporterConstants.ts | 183 + scenario/src/Event.ts | 7 + scenario/src/Event/AssertionEvent.ts | 345 + scenario/src/Event/CTokenEvent.ts | 717 + scenario/src/Event/ComptrollerEvent.ts | 447 + scenario/src/Event/ComptrollerImplEvent.ts | 147 + scenario/src/Event/Erc20Event.ts | 251 + scenario/src/Event/ExpectationEvent.ts | 68 + scenario/src/Event/InterestRateModelEvent.ts | 84 + scenario/src/Event/InvariantEvent.ts | 83 + scenario/src/Event/MaximillionEvent.ts | 104 + scenario/src/Event/PriceOracleEvent.ts | 120 + scenario/src/Event/PriceOracleProxyEvent.ts | 81 + scenario/src/Event/TrxEvent.ts | 56 + scenario/src/Event/UnitrollerEvent.ts | 98 + scenario/src/Expectation.ts | 4 + .../src/Expectation/ChangesExpectation.ts | 47 + .../src/Expectation/RemainsExpectation.ts | 32 + scenario/src/File.ts | 32 + scenario/src/Formatter.ts | 25 + scenario/src/Help.ts | 64 + scenario/src/HistoricReadline.ts | 35 + scenario/src/Invariant.ts | 5 + scenario/src/Invariant/RemainsInvariant.ts | 33 + scenario/src/Invariant/StaticInvariant.ts | 33 + scenario/src/Invariant/SuccessInvariant.ts | 21 + scenario/src/Invokation.ts | 274 + scenario/src/Macro.ts | 98 + scenario/src/Networks.ts | 140 + scenario/src/Parser.ts | 3210 ++++ scenario/src/Printer.ts | 120 + scenario/src/Repl.d.ts | 9 + scenario/src/Repl.ts | 168 + scenario/src/Runner.ts | 20 + scenario/src/Settings.ts | 75 + scenario/src/Utils.ts | 62 + scenario/src/Value.ts | 386 + scenario/src/Value/CTokenValue.ts | 293 + scenario/src/Value/ComptrollerImplValue.ts | 35 + scenario/src/Value/ComptrollerValue.ts | 313 + scenario/src/Value/Erc20Value.ts | 160 + scenario/src/Value/InterestRateModelValue.ts | 38 + scenario/src/Value/MaximillionValue.ts | 34 + scenario/src/Value/PriceOracleProxyValue.ts | 52 + scenario/src/Value/PriceOracleValue.ts | 52 + scenario/src/Value/UnitrollerValue.ts | 34 + scenario/src/Value/UserValue.ts | 36 + scenario/src/Verify.ts | 157 + scenario/src/Web.ts | 29 + scenario/src/World.ts | 346 + scenario/tsconfig.json | 63 + scenario/webpack.config.js | 28 + scenario/yarn.lock | 5093 +++++ script/README.md | 1 + script/certora/Dockerfile | 7 + script/console | 11 + script/coverage | 23 + script/ganache | 11 + script/ganache-coverage | 11 + script/javascript/buildTruffle.js | 99 + script/javascript/networkId.js | 3 + script/lint | 8 + script/scen/deploy.scen | 31 + script/scenario | 9 + script/test | 35 + script/verify | 36 + spec/formal/CompoundIgnoreExtCalls.spclnk | 13 + spec/formal/EIP20.spclnk | 145 + spec/formal/Liquidate.spclnk | 208 + spec/formal/Maximillion.spclnk | 127 + spec/formal/MintRedeemBorrowRepay.spclnk | 209 + spec/formal/_setMarketPolicyHook.cvl | 72 + spec/formal/_setMarketPriceOracle.cvl | 63 + spec/formal/accrueInterest.cvl | 77 + spec/formal/admin_setCollateralFactor.cvl | 101 + spec/formal/borrowAndRepayFresh.cvl | 257 + spec/formal/compound.cvl | 266 + spec/formal/contracts/CErc20Certora.sol | 164 + spec/formal/contracts/CEtherCertora.sol | 13 + spec/formal/contracts/CTokenCollateral.sol | 19 + spec/formal/contracts/ComptrollerModel.sol | 100 + spec/formal/contracts/MaximillionCertora.sol | 19 + spec/formal/contracts/SimulationInterface.sol | 5 + .../contracts/UnderlyingModelNonStandard.sol | 55 + spec/formal/dummy.cvl | 1 + spec/formal/eip20.cvl | 154 + spec/formal/frame.cvl | 359 + spec/formal/general.cvl | 167 + spec/formal/liquidateFresh.cvl | 331 + spec/formal/maximillion.cvl | 33 + spec/formal/mintAndRedeemFresh.cvl | 447 + spec/scenario/Borrow.scen | 46 + spec/scenario/Borrow.scen.old | 87 + spec/scenario/BorrowBalance.scen | 84 + spec/scenario/BorrowEth.scen | 49 + spec/scenario/BorrowWBTC.scen | 62 + spec/scenario/BreakLiquidate.scen | 82 + spec/scenario/CTokenAdmin.scen | 30 + spec/scenario/CoreMacros | 185 + spec/scenario/EnterExitMarkets.scen | 157 + spec/scenario/Excel.scen.old | 119 + spec/scenario/ExchangeRate.scen | 73 + .../HypotheticalAccountLiquidity.scen | 49 + spec/scenario/Liquidate.scen | 520 + spec/scenario/Liquidate.scen.old | 142 + spec/scenario/LiquidateEthBorrow.scen | 138 + spec/scenario/LiquidateEthCollateral.scen | 140 + spec/scenario/Mint.scen | 90 + spec/scenario/MintEth.scen | 66 + spec/scenario/MintWBTC.scen | 91 + spec/scenario/ReEntry.scen | 13 + spec/scenario/Redeem.scen | 227 + spec/scenario/RedeemEth.scen | 156 + spec/scenario/RedeemUnderlying.scen | 182 + spec/scenario/RedeemUnderlyingEth.scen | 171 + spec/scenario/RedeemUnderlyingWBTC.scen | 183 + spec/scenario/RedeemWBTC.scen | 226 + spec/scenario/ReduceReserves.scen | 136 + spec/scenario/RepayBorrow.scen | 173 + spec/scenario/RepayBorrowEth.scen | 206 + spec/scenario/RepayBorrowWBTC.scen | 189 + spec/scenario/Seize.scen | 50 + spec/scenario/SetComptroller.scen | 26 + spec/scenario/Supply.scen.old | 59 + spec/scenario/TokenTransfer.scen | 86 + spec/scenario/Unitroller.scen | 59 + spec/scenario/Withdraw.scen.old | 48 + .../admin/setMarketPolicyHook.scen.old | 41 + .../admin/setMarketPriceOracle.scen.old | 38 + test/CarefulMathTest.sol | 167 + test/Comptroller/accountLiquidityTest.js | 117 + test/Comptroller/adminTest.js | 110 + test/Comptroller/assetsListTest.js | 186 + test/Comptroller/comptrollerTest.js | 250 + .../liquidateCalculateAmountSeizeTest.js | 97 + test/Comptroller/proxiedComptrollerV1Test.js | 192 + test/Comptroller/unitrollerTest.js | 180 + test/Errors.js | 50 + test/ExponentialTest.sol | 467 + test/MaximillionTest.js | 66 + test/Models/interestRateModelTest.js | 150 + test/PriceOracleProxyTest.js | 129 + test/ScenarioTest.js | 121 + test/SpinaramaTest.js | 315 + test/Tokens/accrueInterestTest.js | 139 + test/Tokens/adminTest.js | 109 + test/Tokens/borrowAndRepayCEtherTest.js | 362 + test/Tokens/borrowAndRepayTest.js | 390 + test/Tokens/cTokenTest.js | 200 + test/Tokens/liquidateTest.js | 270 + test/Tokens/mintAndRedeemCEtherTest.js | 129 + test/Tokens/mintAndRedeemTest.js | 342 + test/Tokens/reservesTest.js | 209 + test/Tokens/safeTokenTest.js | 69 + test/Tokens/setComptrollerTest.js | 48 + test/Tokens/setInterestRateModelTest.js | 103 + test/Tokens/transferTest.js | 52 + test/Utils/Compound.js | 378 + test/Utils/JS.js | 24 + test/Utils/MochaTruffle.js | 266 + test/contracts/BasicToken.sol | 50 + test/contracts/BasicTokenNS.sol | 50 + test/contracts/BoolComptroller.sol | 278 + test/contracts/CErc20Harness.sol | 187 + test/contracts/CErc20Scenario.sol | 40 + test/contracts/CEtherHarness.sol | 207 + test/contracts/CEtherScenario.sol | 44 + test/contracts/CEvil.sol | 25 + test/contracts/ComptrollerBorked.sol | 18 + test/contracts/ComptrollerHarness.sol | 18 + test/contracts/ComptrollerScenario.sol | 48 + test/contracts/DSValueHarness.sol | 32 + test/contracts/EIP20Harness.sol | 123 + test/contracts/EIP20NonCompliantHarness.sol | 27 + .../EIP20NonStandardReturnHarness.sol | 123 + .../EIP20NonStandardThrowHarness.sol | 123 + test/contracts/ERC20.sol | 15 + test/contracts/ERC20Basic.sol | 14 + test/contracts/ERC20BasicNS.sol | 13 + test/contracts/ERC20NS.sol | 16 + test/contracts/ERC20NonView.sol | 196 + test/contracts/EchoTypesComptroller.sol | 31 + test/contracts/EvilToken.sol | 59 + .../FalseMarkerMethodComptroller.sol | 6 + .../FalseMarkerMethodInterestRateModel.sol | 36 + test/contracts/FaucetNonStandardToken.sol | 31 + test/contracts/FaucetToken.sol | 31 + .../contracts/FaucetTokenReEntrantHarness.sol | 75 + test/contracts/FixedPriceOracle.sol | 22 + test/contracts/InterestRateModelHarness.sol | 37 + test/contracts/MathHelpers.sol | 12 + test/contracts/NonStandardToken.sol | 122 + test/contracts/NotPriceOracle.sol | 6 + test/contracts/SafeMath.sol | 52 + test/contracts/StandardToken.sol | 124 + test/contracts/WBTC.sol | 672 + truffle.js | 88 + yarn.lock | 6179 ++++++ 279 files changed, 118770 insertions(+) create mode 100644 .circleci/config.yml create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .solcover.js create mode 100644 .soliumignore create mode 100644 .soliumrc.json create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 contracts/CErc20.sol create mode 100644 contracts/CEther.sol create mode 100644 contracts/CToken.sol create mode 100644 contracts/CarefulMath.sol create mode 100644 contracts/Comptroller.sol create mode 100644 contracts/ComptrollerInterface.sol create mode 100644 contracts/ComptrollerStorage.sol create mode 100644 contracts/EIP20Interface.sol create mode 100644 contracts/EIP20NonStandardInterface.sol create mode 100644 contracts/ErrorReporter.sol create mode 100644 contracts/Exponential.sol create mode 100644 contracts/InterestRateModel.sol create mode 100644 contracts/Maximillion.sol create mode 100644 contracts/PriceOracle.sol create mode 100644 contracts/PriceOracleProxy.sol create mode 100644 contracts/ReentrancyGuard.sol create mode 100644 contracts/SimplePriceOracle.sol create mode 100644 contracts/Unitroller.sol create mode 100644 contracts/WhitePaperInterestRateModel.sol create mode 100644 docs/CompoundProtocol.pdf create mode 100644 docs/CompoundWhitepaper.pdf create mode 100644 migrations/.gitkeep create mode 100644 networks/.gitkeep create mode 100644 networks/README.md create mode 100644 networks/goerli-abi.json create mode 100644 networks/goerli.json create mode 100644 networks/kovan-abi.json create mode 100644 networks/kovan.json create mode 100644 networks/mainnet-abi.json create mode 100644 networks/mainnet.json create mode 100644 networks/rinkeby-abi.json create mode 100644 networks/rinkeby.json create mode 100644 networks/ropsten-abi.json create mode 100644 networks/ropsten.json create mode 100644 package.json create mode 100644 reporterConfig.json create mode 100644 scenario/Grammar.pegjs create mode 100644 scenario/SCENARIO.md create mode 100644 scenario/package.json create mode 100755 scenario/script/generate_parser create mode 100755 scenario/script/repl create mode 100755 scenario/script/tsc create mode 100755 scenario/script/webpack create mode 100644 scenario/src/Accounts.ts create mode 100644 scenario/src/Action.ts create mode 100644 scenario/src/Artifact.ts create mode 100644 scenario/src/Assert.ts create mode 100644 scenario/src/Builder/CTokenBuilder.ts create mode 100644 scenario/src/Builder/ComptrollerImplBuilder.ts create mode 100644 scenario/src/Builder/Erc20Builder.ts create mode 100644 scenario/src/Builder/InterestRateModelBuilder.ts create mode 100644 scenario/src/Builder/MaximillionBuilder.ts create mode 100644 scenario/src/Builder/PriceOracleBuilder.ts create mode 100644 scenario/src/Builder/PriceOracleProxyBuilder.ts create mode 100644 scenario/src/Builder/UnitrollerBuilder.ts create mode 100644 scenario/src/Command.ts create mode 100644 scenario/src/Completer.ts create mode 100644 scenario/src/Contract.ts create mode 100644 scenario/src/Contract/CToken.ts create mode 100644 scenario/src/Contract/Comptroller.ts create mode 100644 scenario/src/Contract/ComptrollerImpl.ts create mode 100644 scenario/src/Contract/Erc20.ts create mode 100644 scenario/src/Contract/InterestRateModel.ts create mode 100644 scenario/src/Contract/Maximillion.ts create mode 100644 scenario/src/Contract/PriceOracle.ts create mode 100644 scenario/src/Contract/PriceOracleProxy.ts create mode 100644 scenario/src/Contract/Unitroller.ts create mode 100644 scenario/src/ContractLookup.ts create mode 100644 scenario/src/CoreEvent.ts create mode 100644 scenario/src/CoreValue.ts create mode 100644 scenario/src/Encoding.ts create mode 100644 scenario/src/ErrorReporter.ts create mode 100644 scenario/src/ErrorReporterConstants.ts create mode 100644 scenario/src/Event.ts create mode 100644 scenario/src/Event/AssertionEvent.ts create mode 100644 scenario/src/Event/CTokenEvent.ts create mode 100644 scenario/src/Event/ComptrollerEvent.ts create mode 100644 scenario/src/Event/ComptrollerImplEvent.ts create mode 100644 scenario/src/Event/Erc20Event.ts create mode 100644 scenario/src/Event/ExpectationEvent.ts create mode 100644 scenario/src/Event/InterestRateModelEvent.ts create mode 100644 scenario/src/Event/InvariantEvent.ts create mode 100644 scenario/src/Event/MaximillionEvent.ts create mode 100644 scenario/src/Event/PriceOracleEvent.ts create mode 100644 scenario/src/Event/PriceOracleProxyEvent.ts create mode 100644 scenario/src/Event/TrxEvent.ts create mode 100644 scenario/src/Event/UnitrollerEvent.ts create mode 100644 scenario/src/Expectation.ts create mode 100644 scenario/src/Expectation/ChangesExpectation.ts create mode 100644 scenario/src/Expectation/RemainsExpectation.ts create mode 100644 scenario/src/File.ts create mode 100644 scenario/src/Formatter.ts create mode 100644 scenario/src/Help.ts create mode 100644 scenario/src/HistoricReadline.ts create mode 100644 scenario/src/Invariant.ts create mode 100644 scenario/src/Invariant/RemainsInvariant.ts create mode 100644 scenario/src/Invariant/StaticInvariant.ts create mode 100644 scenario/src/Invariant/SuccessInvariant.ts create mode 100644 scenario/src/Invokation.ts create mode 100644 scenario/src/Macro.ts create mode 100644 scenario/src/Networks.ts create mode 100644 scenario/src/Parser.ts create mode 100644 scenario/src/Printer.ts create mode 100644 scenario/src/Repl.d.ts create mode 100644 scenario/src/Repl.ts create mode 100644 scenario/src/Runner.ts create mode 100644 scenario/src/Settings.ts create mode 100644 scenario/src/Utils.ts create mode 100644 scenario/src/Value.ts create mode 100644 scenario/src/Value/CTokenValue.ts create mode 100644 scenario/src/Value/ComptrollerImplValue.ts create mode 100644 scenario/src/Value/ComptrollerValue.ts create mode 100644 scenario/src/Value/Erc20Value.ts create mode 100644 scenario/src/Value/InterestRateModelValue.ts create mode 100644 scenario/src/Value/MaximillionValue.ts create mode 100644 scenario/src/Value/PriceOracleProxyValue.ts create mode 100644 scenario/src/Value/PriceOracleValue.ts create mode 100644 scenario/src/Value/UnitrollerValue.ts create mode 100644 scenario/src/Value/UserValue.ts create mode 100644 scenario/src/Verify.ts create mode 100644 scenario/src/Web.ts create mode 100644 scenario/src/World.ts create mode 100644 scenario/tsconfig.json create mode 100644 scenario/webpack.config.js create mode 100644 scenario/yarn.lock create mode 100644 script/README.md create mode 100644 script/certora/Dockerfile create mode 100755 script/console create mode 100755 script/coverage create mode 100755 script/ganache create mode 100755 script/ganache-coverage create mode 100644 script/javascript/buildTruffle.js create mode 100644 script/javascript/networkId.js create mode 100755 script/lint create mode 100755 script/scen/deploy.scen create mode 100755 script/scenario create mode 100755 script/test create mode 100755 script/verify create mode 100644 spec/formal/CompoundIgnoreExtCalls.spclnk create mode 100644 spec/formal/EIP20.spclnk create mode 100644 spec/formal/Liquidate.spclnk create mode 100644 spec/formal/Maximillion.spclnk create mode 100644 spec/formal/MintRedeemBorrowRepay.spclnk create mode 100644 spec/formal/_setMarketPolicyHook.cvl create mode 100644 spec/formal/_setMarketPriceOracle.cvl create mode 100644 spec/formal/accrueInterest.cvl create mode 100644 spec/formal/admin_setCollateralFactor.cvl create mode 100644 spec/formal/borrowAndRepayFresh.cvl create mode 100644 spec/formal/compound.cvl create mode 100644 spec/formal/contracts/CErc20Certora.sol create mode 100644 spec/formal/contracts/CEtherCertora.sol create mode 100644 spec/formal/contracts/CTokenCollateral.sol create mode 100644 spec/formal/contracts/ComptrollerModel.sol create mode 100644 spec/formal/contracts/MaximillionCertora.sol create mode 100644 spec/formal/contracts/SimulationInterface.sol create mode 100644 spec/formal/contracts/UnderlyingModelNonStandard.sol create mode 100644 spec/formal/dummy.cvl create mode 100644 spec/formal/eip20.cvl create mode 100644 spec/formal/frame.cvl create mode 100644 spec/formal/general.cvl create mode 100644 spec/formal/liquidateFresh.cvl create mode 100644 spec/formal/maximillion.cvl create mode 100644 spec/formal/mintAndRedeemFresh.cvl create mode 100644 spec/scenario/Borrow.scen create mode 100644 spec/scenario/Borrow.scen.old create mode 100644 spec/scenario/BorrowBalance.scen create mode 100644 spec/scenario/BorrowEth.scen create mode 100644 spec/scenario/BorrowWBTC.scen create mode 100644 spec/scenario/BreakLiquidate.scen create mode 100644 spec/scenario/CTokenAdmin.scen create mode 100644 spec/scenario/CoreMacros create mode 100644 spec/scenario/EnterExitMarkets.scen create mode 100644 spec/scenario/Excel.scen.old create mode 100644 spec/scenario/ExchangeRate.scen create mode 100644 spec/scenario/HypotheticalAccountLiquidity.scen create mode 100644 spec/scenario/Liquidate.scen create mode 100644 spec/scenario/Liquidate.scen.old create mode 100644 spec/scenario/LiquidateEthBorrow.scen create mode 100644 spec/scenario/LiquidateEthCollateral.scen create mode 100644 spec/scenario/Mint.scen create mode 100644 spec/scenario/MintEth.scen create mode 100644 spec/scenario/MintWBTC.scen create mode 100644 spec/scenario/ReEntry.scen create mode 100644 spec/scenario/Redeem.scen create mode 100644 spec/scenario/RedeemEth.scen create mode 100644 spec/scenario/RedeemUnderlying.scen create mode 100644 spec/scenario/RedeemUnderlyingEth.scen create mode 100644 spec/scenario/RedeemUnderlyingWBTC.scen create mode 100644 spec/scenario/RedeemWBTC.scen create mode 100644 spec/scenario/ReduceReserves.scen create mode 100644 spec/scenario/RepayBorrow.scen create mode 100644 spec/scenario/RepayBorrowEth.scen create mode 100644 spec/scenario/RepayBorrowWBTC.scen create mode 100644 spec/scenario/Seize.scen create mode 100644 spec/scenario/SetComptroller.scen create mode 100644 spec/scenario/Supply.scen.old create mode 100644 spec/scenario/TokenTransfer.scen create mode 100644 spec/scenario/Unitroller.scen create mode 100644 spec/scenario/Withdraw.scen.old create mode 100644 spec/scenario/admin/setMarketPolicyHook.scen.old create mode 100644 spec/scenario/admin/setMarketPriceOracle.scen.old create mode 100644 test/CarefulMathTest.sol create mode 100644 test/Comptroller/accountLiquidityTest.js create mode 100644 test/Comptroller/adminTest.js create mode 100644 test/Comptroller/assetsListTest.js create mode 100644 test/Comptroller/comptrollerTest.js create mode 100644 test/Comptroller/liquidateCalculateAmountSeizeTest.js create mode 100644 test/Comptroller/proxiedComptrollerV1Test.js create mode 100644 test/Comptroller/unitrollerTest.js create mode 100644 test/Errors.js create mode 100644 test/ExponentialTest.sol create mode 100644 test/MaximillionTest.js create mode 100644 test/Models/interestRateModelTest.js create mode 100644 test/PriceOracleProxyTest.js create mode 100644 test/ScenarioTest.js create mode 100644 test/SpinaramaTest.js create mode 100644 test/Tokens/accrueInterestTest.js create mode 100644 test/Tokens/adminTest.js create mode 100644 test/Tokens/borrowAndRepayCEtherTest.js create mode 100644 test/Tokens/borrowAndRepayTest.js create mode 100644 test/Tokens/cTokenTest.js create mode 100644 test/Tokens/liquidateTest.js create mode 100644 test/Tokens/mintAndRedeemCEtherTest.js create mode 100644 test/Tokens/mintAndRedeemTest.js create mode 100644 test/Tokens/reservesTest.js create mode 100644 test/Tokens/safeTokenTest.js create mode 100644 test/Tokens/setComptrollerTest.js create mode 100644 test/Tokens/setInterestRateModelTest.js create mode 100644 test/Tokens/transferTest.js create mode 100644 test/Utils/Compound.js create mode 100644 test/Utils/JS.js create mode 100644 test/Utils/MochaTruffle.js create mode 100644 test/contracts/BasicToken.sol create mode 100644 test/contracts/BasicTokenNS.sol create mode 100644 test/contracts/BoolComptroller.sol create mode 100644 test/contracts/CErc20Harness.sol create mode 100644 test/contracts/CErc20Scenario.sol create mode 100644 test/contracts/CEtherHarness.sol create mode 100644 test/contracts/CEtherScenario.sol create mode 100644 test/contracts/CEvil.sol create mode 100644 test/contracts/ComptrollerBorked.sol create mode 100644 test/contracts/ComptrollerHarness.sol create mode 100644 test/contracts/ComptrollerScenario.sol create mode 100644 test/contracts/DSValueHarness.sol create mode 100644 test/contracts/EIP20Harness.sol create mode 100644 test/contracts/EIP20NonCompliantHarness.sol create mode 100644 test/contracts/EIP20NonStandardReturnHarness.sol create mode 100644 test/contracts/EIP20NonStandardThrowHarness.sol create mode 100644 test/contracts/ERC20.sol create mode 100644 test/contracts/ERC20Basic.sol create mode 100644 test/contracts/ERC20BasicNS.sol create mode 100644 test/contracts/ERC20NS.sol create mode 100644 test/contracts/ERC20NonView.sol create mode 100644 test/contracts/EchoTypesComptroller.sol create mode 100644 test/contracts/EvilToken.sol create mode 100644 test/contracts/FalseMarkerMethodComptroller.sol create mode 100644 test/contracts/FalseMarkerMethodInterestRateModel.sol create mode 100644 test/contracts/FaucetNonStandardToken.sol create mode 100644 test/contracts/FaucetToken.sol create mode 100644 test/contracts/FaucetTokenReEntrantHarness.sol create mode 100644 test/contracts/FixedPriceOracle.sol create mode 100644 test/contracts/InterestRateModelHarness.sol create mode 100644 test/contracts/MathHelpers.sol create mode 100644 test/contracts/NonStandardToken.sol create mode 100644 test/contracts/NotPriceOracle.sol create mode 100644 test/contracts/SafeMath.sol create mode 100644 test/contracts/StandardToken.sol create mode 100644 test/contracts/WBTC.sol create mode 100644 truffle.js create mode 100644 yarn.lock diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..3c75a1184 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,173 @@ +version: 2.1 + +orbs: + codecov: codecov/codecov@1.0.3 + +jobs: + test: + docker: + - image: circleci/node:11 + working_directory: ~/repo + steps: + - run: + | + sudo wget https://github.com/ethereum/solidity/releases/download/v0.5.8/solc-static-linux -O /usr/local/bin/solc + sudo chmod +x /usr/local/bin/solc + - checkout + - restore_cache: + keys: + - v2-dependencies-{{ checksum "package.json" }} + - v2-dependencies- + - restore_cache: + keys: + - v2-scenario/dependencies-{{ checksum "scenario/package.json" }} + - v2-scenario/dependencies- + - run: yarn install + - run: cd scenario && yarn install + - run: + name: Ganache + command: script/ganache + background: true + - run: | + while ! nc -z localhost 8545; do + sleep 0.1 # wait for ganache to start + done + - save_cache: + paths: + - node_modules + key: v2-dependencies-{{ checksum "package.json" }} + - save_cache: + paths: + - scenario/node_modules + key: v2-scenario-dependencies-{{ checksum "scenario/package.json" }} + - attach_workspace: + at: ~/repo + - run: mkdir ~/junit + - run: TSC_ARGS="" MOCHA_FILE=~/junit/test-results.xml script/test + - store_test_results: + path: ~/junit + - store_artifacts: + path: ~/junit + parallelism: 4 + + mocha_coverage: + parallelism: 5 + docker: + - image: circleci/node:11 + working_directory: ~/repo + steps: + - checkout + - restore_cache: + keys: + - v2-dependencies-{{ checksum "package.json" }} + - v2-dependencies- + - restore_cache: + keys: + - v2-scenario/dependencies-{{ checksum "scenario/package.json" }} + - v2-scenario/dependencies- + - run: yarn install + - run: cd scenario && yarn install + - run: + name: Ganache + command: script/ganache-coverage + background: true + - save_cache: + paths: + - node_modules + key: v2-dependencies-{{ checksum "package.json" }} + - save_cache: + paths: + - scenario/node_modules + key: v2-scenario-dependencies-{{ checksum "scenario/package.json" }} + - attach_workspace: + at: ~/repo + - run: + command: yarn run coverage mocha + no_output_timeout: 20m + - store_artifacts: + path: ~/repo/coverage.json + destination: coverage.json + - store_artifacts: + path: ~/repo/coverage + destination: coverage + - codecov/upload + + scenario_coverage: + docker: + - image: circleci/node:11 + working_directory: ~/repo + steps: + - run: + | + sudo wget https://github.com/ethereum/solidity/releases/download/v0.5.8/solc-static-linux -O /usr/local/bin/solc + sudo chmod +x /usr/local/bin/solc + - checkout + - restore_cache: + keys: + - v2-dependencies-{{ checksum "package.json" }} + - v2-dependencies- + - restore_cache: + keys: + - v2-scenario/dependencies-{{ checksum "scenario/package.json" }} + - v2-scenario/dependencies- + - run: yarn install + - run: cd scenario && yarn install + - run: + name: Ganache + command: script/ganache-coverage + background: true + - save_cache: + paths: + - node_modules + key: v2-dependencies-{{ checksum "package.json" }} + - save_cache: + paths: + - scenario/node_modules + key: v2-scenario-dependencies-{{ checksum "scenario/package.json" }} + - attach_workspace: + at: ~/repo + - run: + command: yarn run coverage scenario + no_output_timeout: 20m + - store_artifacts: + path: ~/repo/coverage.json + destination: coverage.json + - store_artifacts: + path: ~/repo/coverage + destination: coverage + - codecov/upload + + lint: + docker: + - image: circleci/node:11 + - image: trufflesuite/ganache-cli:v6.2.5 + working_directory: ~/repo + steps: + - checkout + - restore_cache: + keys: + - v2-dependencies-{{ checksum "package.json" }} + - v2-dependencies- + - run: yarn install + - save_cache: + paths: + - node_modules + key: v2-dependencies-{{ checksum "package.json" }} + - attach_workspace: + at: ~/repo + - run: yarn run lint + +workflows: + version: 2 + build-test-and-deploy: + jobs: + - test + - mocha_coverage: + filters: + branches: + only: /^(master|(.*-cov(er(age)?)?))$/ + - scenario_coverage: + filters: + branches: + only: /^(master|(.*-cov(er(age)?)?))$/ + - lint diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..aff89f66e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +scenario/node_modules +test +!test/contracts +*.DS_Store \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..8f47fc2bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +allFiredEvents +.build-temp +build +build_ +node_modules +.env +coverage/ +coverage.json +coverageEnv/ +formulas/ +networks/test.json +networks/test-abi.json +networks/coverage.json +networks/coverage-abi.json +networks/development.json +networks/development-abi.json +networks/*-contracts.json +networks/*-history +networks/*-settings.json +outputs/ +Reports/ +scTopics +*.DS_Store +test-results.xml +.tsbuilt +yarn-error.log +scenario/build/webpack.js \ No newline at end of file diff --git a/.solcover.js b/.solcover.js new file mode 100644 index 000000000..20908fd23 --- /dev/null +++ b/.solcover.js @@ -0,0 +1,8 @@ +module.exports = { + port: 8555, + norpc: true, + testCommand: process.env['TEST_COMMAND'] || 'NETWORK=coverage script/test', + skipFiles: ['FormalMoneyMarket.sol', 'test_contracts'].concat( + process.env['SKIP_UNITROLLER'] ? ['Unitroller.sol'] : []), + deepSkip: true +}; diff --git a/.soliumignore b/.soliumignore new file mode 100644 index 000000000..8ca588c52 --- /dev/null +++ b/.soliumignore @@ -0,0 +1,2 @@ +node_modules +test/contracts/WBTC.sol diff --git a/.soliumrc.json b/.soliumrc.json new file mode 100644 index 000000000..bbc39e058 --- /dev/null +++ b/.soliumrc.json @@ -0,0 +1,16 @@ +{ + "extends": "solium:recommended", + "plugins": [ + "security" + ], + "rules": { + "quotes": [ + "error", + "double" + ], + "indentation": [ + "error", + 4 + ] + } +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..092304f6a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM mhart/alpine-node:11.10.1 + +RUN apk update && apk add --no-cache --virtual build-dependencies git python g++ make +RUN yarn global add truffle@5.0.30 +RUN yarn global add ganache-cli@6.5.1 +RUN yarn global add typescript + +RUN wget https://github.com/ethereum/solidity/releases/download/v0.5.8/solc-static-linux -O /usr/local/bin/solc && \ + chmod +x /usr/local/bin/solc + +RUN mkdir -p /deploy/compound-protocol/scenario +WORKDIR /deploy/compound-protocol + +# First add deps +ADD ./package.json /deploy/compound-protocol/ +ADD ./yarn.lock /deploy/compound-protocol/ +RUN yarn install +ADD scenario/package.json /deploy/compound-protocol/scenario +ADD scenario/yarn.lock /deploy/compound-protocol/scenario +RUN ls -la /deploy/compound-protocol +RUN ls -la /deploy/compound-protocol/scenario +RUN cd /deploy/compound-protocol/scenario && yarn install + +# Then rest of code and build +ADD . /deploy/compound-protocol + +RUN truffle compile + +RUN apk del build-dependencies +RUN yarn cache clean + +CMD while :; do sleep 2073600; done diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..50db18e9d --- /dev/null +++ b/LICENSE @@ -0,0 +1,5 @@ +The software and documentation available in this repository (the "Software") is protected by copyright law and accessible pursuant to the license set forth below. Copyright © 2019 Compound Labs, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person or organization obtaining the Software (the “Licensee”) to privately study, review, and analyze the Software. Licensee shall not use the Software for any other purpose. Licensee shall not modify, transfer, assign, share, or sub-license the Software or any derivative works of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..46a3465a9 --- /dev/null +++ b/README.md @@ -0,0 +1,182 @@ +[![CircleCI](https://circleci.com/gh/compound-finance/compound-protocol.svg?style=svg&circle-token=5ed19932325c559a06f71f87d69012aedd2cf3fb)](https://circleci.com/gh/compound-finance/compound-protocol) [![codecov](https://codecov.io/gh/compound-finance/compound-protocol/branch/master/graph/badge.svg?token=q4UvsvVzOX)](https://codecov.io/gh/compound-finance/compound-protocol) + +Compound Protocol +================= + +The Compound Protocol is an Ethereum smart contract for supplying or borrowing assets. Through the cToken contracts, accounts on the blockchain *supply* capital (Ether or ERC-20 tokens) to receive cTokens or *borrow* assets from the protocol (holding other assets as collateral). The Compound cToken contracts track these balances and algorithmically set interest rates for borrowers. + +Before getting started with this repo, please read: + +* The [Compound Whitepaper](https://github.com/compound-finance/compound-protocol/tree/master/docs/CompoundWhitepaper.pdf), describing how Compound works +* The [Compound Protocol Specification](https://github.com/compound-finance/compound-protocol/tree/master/docs/CompoundProtocol.pdf), explaining in plain English how the protocol operates + +For questions about interacting with Compound, please visit [our Discord server](https://compound.finance/discord). + +For security concerns, please visit [https://compound.finance/security](https://compound.finance/security) or email [security@compound.finance](mailto:security@compound.finance). + +Contracts +========= + +We detail a few of the core contracts in the Compound protocol. + +
+
CToken, CErc20 and CEther
+
The Compound cTokens, which are self-contained borrowing and lending contracts. CToken contains the core logic and CErc20 and CEther add public interfaces for Erc20 tokens and ether, respectively. Each CToken is assigned an interest rate and risk model (see InterestRateModel and Comptroller sections), and allows accounts to *mint* (supply capital), *redeem* (withdraw capital), *borrow* and *repay a borrow*. Each CToken is an ERC-20 compliant token where balances represent ownership of the market.
+
+ +
+
Comptroller
+
The risk model contract, which validates permissible user actions and disallows actions if they do not fit certain risk parameters. For instance, the Comptroller enforces that each borrowing user must maintain a sufficient collateral balance across all cTokens.
+
+ +
+
InterestRateModel
+
Contracts which define interest rate models. These models algorithmically determine interest rates based on the current utilization of a given market (that is, how much of the supplied assets are liquid versus borrowed).
+
+ +
+
Careful Math
+
Library for safe math operations.
+
+ +
+
ErrorReporter
+
Library for tracking error codes and failure conditions.
+
+ +
+
Exponential
+
Library for handling fixed-point decimal numbers.
+
+ +
+
SafeToken
+
Library for safely handling Erc20 interaction.
+
+ +
+
WhitePaperInterestRateModel
+
Initial interest rate model, as defined in the Whitepaper. This contract accepts a base rate and slope parameter in its constructor.
+
+ +Installation +------------ +To run compound, pull the repository from GitHub and install its dependencies. You will need [yarn](https://yarnpkg.com/lang/en/docs/install/) or [npm](https://docs.npmjs.com/cli/install) installed. + + git clone https://github.com/compound-finance/compound-protocol + cd compound-protocol + yarn # or `npm install` + +You can then compile and deploy the contracts with: + + yarn run deploy + +Note: this project does not use truffle migrations. The command above is the best way to deploy contracts. To view the addresses of contracts, please inspect the `networks/development.json` file that is produced as an artifact of that command. + +Console +------- + +After you deploy, as above, you can run a truffle console with the following command: + + yarn run console + +This command will create a truffle-like build directory and start a truffle console, thus you can then run: + + truffle(rinkeby)> cDAI.deployed().then((cdai) => cdai.borrowRatePerBlock.call()) + + +You can also specify a network (rinkeby, ropsten, kovan, goerli or mainnet): + + yarn run console rinkeby + +REPL +---- + +The Compound Protocol has a simple scenario evaluation tool to test and evaluate scenarios which could occur on the blockchain. This is primarily used for constructing high-level integration tests. The tool also has a REPL to interact with local the Compound Protocol (similar to `truffle console`). + + yarn run repl + + > Read CToken cBAT Address + Command: Read CToken cBAT Address + AddressV + +You can read more about the scenario runner in the [Scenario Docs](https://github.com/compound-finance/compound-protocol/tree/master/scenario/SCENARIO.md) on steps for using the repl. + +Deployment +---------- + +The easiest way to deploy some Erc20 tokens, cTokens and a Comptroller is through scenario scripts. + + # run ganache locally + script/ganache # or `ganache-cli` + + # ensure development files don't exist as + # new ganache instances invalidate old deployed contracts + rm networks/development* + + # run deployment script + yarn run deploy -v + +After that, you'll have a full set of contracts deployed locally. Look in `networks/development.json` for the addresses for those deployed contracts. You can use the `yarn run console` command above to interact with the contracts (or the scenario REPL, if you prefer). + +Testing +------- +Mocha contract tests are defined under the [test directory](https://github.com/compound-finance/compound-protocol/tree/master/test). To run the tests run: + + yarn run test + +or with inspection (visit chrome://inspect) and look for a remote target after running: + + node --inspect node_modules/truffle-core/cli.js test + +Assertions used in our tests are provided by [ChaiJS](http://chaijs.com). + +Integration Specs +----------------- + +There are additional tests under the [spec/scenario](https://github.com/compound-finance/compound-protocol/tree/master/spec/scenario) folder. These are high-level integration tests based on the scenario runner depicted above. The aim of these tests is to be highly literate and have high coverage in the interaction of contracts. + +Formal Verification Specs +------------------------- + +The Compound Protocol has a number of formal verification specifications, powered by [Certora](https://www.certora.com/). You can find details in the [spec/formal](https://github.com/compound-finance/compound-protocol/tree/master/spec/formal) folder. The Certora Verification Language (CVL) files included are specifications, which when with the Certora CLI tool, produce formal proofs (or counter-examples) that the code of a given contract exactly matches that specification. + +Code Coverage +------------- +To run code coverage, run: + + scripts/ganache-coverage # run ganache in coverage mode + yarn run coverage + +Linting +------- +To lint the code, run: + + yarn run lint + +Docker +------ + +To run in docker: + + # Build the docker image + docker build -t compound-protocol . + + # Run a shell to the built image + docker run -it compound-protocol /bin/sh + +From within a docker shell, you can interact locally with the protocol via ganache and truffle: + + > ganache-cli & + > yarn run deploy + > yarn run console + truffle(development)> cDAI.deployed().then((contract) => cdai = contract); + truffle(development)> cdai.borrowRatePerBlock.call().then((rate) => rate.toNumber()) + 20 + +Discussion +---------- + +For any concerns with the protocol, visit us on [Discord](https://compound.finance/discord) to discuss. + +_© Copyright 2019, Compound Labs, Inc._ diff --git a/contracts/CErc20.sol b/contracts/CErc20.sol new file mode 100644 index 000000000..b86ce526c --- /dev/null +++ b/contracts/CErc20.sol @@ -0,0 +1,215 @@ +pragma solidity ^0.5.8; + +import "./CToken.sol"; + +/** + * @title Compound's CErc20 Contract + * @notice CTokens which wrap an EIP-20 underlying + * @author Compound + */ +contract CErc20 is CToken { + + /** + * @notice Underlying asset for this CToken + */ + address public underlying; + + /** + * @notice Construct a new money market + * @param underlying_ The address of the underlying asset + * @param comptroller_ The address of the Comptroller + * @param interestRateModel_ The address of the interest rate model + * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 + * @param name_ ERC-20 name of this token + * @param symbol_ ERC-20 symbol of this token + * @param decimals_ ERC-20 decimal precision of this token + */ + constructor(address underlying_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa_, + string memory name_, + string memory symbol_, + uint decimals_) public + CToken(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_) { + // Set underlying + underlying = underlying_; + EIP20Interface(underlying).totalSupply(); // Sanity check the underlying + } + + /*** User Interface ***/ + + /** + * @notice Sender supplies assets into the market and receives cTokens in exchange + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param mintAmount The amount of the underlying asset to supply + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function mint(uint mintAmount) external returns (uint) { + return mintInternal(mintAmount); + } + + /** + * @notice Sender redeems cTokens in exchange for the underlying asset + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param redeemTokens The number of cTokens to redeem into underlying + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeem(uint redeemTokens) external returns (uint) { + return redeemInternal(redeemTokens); + } + + /** + * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param redeemAmount The amount of underlying to redeem + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeemUnderlying(uint redeemAmount) external returns (uint) { + return redeemUnderlyingInternal(redeemAmount); + } + + /** + * @notice Sender borrows assets from the protocol to their own address + * @param borrowAmount The amount of the underlying asset to borrow + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function borrow(uint borrowAmount) external returns (uint) { + return borrowInternal(borrowAmount); + } + + /** + * @notice Sender repays their own borrow + * @param repayAmount The amount to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function repayBorrow(uint repayAmount) external returns (uint) { + return repayBorrowInternal(repayAmount); + } + + /** + * @notice Sender repays a borrow belonging to borrower + * @param borrower the account with the debt being payed off + * @param repayAmount The amount to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) { + return repayBorrowBehalfInternal(borrower, repayAmount); + } + + /** + * @notice The sender liquidates the borrowers collateral. + * The collateral seized is transferred to the liquidator. + * @param borrower The borrower of this cToken to be liquidated + * @param cTokenCollateral The market in which to seize collateral from the borrower + * @param repayAmount The amount of the underlying borrowed asset to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function liquidateBorrow(address borrower, uint repayAmount, CToken cTokenCollateral) external returns (uint) { + return liquidateBorrowInternal(borrower, repayAmount, cTokenCollateral); + } + + /*** Safe Token ***/ + + /** + * @notice Gets balance of this contract in terms of the underlying + * @dev This excludes the value of the current message, if any + * @return The quantity of underlying tokens owned by this contract + */ + function getCashPrior() internal view returns (uint) { + EIP20Interface token = EIP20Interface(underlying); + return token.balanceOf(address(this)); + } + + /** + * @dev Checks whether or not there is sufficient allowance for this contract to move amount from `from` and + * whether or not `from` has a balance of at least `amount`. Does NOT do a transfer. + */ + function checkTransferIn(address from, uint amount) internal view returns (Error) { + EIP20Interface token = EIP20Interface(underlying); + + if (token.allowance(from, address(this)) < amount) { + return Error.TOKEN_INSUFFICIENT_ALLOWANCE; + } + + if (token.balanceOf(from) < amount) { + return Error.TOKEN_INSUFFICIENT_BALANCE; + } + + return Error.NO_ERROR; + } + + /** + * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and returns an explanatory + * error code rather than reverting. If caller has not called `checkTransferIn`, this may revert due to + * insufficient balance or insufficient allowance. If caller has called `checkTransferIn` prior to this call, + * and it returned Error.NO_ERROR, this should not revert in normal conditions. + * + * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. + * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ + function doTransferIn(address from, uint amount) internal returns (Error) { + EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying); + bool result; + + token.transferFrom(from, address(this), amount); + + // solium-disable-next-line security/no-inline-assembly + assembly { + switch returndatasize() + case 0 { // This is a non-standard ERC-20 + result := not(0) // set result to true + } + case 32 { // This is a complaint ERC-20 + returndatacopy(0, 0, 32) + result := mload(0) // Set `result = returndata` of external call + } + default { // This is an excessively non-compliant ERC-20, revert. + revert(0, 0) + } + } + + if (!result) { + return Error.TOKEN_TRANSFER_IN_FAILED; + } + + return Error.NO_ERROR; + } + + /** + * @dev Similar to EIP20 transfer, except it handles a False result from `transfer` and returns an explanatory + * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to + * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified + * it is >= amount, this should not revert in normal conditions. + * + * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value. + * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ + function doTransferOut(address payable to, uint amount) internal returns (Error) { + EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying); + bool result; + + token.transfer(to, amount); + + // solium-disable-next-line security/no-inline-assembly + assembly { + switch returndatasize() + case 0 { // This is a non-standard ERC-20 + result := not(0) // set result to true + } + case 32 { // This is a complaint ERC-20 + returndatacopy(0, 0, 32) + result := mload(0) // Set `result = returndata` of external call + } + default { // This is an excessively non-compliant ERC-20, revert. + revert(0, 0) + } + } + + if (!result) { + return Error.TOKEN_TRANSFER_OUT_FAILED; + } + + return Error.NO_ERROR; + } +} diff --git a/contracts/CEther.sol b/contracts/CEther.sol new file mode 100644 index 000000000..6f5cd09c3 --- /dev/null +++ b/contracts/CEther.sol @@ -0,0 +1,168 @@ +pragma solidity ^0.5.8; + +import "./CToken.sol"; + +/** + * @title Compound's CEther Contract + * @notice CToken which wraps Ether + * @author Compound + */ +contract CEther is CToken { + /** + * @notice Construct a new CEther money market + * @param comptroller_ The address of the Comptroller + * @param interestRateModel_ The address of the interest rate model + * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 + * @param name_ ERC-20 name of this token + * @param symbol_ ERC-20 symbol of this token + * @param decimals_ ERC-20 decimal precision of this token + */ + constructor(ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa_, + string memory name_, + string memory symbol_, + uint decimals_) public + CToken(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_) {} + + /*** User Interface ***/ + + /** + * @notice Sender supplies assets into the market and receives cTokens in exchange + * @dev Reverts upon any failure + */ + function mint() external payable { + requireNoError(mintInternal(msg.value), "mint failed"); + } + + /** + * @notice Sender redeems cTokens in exchange for the underlying asset + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param redeemTokens The number of cTokens to redeem into underlying + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeem(uint redeemTokens) external returns (uint) { + return redeemInternal(redeemTokens); + } + + /** + * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param redeemAmount The amount of underlying to redeem + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeemUnderlying(uint redeemAmount) external returns (uint) { + return redeemUnderlyingInternal(redeemAmount); + } + + /** + * @notice Sender borrows assets from the protocol to their own address + * @param borrowAmount The amount of the underlying asset to borrow + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function borrow(uint borrowAmount) external returns (uint) { + return borrowInternal(borrowAmount); + } + + /** + * @notice Sender repays their own borrow + * @dev Reverts upon any failure + */ + function repayBorrow() external payable { + requireNoError(repayBorrowInternal(msg.value), "repayBorrow failed"); + } + + /** + * @notice Sender repays a borrow belonging to borrower + * @dev Reverts upon any failure + * @param borrower the account with the debt being payed off + */ + function repayBorrowBehalf(address borrower) external payable { + requireNoError(repayBorrowBehalfInternal(borrower, msg.value), "repayBorrowBehalf failed"); + } + + /** + * @notice The sender liquidates the borrowers collateral. + * The collateral seized is transferred to the liquidator. + * @dev Reverts upon any failure + * @param borrower The borrower of this cToken to be liquidated + * @param cTokenCollateral The market in which to seize collateral from the borrower + */ + function liquidateBorrow(address borrower, CToken cTokenCollateral) external payable { + requireNoError(liquidateBorrowInternal(borrower, msg.value, cTokenCollateral), "liquidateBorrow failed"); + } + + /** + * @notice Send Ether to CEther to mint + */ + function () external payable { + requireNoError(mintInternal(msg.value), "mint failed"); + } + + /*** Safe Token ***/ + + /** + * @notice Gets balance of this contract in terms of Ether, before this message + * @dev This excludes the value of the current message, if any + * @return The quantity of Ether owned by this contract + */ + function getCashPrior() internal view returns (uint) { + (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value); + require(err == MathError.NO_ERROR); + return startingBalance; + } + + /** + * @notice Checks whether the requested transfer matches the `msg` + * @dev Does NOT do a transfer + * @param from Address sending the Ether + * @param amount Amount of Ether being sent + * @return Whether or not the transfer checks out + */ + function checkTransferIn(address from, uint amount) internal view returns (Error) { + // Sanity checks + require(msg.sender == from, "sender mismatch"); + require(msg.value == amount, "value mismatch"); + return Error.NO_ERROR; + } + + /** + * @notice Perform the actual transfer in, which is a no-op + * @param from Address sending the Ether + * @param amount Amount of Ether being sent + * @return Success + */ + function doTransferIn(address from, uint amount) internal returns (Error) { + // Sanity checks + require(msg.sender == from, "sender mismatch"); + require(msg.value == amount, "value mismatch"); + return Error.NO_ERROR; + } + + function doTransferOut(address payable to, uint amount) internal returns (Error) { + /* Send the Ether, with minimal gas and revert on failure */ + to.transfer(amount); + return Error.NO_ERROR; + } + + function requireNoError(uint errCode, string memory message) internal pure { + if (errCode == uint(Error.NO_ERROR)) { + return; + } + + bytes memory fullMessage = new bytes(bytes(message).length + 5); + uint i; + + for (i = 0; i < bytes(message).length; i++) { + fullMessage[i] = bytes(message)[i]; + } + + fullMessage[i+0] = byte(uint8(32)); + fullMessage[i+1] = byte(uint8(40)); + fullMessage[i+2] = byte(uint8(48 + ( errCode / 10 ))); + fullMessage[i+3] = byte(uint8(48 + ( errCode % 10 ))); + fullMessage[i+4] = byte(uint8(41)); + + require(errCode == uint(Error.NO_ERROR), string(fullMessage)); + } +} diff --git a/contracts/CToken.sol b/contracts/CToken.sol new file mode 100644 index 000000000..df653280f --- /dev/null +++ b/contracts/CToken.sol @@ -0,0 +1,1572 @@ +pragma solidity ^0.5.8; + +import "./ComptrollerInterface.sol"; +import "./ErrorReporter.sol"; +import "./Exponential.sol"; +import "./EIP20Interface.sol"; +import "./EIP20NonStandardInterface.sol"; +import "./ReentrancyGuard.sol"; +import "./InterestRateModel.sol"; + +/** + * @title Compound's CToken Contract + * @notice Abstract base for CTokens + * @author Compound + */ +contract CToken is EIP20Interface, Exponential, TokenErrorReporter, ReentrancyGuard { + /** + * @notice Indicator that this is a CToken contract (for inspection) + */ + bool public constant isCToken = true; + + /** + * @notice EIP-20 token name for this token + */ + string public name; + + /** + * @notice EIP-20 token symbol for this token + */ + string public symbol; + + /** + * @notice EIP-20 token decimals for this token + */ + uint public decimals; + + /** + * @notice Maximum borrow rate that can ever be applied (.0005% / block) + */ + uint constant borrowRateMaxMantissa = 5e14; + + /** + * @notice Maximum fraction of interest that can be set aside for reserves + */ + uint constant reserveFactorMaxMantissa = 1e18; + + /** + * @notice Administrator for this contract + */ + address payable public admin; + + /** + * @notice Pending administrator for this contract + */ + address payable public pendingAdmin; + + /** + * @notice Contract which oversees inter-cToken operations + */ + ComptrollerInterface public comptroller; + + /** + * @notice Model which tells what the current interest rate should be + */ + InterestRateModel public interestRateModel; + + /** + * @notice Initial exchange rate used when minting the first CTokens (used when totalSupply = 0) + */ + uint public initialExchangeRateMantissa; + + /** + * @notice Fraction of interest currently set aside for reserves + */ + uint public reserveFactorMantissa; + + /** + * @notice Block number that interest was last accrued at + */ + uint public accrualBlockNumber; + + /** + * @notice Accumulator of total earned interest since the opening of the market + */ + uint public borrowIndex; + + /** + * @notice Total amount of outstanding borrows of the underlying in this market + */ + uint public totalBorrows; + + /** + * @notice Total amount of reserves of the underlying held in this market + */ + uint public totalReserves; + + /** + * @notice Total number of tokens in circulation + */ + uint256 public totalSupply; + + /** + * @notice Official record of token balances for each account + */ + mapping (address => uint256) accountTokens; + + /** + * @notice Approved token transfer amounts on behalf of others + */ + mapping (address => mapping (address => uint256)) transferAllowances; + + /** + * @notice Container for borrow balance information + * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action + * @member interestIndex Global borrowIndex as of the most recent balance-changing action + */ + struct BorrowSnapshot { + uint principal; + uint interestIndex; + } + + /** + * @notice Mapping of account addresses to outstanding borrow balances + */ + mapping(address => BorrowSnapshot) accountBorrows; + + + /*** Market Events ***/ + + /** + * @notice Event emitted when interest is accrued + */ + event AccrueInterest(uint interestAccumulated, uint borrowIndex, uint totalBorrows); + + /** + * @notice Event emitted when tokens are minted + */ + event Mint(address minter, uint mintAmount, uint mintTokens); + + /** + * @notice Event emitted when tokens are redeemed + */ + event Redeem(address redeemer, uint redeemAmount, uint redeemTokens); + + /** + * @notice Event emitted when underlying is borrowed + */ + event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows); + + /** + * @notice Event emitted when a borrow is repaid + */ + event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows); + + /** + * @notice Event emitted when a borrow is liquidated + */ + event LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens); + + + /*** Admin Events ***/ + + /** + * @notice Event emitted when pendingAdmin is changed + */ + event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); + + /** + * @notice Event emitted when pendingAdmin is accepted, which means admin is updated + */ + event NewAdmin(address oldAdmin, address newAdmin); + + /** + * @notice Event emitted when comptroller is changed + */ + event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller); + + /** + * @notice Event emitted when interestRateModel is changed + */ + event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel); + + /** + * @notice Event emitted when the reserve factor is changed + */ + event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa); + + /** + * @notice Event emitted when the reserves are reduced + */ + event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves); + + + /** + * @notice Construct a new money market + * @param comptroller_ The address of the Comptroller + * @param interestRateModel_ The address of the interest rate model + * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18 + * @param name_ EIP-20 name of this token + * @param symbol_ EIP-20 symbol of this token + * @param decimals_ EIP-20 decimal precision of this token + */ + constructor(ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa_, + string memory name_, + string memory symbol_, + uint decimals_) internal { + // Set admin to msg.sender + admin = msg.sender; + + // Set initial exchange rate + initialExchangeRateMantissa = initialExchangeRateMantissa_; + require(initialExchangeRateMantissa > 0, "Initial exchange rate must be greater than zero."); + + // Set the comptroller + uint err = _setComptroller(comptroller_); + require(err == uint(Error.NO_ERROR), "Setting comptroller failed"); + + // Initialize block number and borrow index (block number mocks depend on comptroller being set) + accrualBlockNumber = getBlockNumber(); + borrowIndex = mantissaOne; + + // Set the interest rate model (depends on block number / borrow index) + err = _setInterestRateModelFresh(interestRateModel_); + require(err == uint(Error.NO_ERROR), "Setting interest rate model failed"); + + name = name_; + symbol = symbol_; + decimals = decimals_; + } + + /** + * @notice Transfer `tokens` tokens from `src` to `dst` by `spender` + * @dev Called by both `transfer` and `transferFrom` internally + * @param spender The address of the account performing the transfer + * @param src The address of the source account + * @param dst The address of the destination account + * @param tokens The number of tokens to transfer + * @return Whether or not the transfer succeeded + */ + function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) { + /* Fail if transfer not allowed */ + uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed); + } + + /* Do not allow self-transfers */ + if (src == dst) { + return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED); + } + + /* Get the allowance, infinite for the account owner */ + uint startingAllowance = 0; + if (spender == src) { + startingAllowance = uint(-1); + } else { + startingAllowance = transferAllowances[src][spender]; + } + + /* Do the calculations, checking for {under,over}flow */ + MathError mathErr; + uint allowanceNew; + uint srcTokensNew; + uint dstTokensNew; + + (mathErr, allowanceNew) = subUInt(startingAllowance, tokens); + if (mathErr != MathError.NO_ERROR) { + return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED); + } + + (mathErr, srcTokensNew) = subUInt(accountTokens[src], tokens); + if (mathErr != MathError.NO_ERROR) { + return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH); + } + + (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens); + if (mathErr != MathError.NO_ERROR) { + return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + accountTokens[src] = srcTokensNew; + accountTokens[dst] = dstTokensNew; + + /* Eat some of the allowance (if necessary) */ + if (startingAllowance != uint(-1)) { + transferAllowances[src][spender] = allowanceNew; + } + + /* We emit a Transfer event */ + emit Transfer(src, dst, tokens); + + /* We call the defense hook (which checks for under-collateralization) */ + comptroller.transferVerify(address(this), src, dst, tokens); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Transfer `amount` tokens from `msg.sender` to `dst` + * @param dst The address of the destination account + * @param amount The number of tokens to transfer + * @return Whether or not the transfer succeeded + */ + function transfer(address dst, uint256 amount) external nonReentrant returns (bool) { + return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR); + } + + /** + * @notice Transfer `amount` tokens from `src` to `dst` + * @param src The address of the source account + * @param dst The address of the destination account + * @param amount The number of tokens to transfer + * @return Whether or not the transfer succeeded + */ + function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) { + return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR); + } + + /** + * @notice Approve `spender` to transfer up to `amount` from `src` + * @dev This will overwrite the approval amount for `spender` + * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) + * @param spender The address of the account which may transfer tokens + * @param amount The number of tokens that are approved (-1 means infinite) + * @return Whether or not the approval succeeded + */ + function approve(address spender, uint256 amount) external returns (bool) { + address src = msg.sender; + transferAllowances[src][spender] = amount; + emit Approval(src, spender, amount); + return true; + } + + /** + * @notice Get the current allowance from `owner` for `spender` + * @param owner The address of the account which owns the tokens to be spent + * @param spender The address of the account which may transfer tokens + * @return The number of tokens allowed to be spent (-1 means infinite) + */ + function allowance(address owner, address spender) external view returns (uint256) { + return transferAllowances[owner][spender]; + } + + /** + * @notice Get the token balance of the `owner` + * @param owner The address of the account to query + * @return The number of tokens owned by `owner` + */ + function balanceOf(address owner) external view returns (uint256) { + return accountTokens[owner]; + } + + /** + * @notice Get the underlying balance of the `owner` + * @dev This also accrues interest in a transaction + * @param owner The address of the account to query + * @return The amount of underlying owned by `owner` + */ + function balanceOfUnderlying(address owner) external returns (uint) { + Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()}); + (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]); + require(mErr == MathError.NO_ERROR); + return balance; + } + + /** + * @notice Get a snapshot of the account's balances, and the cached exchange rate + * @dev This is used by comptroller to more efficiently perform liquidity checks. + * @param account Address of the account to snapshot + * @return (possible error, token balance, borrow balance, exchange rate mantissa) + */ + function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) { + uint cTokenBalance = accountTokens[account]; + uint borrowBalance; + uint exchangeRateMantissa; + + MathError mErr; + + (mErr, borrowBalance) = borrowBalanceStoredInternal(account); + if (mErr != MathError.NO_ERROR) { + return (uint(Error.MATH_ERROR), 0, 0, 0); + } + + (mErr, exchangeRateMantissa) = exchangeRateStoredInternal(); + if (mErr != MathError.NO_ERROR) { + return (uint(Error.MATH_ERROR), 0, 0, 0); + } + + return (uint(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa); + } + + /** + * @dev Function to simply retrieve block number + * This exists mainly for inheriting test contracts to stub this result. + */ + function getBlockNumber() internal view returns (uint) { + return block.number; + } + + /** + * @notice Returns the current per-block borrow interest rate for this cToken + * @return The borrow interest rate per block, scaled by 1e18 + */ + function borrowRatePerBlock() external view returns (uint) { + (uint opaqueErr, uint borrowRateMantissa) = interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); + require(opaqueErr == 0, "borrowRatePerBlock: interestRateModel.borrowRate failed"); // semi-opaque + return borrowRateMantissa; + } + + /** + * @notice Returns the current per-block supply interest rate for this cToken + * @return The supply interest rate per block, scaled by 1e18 + */ + function supplyRatePerBlock() external view returns (uint) { + /* We calculate the supply rate: + * underlying = totalSupply × exchangeRate + * borrowsPer = totalBorrows ÷ underlying + * supplyRate = borrowRate × (1-reserveFactor) × borrowsPer + */ + uint exchangeRateMantissa = exchangeRateStored(); + + (uint e0, uint borrowRateMantissa) = interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); + require(e0 == 0, "supplyRatePerBlock: calculating borrowRate failed"); // semi-opaque + + (MathError e1, Exp memory underlying) = mulScalar(Exp({mantissa: exchangeRateMantissa}), totalSupply); + require(e1 == MathError.NO_ERROR, "supplyRatePerBlock: calculating underlying failed"); + + (MathError e2, Exp memory borrowsPer) = divScalarByExp(totalBorrows, underlying); + require(e2 == MathError.NO_ERROR, "supplyRatePerBlock: calculating borrowsPer failed"); + + (MathError e3, Exp memory oneMinusReserveFactor) = subExp(Exp({mantissa: mantissaOne}), Exp({mantissa: reserveFactorMantissa})); + require(e3 == MathError.NO_ERROR, "supplyRatePerBlock: calculating oneMinusReserveFactor failed"); + + (MathError e4, Exp memory supplyRate) = mulExp3(Exp({mantissa: borrowRateMantissa}), oneMinusReserveFactor, borrowsPer); + require(e4 == MathError.NO_ERROR, "supplyRatePerBlock: calculating supplyRate failed"); + + return supplyRate.mantissa; + } + + /** + * @notice Returns the current total borrows plus accrued interest + * @return The total borrows with interest + */ + function totalBorrowsCurrent() external nonReentrant returns (uint) { + require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed"); + return totalBorrows; + } + + /** + * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex + * @param account The address whose balance should be calculated after updating borrowIndex + * @return The calculated balance + */ + function borrowBalanceCurrent(address account) external nonReentrant returns (uint) { + require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed"); + return borrowBalanceStored(account); + } + + /** + * @notice Return the borrow balance of account based on stored data + * @param account The address whose balance should be calculated + * @return The calculated balance + */ + function borrowBalanceStored(address account) public view returns (uint) { + (MathError err, uint result) = borrowBalanceStoredInternal(account); + require(err == MathError.NO_ERROR, "borrowBalanceStored: borrowBalanceStoredInternal failed"); + return result; + } + + /** + * @notice Return the borrow balance of account based on stored data + * @param account The address whose balance should be calculated + * @return (error code, the calculated balance or 0 if error code is non-zero) + */ + function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) { + /* Note: we do not assert that the market is up to date */ + MathError mathErr; + uint principalTimesIndex; + uint result; + + /* Get borrowBalance and borrowIndex */ + BorrowSnapshot storage borrowSnapshot = accountBorrows[account]; + + /* If borrowBalance = 0 then borrowIndex is likely also 0. + * Rather than failing the calculation with a division by 0, we immediately return 0 in this case. + */ + if (borrowSnapshot.principal == 0) { + return (MathError.NO_ERROR, 0); + } + + /* Calculate new borrow balance using the interest index: + * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex + */ + (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex); + if (mathErr != MathError.NO_ERROR) { + return (mathErr, 0); + } + + (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex); + if (mathErr != MathError.NO_ERROR) { + return (mathErr, 0); + } + + return (MathError.NO_ERROR, result); + } + + /** + * @notice Accrue interest then return the up-to-date exchange rate + * @return Calculated exchange rate scaled by 1e18 + */ + function exchangeRateCurrent() public nonReentrant returns (uint) { + require(accrueInterest() == uint(Error.NO_ERROR), "accrue interest failed"); + return exchangeRateStored(); + } + + /** + * @notice Calculates the exchange rate from the underlying to the CToken + * @dev This function does not accrue interest before calculating the exchange rate + * @return Calculated exchange rate scaled by 1e18 + */ + function exchangeRateStored() public view returns (uint) { + (MathError err, uint result) = exchangeRateStoredInternal(); + require(err == MathError.NO_ERROR, "exchangeRateStored: exchangeRateStoredInternal failed"); + return result; + } + + /** + * @notice Calculates the exchange rate from the underlying to the CToken + * @dev This function does not accrue interest before calculating the exchange rate + * @return (error code, calculated exchange rate scaled by 1e18) + */ + function exchangeRateStoredInternal() internal view returns (MathError, uint) { + if (totalSupply == 0) { + /* + * If there are no tokens minted: + * exchangeRate = initialExchangeRate + */ + return (MathError.NO_ERROR, initialExchangeRateMantissa); + } else { + /* + * Otherwise: + * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply + */ + uint totalCash = getCashPrior(); + uint cashPlusBorrowsMinusReserves; + Exp memory exchangeRate; + MathError mathErr; + + (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves); + if (mathErr != MathError.NO_ERROR) { + return (mathErr, 0); + } + + (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, totalSupply); + if (mathErr != MathError.NO_ERROR) { + return (mathErr, 0); + } + + return (MathError.NO_ERROR, exchangeRate.mantissa); + } + } + + /** + * @notice Get cash balance of this cToken in the underlying asset + * @return The quantity of underlying asset owned by this contract + */ + function getCash() external view returns (uint) { + return getCashPrior(); + } + + struct AccrueInterestLocalVars { + MathError mathErr; + uint opaqueErr; + uint borrowRateMantissa; + uint currentBlockNumber; + uint blockDelta; + + Exp simpleInterestFactor; + + uint interestAccumulated; + uint totalBorrowsNew; + uint totalReservesNew; + uint borrowIndexNew; + } + + /** + * @notice Applies accrued interest to total borrows and reserves. + * @dev This calculates interest accrued from the last checkpointed block + * up to the current block and writes new checkpoint to storage. + */ + function accrueInterest() public returns (uint) { + AccrueInterestLocalVars memory vars; + + /* Calculate the current borrow interest rate */ + (vars.opaqueErr, vars.borrowRateMantissa) = interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves); + require(vars.borrowRateMantissa <= borrowRateMaxMantissa, "borrow rate is absurdly high"); + if (vars.opaqueErr != 0) { + return failOpaque(Error.INTEREST_RATE_MODEL_ERROR, FailureInfo.ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED, vars.opaqueErr); + } + + /* Remember the initial block number */ + vars.currentBlockNumber = getBlockNumber(); + + /* Calculate the number of blocks elapsed since the last accrual */ + (vars.mathErr, vars.blockDelta) = subUInt(vars.currentBlockNumber, accrualBlockNumber); + assert(vars.mathErr == MathError.NO_ERROR); // Block delta should always succeed and if it doesn't, blow up. + + /* + * Calculate the interest accumulated into borrows and reserves and the new index: + * simpleInterestFactor = borrowRate * blockDelta + * interestAccumulated = simpleInterestFactor * totalBorrows + * totalBorrowsNew = interestAccumulated + totalBorrows + * totalReservesNew = interestAccumulated * reserveFactor + totalReserves + * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex + */ + (vars.mathErr, vars.simpleInterestFactor) = mulScalar(Exp({mantissa: vars.borrowRateMantissa}), vars.blockDelta); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.interestAccumulated) = mulScalarTruncate(vars.simpleInterestFactor, totalBorrows); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.totalBorrowsNew) = addUInt(vars.interestAccumulated, totalBorrows); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.totalReservesNew) = mulScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), vars.interestAccumulated, totalReserves); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.borrowIndexNew) = mulScalarTruncateAddUInt(vars.simpleInterestFactor, borrowIndex, borrowIndex); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint(vars.mathErr)); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + /* We write the previously calculated values into storage */ + accrualBlockNumber = vars.currentBlockNumber; + borrowIndex = vars.borrowIndexNew; + totalBorrows = vars.totalBorrowsNew; + totalReserves = vars.totalReservesNew; + + /* We emit an AccrueInterest event */ + emit AccrueInterest(vars.interestAccumulated, vars.borrowIndexNew, totalBorrows); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sender supplies assets into the market and receives cTokens in exchange + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param mintAmount The amount of the underlying asset to supply + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function mintInternal(uint mintAmount) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed + return fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED); + } + // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to + return mintFresh(msg.sender, mintAmount); + } + + struct MintLocalVars { + Error err; + MathError mathErr; + uint exchangeRateMantissa; + uint mintTokens; + uint totalSupplyNew; + uint accountTokensNew; + } + + /** + * @notice User supplies assets into the market and receives cTokens in exchange + * @dev Assumes interest has already been accrued up to the current block + * @param minter The address of the account which is supplying the assets + * @param mintAmount The amount of the underlying asset to supply + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function mintFresh(address minter, uint mintAmount) internal returns (uint) { + /* Fail if mint not allowed */ + uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed); + } + + /* Verify market's block number equals current block number */ + if (accrualBlockNumber != getBlockNumber()) { + return fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK); + } + + MintLocalVars memory vars; + + /* Fail if checkTransferIn fails */ + vars.err = checkTransferIn(minter, mintAmount); + if (vars.err != Error.NO_ERROR) { + return fail(vars.err, FailureInfo.MINT_TRANSFER_IN_NOT_POSSIBLE); + } + + /* + * We get the current exchange rate and calculate the number of cTokens to be minted: + * mintTokens = mintAmount / exchangeRate + */ + (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(mintAmount, Exp({mantissa: vars.exchangeRateMantissa})); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + /* + * We calculate the new total supply of cTokens and minter token balance, checking for overflow: + * totalSupplyNew = totalSupply + mintTokens + * accountTokensNew = accountTokens[minter] + mintTokens + */ + (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + /* + * We call doTransferIn for the minter and the mintAmount + * Note: The cToken must handle variations between ERC-20 and ETH underlying. + * On success, the cToken holds an additional mintAmount of cash. + * If doTransferIn fails despite the fact we checked pre-conditions, + * we revert because we can't be sure if side effects occurred. + */ + vars.err = doTransferIn(minter, mintAmount); + if (vars.err != Error.NO_ERROR) { + return fail(vars.err, FailureInfo.MINT_TRANSFER_IN_FAILED); + } + + /* We write previously calculated values into storage */ + totalSupply = vars.totalSupplyNew; + accountTokens[minter] = vars.accountTokensNew; + + /* We emit a Mint event, and a Transfer event */ + emit Mint(minter, mintAmount, vars.mintTokens); + emit Transfer(address(this), minter, vars.mintTokens); + + /* We call the defense hook */ + comptroller.mintVerify(address(this), minter, mintAmount, vars.mintTokens); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sender redeems cTokens in exchange for the underlying asset + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param redeemTokens The number of cTokens to redeem into underlying + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed + return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED); + } + // redeemFresh emits redeem-specific logs on errors, so we don't need to + return redeemFresh(msg.sender, redeemTokens, 0); + } + + /** + * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset + * @dev Accrues interest whether or not the operation succeeds, unless reverted + * @param redeemAmount The amount of underlying to redeem + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed + return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED); + } + // redeemFresh emits redeem-specific logs on errors, so we don't need to + return redeemFresh(msg.sender, 0, redeemAmount); + } + + struct RedeemLocalVars { + Error err; + MathError mathErr; + uint exchangeRateMantissa; + uint redeemTokens; + uint redeemAmount; + uint totalSupplyNew; + uint accountTokensNew; + } + + /** + * @notice User redeems cTokens in exchange for the underlying asset + * @dev Assumes interest has already been accrued up to the current block + * @param redeemer The address of the account which is redeeming the tokens + * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be zero) + * @param redeemAmountIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be zero) + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) { + require(redeemTokensIn == 0 || redeemAmountIn == 0, "one of redeemTokensIn or redeemAmountIn must be zero"); + + RedeemLocalVars memory vars; + + /* exchangeRate = invoke Exchange Rate Stored() */ + (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal(); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)); + } + + /* If redeemTokensIn > 0: */ + if (redeemTokensIn > 0) { + /* + * We calculate the exchange rate and the amount of underlying to be redeemed: + * redeemTokens = redeemTokensIn + * redeemAmount = redeemTokensIn x exchangeRateCurrent + */ + vars.redeemTokens = redeemTokensIn; + + (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint(vars.mathErr)); + } + } else { + /* + * We get the current exchange rate and calculate the amount to be redeemed: + * redeemTokens = redeemAmountIn / exchangeRate + * redeemAmount = redeemAmountIn + */ + + (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa})); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint(vars.mathErr)); + } + + vars.redeemAmount = redeemAmountIn; + } + + /* Fail if redeem not allowed */ + uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed); + } + + /* Verify market's block number equals current block number */ + if (accrualBlockNumber != getBlockNumber()) { + return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK); + } + + /* + * We calculate the new total supply and redeemer balance, checking for underflow: + * totalSupplyNew = totalSupply - redeemTokens + * accountTokensNew = accountTokens[redeemer] - redeemTokens + */ + (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + /* Fail gracefully if protocol has insufficient cash */ + if (getCashPrior() < vars.redeemAmount) { + return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + /* + * We invoke doTransferOut for the redeemer and the redeemAmount. + * Note: The cToken must handle variations between ERC-20 and ETH underlying. + * On success, the cToken has redeemAmount less of cash. + * If doTransferOut fails despite the fact we checked pre-conditions, + * we revert because we can't be sure if side effects occurred. + */ + vars.err = doTransferOut(redeemer, vars.redeemAmount); + require(vars.err == Error.NO_ERROR, "redeem transfer out failed"); + + /* We write previously calculated values into storage */ + totalSupply = vars.totalSupplyNew; + accountTokens[redeemer] = vars.accountTokensNew; + + /* We emit a Transfer event, and a Redeem event */ + emit Transfer(redeemer, address(this), vars.redeemTokens); + emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens); + + /* We call the defense hook */ + comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sender borrows assets from the protocol to their own address + * @param borrowAmount The amount of the underlying asset to borrow + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function borrowInternal(uint borrowAmount) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed + return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED); + } + // borrowFresh emits borrow-specific logs on errors, so we don't need to + return borrowFresh(msg.sender, borrowAmount); + } + + struct BorrowLocalVars { + Error err; + MathError mathErr; + uint accountBorrows; + uint accountBorrowsNew; + uint totalBorrowsNew; + } + + /** + * @notice Users borrow assets from the protocol to their own address + * @param borrowAmount The amount of the underlying asset to borrow + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function borrowFresh(address payable borrower, uint borrowAmount) internal returns (uint) { + /* Fail if borrow not allowed */ + uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed); + } + + /* Verify market's block number equals current block number */ + if (accrualBlockNumber != getBlockNumber()) { + return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK); + } + + /* Fail gracefully if protocol has insufficient underlying cash */ + if (getCashPrior() < borrowAmount) { + return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE); + } + + BorrowLocalVars memory vars; + + /* + * We calculate the new borrower and total borrow balances, failing on overflow: + * accountBorrowsNew = accountBorrows + borrowAmount + * totalBorrowsNew = totalBorrows + borrowAmount + */ + (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + /* + * We invoke doTransferOut for the borrower and the borrowAmount. + * Note: The cToken must handle variations between ERC-20 and ETH underlying. + * On success, the cToken borrowAmount less of cash. + * If doTransferOut fails despite the fact we checked pre-conditions, + * we revert because we can't be sure if side effects occurred. + */ + vars.err = doTransferOut(borrower, borrowAmount); + require(vars.err == Error.NO_ERROR, "borrow transfer out failed"); + + /* We write the previously calculated values into storage */ + accountBorrows[borrower].principal = vars.accountBorrowsNew; + accountBorrows[borrower].interestIndex = borrowIndex; + totalBorrows = vars.totalBorrowsNew; + + /* We emit a Borrow event */ + emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); + + /* We call the defense hook */ + comptroller.borrowVerify(address(this), borrower, borrowAmount); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sender repays their own borrow + * @param repayAmount The amount to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed + return fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED); + } + // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to + return repayBorrowFresh(msg.sender, msg.sender, repayAmount); + } + + /** + * @notice Sender repays a borrow belonging to borrower + * @param borrower the account with the debt being payed off + * @param repayAmount The amount to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed + return fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED); + } + // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to + return repayBorrowFresh(msg.sender, borrower, repayAmount); + } + + struct RepayBorrowLocalVars { + Error err; + MathError mathErr; + uint repayAmount; + uint borrowerIndex; + uint accountBorrows; + uint accountBorrowsNew; + uint totalBorrowsNew; + } + + /** + * @notice Borrows are repaid by another user (possibly the borrower). + * @param payer the account paying off the borrow + * @param borrower the account with the debt being payed off + * @param repayAmount the amount of undelrying tokens being returned + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint) { + /* Fail if repayBorrow not allowed */ + uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed); + } + + /* Verify market's block number equals current block number */ + if (accrualBlockNumber != getBlockNumber()) { + return fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK); + } + + RepayBorrowLocalVars memory vars; + + /* We remember the original borrowerIndex for verification purposes */ + vars.borrowerIndex = accountBorrows[borrower].interestIndex; + + /* We fetch the amount the borrower owes, with accumulated interest */ + (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + /* If repayAmount == -1, repayAmount = accountBorrows */ + if (repayAmount == uint(-1)) { + vars.repayAmount = vars.accountBorrows; + } else { + vars.repayAmount = repayAmount; + } + + /* Fail if checkTransferIn fails */ + vars.err = checkTransferIn(payer, vars.repayAmount); + if (vars.err != Error.NO_ERROR) { + return fail(vars.err, FailureInfo.REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE); + } + + /* + * We calculate the new borrower and total borrow balances, failing on underflow: + * accountBorrowsNew = accountBorrows - repayAmount + * totalBorrowsNew = totalBorrows - repayAmount + */ + (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.repayAmount); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.repayAmount); + if (vars.mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint(vars.mathErr)); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + /* + * We call doTransferIn for the payer and the repayAmount + * Note: The cToken must handle variations between ERC-20 and ETH underlying. + * On success, the cToken holds an additional repayAmount of cash. + * If doTransferIn fails despite the fact we checked pre-conditions, + * we revert because we can't be sure if side effects occurred. + */ + vars.err = doTransferIn(payer, vars.repayAmount); + require(vars.err == Error.NO_ERROR, "repay borrow transfer in failed"); + + /* We write the previously calculated values into storage */ + accountBorrows[borrower].principal = vars.accountBorrowsNew; + accountBorrows[borrower].interestIndex = borrowIndex; + totalBorrows = vars.totalBorrowsNew; + + /* We emit a RepayBorrow event */ + emit RepayBorrow(payer, borrower, vars.repayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); + + /* We call the defense hook */ + comptroller.repayBorrowVerify(address(this), payer, borrower, vars.repayAmount, vars.borrowerIndex); + + return uint(Error.NO_ERROR); + } + + /** + * @notice The sender liquidates the borrowers collateral. + * The collateral seized is transferred to the liquidator. + * @param borrower The borrower of this cToken to be liquidated + * @param cTokenCollateral The market in which to seize collateral from the borrower + * @param repayAmount The amount of the underlying borrowed asset to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function liquidateBorrowInternal(address borrower, uint repayAmount, CToken cTokenCollateral) internal nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed + return fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED); + } + + error = cTokenCollateral.accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed + return fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED); + } + + // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to + return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral); + } + + /** + * @notice The liquidator liquidates the borrowers collateral. + * The collateral seized is transferred to the liquidator. + * @param borrower The borrower of this cToken to be liquidated + * @param liquidator The address repaying the borrow and seizing collateral + * @param cTokenCollateral The market in which to seize collateral from the borrower + * @param repayAmount The amount of the underlying borrowed asset to repay + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function liquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CToken cTokenCollateral) internal returns (uint) { + /* Fail if liquidate not allowed */ + uint allowed = comptroller.liquidateBorrowAllowed(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed); + } + + /* Verify market's block number equals current block number */ + if (accrualBlockNumber != getBlockNumber()) { + return fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK); + } + + /* Verify cTokenCollateral market's block number equals current block number */ + if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) { + return fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK); + } + + /* Fail if borrower = liquidator */ + if (borrower == liquidator) { + return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER); + } + + /* Fail if repayAmount = 0 */ + if (repayAmount == 0) { + return fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO); + } + + /* Fail if repayAmount = -1 */ + if (repayAmount == uint(-1)) { + return fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX); + } + + /* We calculate the number of collateral tokens that will be seized */ + (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(address(this), address(cTokenCollateral), repayAmount); + if (amountSeizeError != 0) { + return failOpaque(Error.COMPTROLLER_CALCULATION_ERROR, FailureInfo.LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED, amountSeizeError); + } + + /* Fail if seizeTokens > borrower collateral token balance */ + if (seizeTokens > cTokenCollateral.balanceOf(borrower)) { + return fail(Error.TOKEN_INSUFFICIENT_BALANCE, FailureInfo.LIQUIDATE_SEIZE_TOO_MUCH); + } + + /* Fail if repayBorrow fails */ + uint repayBorrowError = repayBorrowFresh(liquidator, borrower, repayAmount); + if (repayBorrowError != uint(Error.NO_ERROR)) { + return fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED); + } + + /* Revert if seize tokens fails (since we cannot be sure of side effects) */ + uint seizeError = cTokenCollateral.seize(liquidator, borrower, seizeTokens); + require(seizeError == uint(Error.NO_ERROR), "token seizure failed"); + + /* We emit a LiquidateBorrow event */ + emit LiquidateBorrow(liquidator, borrower, repayAmount, address(cTokenCollateral), seizeTokens); + + /* We call the defense hook */ + comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, repayAmount, seizeTokens); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Transfers collateral tokens (this market) to the liquidator. + * @dev Will fail unless called by another cToken during the process of liquidation. + * Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter. + * @param liquidator The account receiving seized collateral + * @param borrower The account having collateral seized + * @param seizeTokens The number of cTokens to seize + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) { + /* Fail if seize not allowed */ + uint allowed = comptroller.seizeAllowed(address(this), msg.sender, liquidator, borrower, seizeTokens); + if (allowed != 0) { + return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed); + } + + /* Fail if borrower = liquidator */ + if (borrower == liquidator) { + return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER); + } + + MathError mathErr; + uint borrowerTokensNew; + uint liquidatorTokensNew; + + /* + * We calculate the new borrower and liquidator token balances, failing on underflow/overflow: + * borrowerTokensNew = accountTokens[borrower] - seizeTokens + * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens + */ + (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens); + if (mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr)); + } + + (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens); + if (mathErr != MathError.NO_ERROR) { + return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr)); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + /* We write the previously calculated values into storage */ + accountTokens[borrower] = borrowerTokensNew; + accountTokens[liquidator] = liquidatorTokensNew; + + /* Emit a Transfer event */ + emit Transfer(borrower, liquidator, seizeTokens); + + /* We call the defense hook */ + comptroller.seizeVerify(address(this), msg.sender, liquidator, borrower, seizeTokens); + + return uint(Error.NO_ERROR); + } + + + /*** Admin Functions ***/ + + /** + * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. + * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. + * @param newPendingAdmin New pending admin. + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + * + * TODO: Should we add a second arg to verify, like a checksum of `newAdmin` address? + */ + function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) { + // Check caller = admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK); + } + + // Save current value, if any, for inclusion in log + address oldPendingAdmin = pendingAdmin; + + // Store pendingAdmin with value newPendingAdmin + pendingAdmin = newPendingAdmin; + + // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) + emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin + * @dev Admin function for pending admin to accept role and update admin + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _acceptAdmin() external returns (uint) { + // Check caller is pendingAdmin and pendingAdmin ≠ address(0) + if (msg.sender != pendingAdmin || msg.sender == address(0)) { + return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK); + } + + // Save current values for inclusion in log + address oldAdmin = admin; + address oldPendingAdmin = pendingAdmin; + + // Store admin with value pendingAdmin + admin = pendingAdmin; + + // Clear the pending value + pendingAdmin = address(0); + + emit NewAdmin(oldAdmin, admin); + emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sets a new comptroller for the market + * @dev Admin function to set a new comptroller + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) { + // Check caller is admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK); + } + + ComptrollerInterface oldComptroller = comptroller; + // Ensure invoke comptroller.isComptroller() returns true + require(newComptroller.isComptroller(), "marker method returned false"); + + // Set market's comptroller to newComptroller + comptroller = newComptroller; + + // Emit NewComptroller(oldComptroller, newComptroller) + emit NewComptroller(oldComptroller, newComptroller); + + return uint(Error.NO_ERROR); + } + + /** + * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh + * @dev Admin function to accrue interest and set a new reserve factor + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _setReserveFactor(uint newReserveFactorMantissa) external nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed. + return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED); + } + // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to. + return _setReserveFactorFresh(newReserveFactorMantissa); + } + + /** + * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual) + * @dev Admin function to set a new reserve factor + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) { + // Check caller is admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK); + } + + // Verify market's block number equals current block number + if (accrualBlockNumber != getBlockNumber()) { + // TODO: static_assert + no error code? + return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK); + } + + // Check newReserveFactor ≤ maxReserveFactor + if (newReserveFactorMantissa > reserveFactorMaxMantissa) { + return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK); + } + + uint oldReserveFactorMantissa = reserveFactorMantissa; + reserveFactorMantissa = newReserveFactorMantissa; + + emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Accrues interest and reduces reserves by transferring to admin + * @param reduceAmount Amount of reduction to reserves + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed. + return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED); + } + // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to. + return _reduceReservesFresh(reduceAmount); + } + + /** + * @notice Reduces reserves by transferring to admin + * @dev Requires fresh interest accrual + * @param reduceAmount Amount of reduction to reserves + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _reduceReservesFresh(uint reduceAmount) internal returns (uint) { + Error err; + // totalReserves - reduceAmount + uint totalReservesNew; + + // Check caller is admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK); + } + + // We fail gracefully unless market's block number equals current block number + if (accrualBlockNumber != getBlockNumber()) { + // TODO: static_assert + no error code? + return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK); + } + + // Fail gracefully if protocol has insufficient underlying cash + if (getCashPrior() < reduceAmount) { + return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE); + } + + // Check reduceAmount ≤ reserves[n] (totalReserves) + // TODO: I'm following the spec literally here but I think we should we just use SafeMath instead and fail on an error (which would be underflow) + if (reduceAmount > totalReserves) { + return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION); + } + + ///////////////////////// + // EFFECTS & INTERACTIONS + // (No safe failures beyond this point) + + totalReservesNew = totalReserves - reduceAmount; + // We checked reduceAmount <= totalReserves above, so this should never revert. + require(totalReservesNew <= totalReserves, "reduce reserves unexpected underflow"); + + // Store reserves[n+1] = reserves[n] - reduceAmount + totalReserves = totalReservesNew; + + // invoke doTransferOut(reduceAmount, admin) + err = doTransferOut(admin, reduceAmount); + // we revert on the failure of this command + require(err == Error.NO_ERROR, "reduce reserves transfer out failed"); + + emit ReservesReduced(admin, reduceAmount, totalReservesNew); + + return uint(Error.NO_ERROR); + } + + /** + * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh + * @dev Admin function to accrue interest and update the interest rate model + * @param newInterestRateModel the new interest rate model to use + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) { + uint error = accrueInterest(); + if (error != uint(Error.NO_ERROR)) { + // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed + return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED); + } + // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to. + return _setInterestRateModelFresh(newInterestRateModel); + } + + /** + * @notice updates the interest rate model (*requires fresh interest accrual) + * @dev Admin function to update the interest rate model + * @param newInterestRateModel the new interest rate model to use + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) { + + // Used to store old model for use in the event that is emitted on success + InterestRateModel oldInterestRateModel; + + // Check caller is admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK); + } + + // We fail gracefully unless market's block number equals current block number + if (accrualBlockNumber != getBlockNumber()) { + // TODO: static_assert + no error code? + return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK); + } + + // Track the market's current interest rate model + oldInterestRateModel = interestRateModel; + + // Ensure invoke newInterestRateModel.isInterestRateModel() returns true + require(newInterestRateModel.isInterestRateModel(), "marker method returned false"); + + // Set the interest rate model to newInterestRateModel + interestRateModel = newInterestRateModel; + + // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel) + emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel); + + return uint(Error.NO_ERROR); + } + + /*** Safe Token ***/ + + /** + * @notice Gets balance of this contract in terms of the underlying + * @dev This excludes the value of the current message, if any + * @return The quantity of underlying owned by this contract + */ + function getCashPrior() internal view returns (uint); + + /** + * @dev Checks whether or not there is sufficient allowance for this contract to move amount from `from` and + * whether or not `from` has a balance of at least `amount`. Does NOT do a transfer. + */ + function checkTransferIn(address from, uint amount) internal view returns (Error); + + /** + * @dev Performs a transfer in, ideally returning an explanatory error code upon failure rather than reverting. + * If caller has not called `checkTransferIn`, this may revert due to insufficient balance or insufficient allowance. + * If caller has called `checkTransferIn` successfully, this should not revert in normal conditions. + */ + function doTransferIn(address from, uint amount) internal returns (Error); + + /** + * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting. + * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract. + * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions. + */ + function doTransferOut(address payable to, uint amount) internal returns (Error); +} diff --git a/contracts/CarefulMath.sol b/contracts/CarefulMath.sol new file mode 100644 index 000000000..1670342c1 --- /dev/null +++ b/contracts/CarefulMath.sol @@ -0,0 +1,85 @@ +pragma solidity ^0.5.8; + +/** + * @title Careful Math + * @author Compound + * @notice Derived from OpenZeppelin's SafeMath library + * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol + */ +contract CarefulMath { + + /** + * @dev Possible error codes that we can return + */ + enum MathError { + NO_ERROR, + DIVISION_BY_ZERO, + INTEGER_OVERFLOW, + INTEGER_UNDERFLOW + } + + /** + * @dev Multiplies two numbers, returns an error on overflow. + */ + function mulUInt(uint a, uint b) internal pure returns (MathError, uint) { + if (a == 0) { + return (MathError.NO_ERROR, 0); + } + + uint c = a * b; + + if (c / a != b) { + return (MathError.INTEGER_OVERFLOW, 0); + } else { + return (MathError.NO_ERROR, c); + } + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function divUInt(uint a, uint b) internal pure returns (MathError, uint) { + if (b == 0) { + return (MathError.DIVISION_BY_ZERO, 0); + } + + return (MathError.NO_ERROR, a / b); + } + + /** + * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend). + */ + function subUInt(uint a, uint b) internal pure returns (MathError, uint) { + if (b <= a) { + return (MathError.NO_ERROR, a - b); + } else { + return (MathError.INTEGER_UNDERFLOW, 0); + } + } + + /** + * @dev Adds two numbers, returns an error on overflow. + */ + function addUInt(uint a, uint b) internal pure returns (MathError, uint) { + uint c = a + b; + + if (c >= a) { + return (MathError.NO_ERROR, c); + } else { + return (MathError.INTEGER_OVERFLOW, 0); + } + } + + /** + * @dev add a and b and then subtract c + */ + function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) { + (MathError err0, uint sum) = addUInt(a, b); + + if (err0 != MathError.NO_ERROR) { + return (err0, 0); + } + + return subUInt(sum, c); + } +} \ No newline at end of file diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol new file mode 100644 index 000000000..2991b77cf --- /dev/null +++ b/contracts/Comptroller.sol @@ -0,0 +1,996 @@ +pragma solidity ^0.5.8; + +import "./CToken.sol"; +import "./ErrorReporter.sol"; +import "./Exponential.sol"; +import "./PriceOracle.sol"; +import "./ComptrollerInterface.sol"; +import "./ComptrollerStorage.sol"; +import "./Unitroller.sol"; + +/** + * @title Compound's Comptroller Contract + * @author Compound + */ +contract Comptroller is ComptrollerV1Storage, ComptrollerInterface, ComptrollerErrorReporter, Exponential { + struct Market { + /** + * @notice Whether or not this market is listed + */ + bool isListed; + + /** + * @notice Multiplier representing the most one can borrow against their collateral in this market. + * For instance, 0.9 to allow borrowing 90% of collateral value. + * Must be between 0 and 1, and stored as a mantissa. + */ + uint collateralFactorMantissa; + + /** + * @notice Per-market mapping of "accounts in this asset" + */ + mapping(address => bool) accountMembership; + } + + /** + * @notice Official mapping of cTokens -> Market metadata + * @dev Used e.g. to determine if a market is supported + */ + mapping(address => Market) public markets; + + /** + * @notice Emitted when an admin supports a market + */ + event MarketListed(CToken cToken); + + /** + * @notice Emitted when an account enters a market + */ + event MarketEntered(CToken cToken, address account); + + /** + * @notice Emitted when an account exits a market + */ + event MarketExited(CToken cToken, address account); + + /** + * @notice Emitted when close factor is changed by admin + */ + event NewCloseFactor(uint oldCloseFactorMantissa, uint newCloseFactorMantissa); + + /** + * @notice Emitted when a collateral factor is changed by admin + */ + event NewCollateralFactor(CToken cToken, uint oldCollateralFactorMantissa, uint newCollateralFactorMantissa); + + /** + * @notice Emitted when liquidation incentive is changed by admin + */ + event NewLiquidationIncentive(uint oldLiquidationIncentiveMantissa, uint newLiquidationIncentiveMantissa); + + /** + * @notice Emitted when maxAssets is changed by admin + */ + event NewMaxAssets(uint oldMaxAssets, uint newMaxAssets); + + /** + * @notice Emitted when price oracle is changed + */ + event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle); + + /** + * @notice Indicator that this is a Comptroller contract (for inspection) + */ + bool public constant isComptroller = true; + + // closeFactorMantissa must be strictly greater than this value + uint constant closeFactorMinMantissa = 5e16; // 0.05 + + // closeFactorMantissa must not exceed this value + uint constant closeFactorMaxMantissa = 9e17; // 0.9 + + // No collateralFactorMantissa may exceed this value + uint constant collateralFactorMaxMantissa = 9e17; // 0.9 + + // liquidationIncentiveMantissa must be no less than this value + uint constant liquidationIncentiveMinMantissa = mantissaOne; + + // liquidationIncentiveMantissa must be no greater than this value + uint constant liquidationIncentiveMaxMantissa = 15e17; // 1.5 + + constructor() public { + admin = msg.sender; + } + + /*** Assets You Are In ***/ + + /** + * @notice Returns the assets an account has entered + * @param account The address of the account to pull assets for + * @return A dynamic list with the assets the account has entered + */ + function getAssetsIn(address account) external view returns (CToken[] memory) { + CToken[] memory assetsIn = accountAssets[account]; + + return assetsIn; + } + + /** + * @notice Returns whether the given account is entered in the given asset + * @param account The address of the account to check + * @param cToken The cToken to check + * @return True if the account is in the asset, otherwise false. + */ + function checkMembership(address account, CToken cToken) external view returns (bool) { + return markets[address(cToken)].accountMembership[account]; + } + + /** + * @notice Add assets to be included in account liquidity calculation + * @param cTokens The list of addresses of the cToken markets to be enabled + * @return Success indicator for whether each corresponding market was entered + */ + function enterMarkets(address[] memory cTokens) public returns (uint[] memory) { + uint len = cTokens.length; + + uint[] memory results = new uint[](len); + for (uint i = 0; i < len; i++) { + CToken cToken = CToken(cTokens[i]); + Market storage marketToJoin = markets[address(cToken)]; + + if (!marketToJoin.isListed) { + // if market is not listed, cannot join move along + results[i] = uint(Error.MARKET_NOT_LISTED); + continue; + } + + if (marketToJoin.accountMembership[msg.sender] == true) { + // if already joined, move along + results[i] = uint(Error.NO_ERROR); + continue; + } + + if (accountAssets[msg.sender].length >= maxAssets) { + // if no space, cannot join, move along + results[i] = uint(Error.TOO_MANY_ASSETS); + continue; + } + + // survived the gauntlet, add to list + // NOTE: we store these somewhat redundantly as a significant optimization + // this avoids having to iterate through the list for the most common use cases + // that is, only when we need to perform liquidity checks + // and not whenever we want to check if an account is in a particular market + marketToJoin.accountMembership[msg.sender] = true; + accountAssets[msg.sender].push(cToken); + + emit MarketEntered(cToken, msg.sender); + + results[i] = uint(Error.NO_ERROR); + } + + return results; + } + + /** + * @notice Removes asset from sender's account liquidity calculation + * @dev Sender must not have an outstanding borrow balance in the asset, + * or be providing neccessary collateral for an outstanding borrow. + * @param cTokenAddress The address of the asset to be removed + * @return Whether or not the account successfully exited the market + */ + function exitMarket(address cTokenAddress) external returns (uint) { + CToken cToken = CToken(cTokenAddress); + /* Get sender tokensHeld and amountOwed underlying from the cToken */ + (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender); + require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code + + /* Fail if the sender has a borrow balance */ + if (amountOwed != 0) { + return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED); + } + + /* Fail if the sender is not permitted to redeem all of their tokens */ + uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld); + if (allowed != 0) { + return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed); + } + + Market storage marketToExit = markets[address(cToken)]; + + /* Return true if the sender is not already ‘in’ the market */ + if (!marketToExit.accountMembership[msg.sender]) { + return uint(Error.NO_ERROR); + } + + /* Set cToken account membership to false */ + delete marketToExit.accountMembership[msg.sender]; + + /* Delete cToken from the account’s list of assets */ + // load into memory for faster iteration + CToken[] memory userAssetList = accountAssets[msg.sender]; + uint len = userAssetList.length; + uint assetIndex = len; + for (uint i = 0; i < len; i++) { + if (userAssetList[i] == cToken) { + assetIndex = i; + break; + } + } + + // We *must* have found the asset in the list or our redundant data structure is broken + assert(assetIndex < len); + + // copy last item in list to location of item to be removed, reduce length by 1 + CToken[] storage storedList = accountAssets[msg.sender]; + storedList[assetIndex] = storedList[storedList.length - 1]; + storedList.length--; + + emit MarketExited(cToken, msg.sender); + + return uint(Error.NO_ERROR); + } + + /*** Policy Hooks ***/ + + /** + * @notice Checks if the account should be allowed to mint tokens in the given market + * @param cToken The market to verify the mint against + * @param minter The account which would get the minted tokens + * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens + * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) + */ + function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint) { + minter; // currently unused + mintAmount; // currently unused + + if (!markets[cToken].isListed) { + return uint(Error.MARKET_NOT_LISTED); + } + + // *may include Policy Hook-type checks + + return uint(Error.NO_ERROR); + } + + /** + * @notice Validates mint and reverts on rejection. May emit logs. + * @param cToken Asset being minted + * @param minter The address minting the tokens + * @param mintAmount The amount of the underlying asset being minted + * @param mintTokens The number of tokens being minted + */ + function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external { + cToken; // currently unused + minter; // currently unused + mintAmount; // currently unused + mintTokens; // currently unused + + if (false) { + maxAssets = maxAssets; // not pure + } + } + + /** + * @notice Checks if the account should be allowed to redeem tokens in the given market + * @param cToken The market to verify the redeem against + * @param redeemer The account which would redeem the tokens + * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market + * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) + */ + function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint) { + return redeemAllowedInternal(cToken, redeemer, redeemTokens); + } + + function redeemAllowedInternal(address cToken, address redeemer, uint redeemTokens) internal view returns (uint) { + if (!markets[cToken].isListed) { + return uint(Error.MARKET_NOT_LISTED); + } + + // *may include Policy Hook-type checks + + /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ + if (!markets[cToken].accountMembership[redeemer]) { + return uint(Error.NO_ERROR); + } + + /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */ + (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(redeemer, CToken(cToken), redeemTokens, 0); + if (err != Error.NO_ERROR) { + return uint(err); + } + if (shortfall > 0) { + return uint(Error.INSUFFICIENT_LIQUIDITY); + } + + return uint(Error.NO_ERROR); + } + + /** + * @notice Validates redeem and reverts on rejection. May emit logs. + * @param cToken Asset being redeemed + * @param redeemer The address redeeming the tokens + * @param redeemAmount The amount of the underlying asset being redeemed + * @param redeemTokens The number of tokens being redeemed + */ + function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external { + cToken; // currently unused + redeemer; // currently unused + redeemAmount; // currently unused + redeemTokens; // currently unused + + // Require tokens is zero or amount is also zero + if (redeemTokens == 0 && redeemAmount > 0) { + revert("redeemTokens zero"); + } + } + + /** + * @notice Checks if the account should be allowed to borrow the underlying asset of the given market + * @param cToken The market to verify the borrow against + * @param borrower The account which would borrow the asset + * @param borrowAmount The amount of underlying the account would borrow + * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) + */ + function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint) { + if (!markets[cToken].isListed) { + return uint(Error.MARKET_NOT_LISTED); + } + + // *may include Policy Hook-type checks + + if (!markets[cToken].accountMembership[borrower]) { + return uint(Error.MARKET_NOT_ENTERED); + } + + if (oracle.getUnderlyingPrice(CToken(cToken)) == 0) { + return uint(Error.PRICE_ERROR); + } + + (Error err, , uint shortfall) = getHypotheticalAccountLiquidityInternal(borrower, CToken(cToken), 0, borrowAmount); + if (err != Error.NO_ERROR) { + return uint(err); + } + if (shortfall > 0) { + return uint(Error.INSUFFICIENT_LIQUIDITY); + } + + return uint(Error.NO_ERROR); + } + + /** + * @notice Validates borrow and reverts on rejection. May emit logs. + * @param cToken Asset whose underlying is being borrowed + * @param borrower The address borrowing the underlying + * @param borrowAmount The amount of the underlying asset requested to borrow + */ + function borrowVerify(address cToken, address borrower, uint borrowAmount) external { + cToken; // currently unused + borrower; // currently unused + borrowAmount; // currently unused + + if (false) { + maxAssets = maxAssets; // not pure + } + } + + /** + * @notice Checks if the account should be allowed to repay a borrow in the given market + * @param cToken The market to verify the repay against + * @param payer The account which would repay the asset + * @param borrower The account which would borrowed the asset + * @param repayAmount The amount of the underlying asset the account would repay + * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) + */ + function repayBorrowAllowed( + address cToken, + address payer, + address borrower, + uint repayAmount) external returns (uint) { + payer; // currently unused + borrower; // currently unused + repayAmount; // currently unused + + if (!markets[cToken].isListed) { + return uint(Error.MARKET_NOT_LISTED); + } + + // *may include Policy Hook-type checks + + return uint(Error.NO_ERROR); + } + + /** + * @notice Validates repayBorrow and reverts on rejection. May emit logs. + * @param cToken Asset being repaid + * @param payer The address repaying the borrow + * @param borrower The address of the borrower + * @param repayAmount The amount of underlying being repaid + */ + function repayBorrowVerify( + address cToken, + address payer, + address borrower, + uint repayAmount, + uint borrowerIndex) external { + cToken; // currently unused + payer; // currently unused + borrower; // currently unused + repayAmount; // currently unused + borrowerIndex; // currently unused + + if (false) { + maxAssets = maxAssets; // not pure + } + } + + /** + * @notice Checks if the liquidation should be allowed to occur + * @param cTokenBorrowed Asset which was borrowed by the borrower + * @param cTokenCollateral Asset which was used as collateral and will be seized + * @param liquidator The address repaying the borrow and seizing the collateral + * @param borrower The address of the borrower + * @param repayAmount The amount of underlying being repaid + */ + function liquidateBorrowAllowed( + address cTokenBorrowed, + address cTokenCollateral, + address liquidator, + address borrower, + uint repayAmount) external returns (uint) { + liquidator; // currently unused + borrower; // currently unused + repayAmount; // currently unused + + if (!markets[cTokenBorrowed].isListed || !markets[cTokenCollateral].isListed) { + return uint(Error.MARKET_NOT_LISTED); + } + + // *may include Policy Hook-type checks + + /* The borrower must have shortfall in order to be liquidatable */ + (Error err, , uint shortfall) = getAccountLiquidityInternal(borrower); + if (err != Error.NO_ERROR) { + return uint(err); + } + if (shortfall == 0) { + return uint(Error.INSUFFICIENT_SHORTFALL); + } + + /* The liquidator may not repay more than what is allowed by the closeFactor */ + uint borrowBalance = CToken(cTokenBorrowed).borrowBalanceStored(borrower); + (MathError mathErr, uint maxClose) = mulScalarTruncate(Exp({mantissa: closeFactorMantissa}), borrowBalance); + if (mathErr != MathError.NO_ERROR) { + return uint(Error.MATH_ERROR); + } + if (repayAmount > maxClose) { + return uint(Error.TOO_MUCH_REPAY); + } + + return uint(Error.NO_ERROR); + } + + /** + * @notice Validates liquidateBorrow and reverts on rejection. May emit logs. + * @param cTokenBorrowed Asset which was borrowed by the borrower + * @param cTokenCollateral Asset which was used as collateral and will be seized + * @param liquidator The address repaying the borrow and seizing the collateral + * @param borrower The address of the borrower + * @param repayAmount The amount of underlying being repaid + */ + function liquidateBorrowVerify( + address cTokenBorrowed, + address cTokenCollateral, + address liquidator, + address borrower, + uint repayAmount, + uint seizeTokens) external { + cTokenBorrowed; // currently unused + cTokenCollateral; // currently unused + liquidator; // currently unused + borrower; // currently unused + repayAmount; // currently unused + seizeTokens; // currently unused + + if (false) { + maxAssets = maxAssets; // not pure + } + } + + /** + * @notice Checks if the seizing of assets should be allowed to occur + * @param cTokenCollateral Asset which was used as collateral and will be seized + * @param cTokenBorrowed Asset which was borrowed by the borrower + * @param liquidator The address repaying the borrow and seizing the collateral + * @param borrower The address of the borrower + * @param seizeTokens The number of collateral tokens to seize + */ + function seizeAllowed( + address cTokenCollateral, + address cTokenBorrowed, + address liquidator, + address borrower, + uint seizeTokens) external returns (uint) { + liquidator; // currently unused + borrower; // currently unused + seizeTokens; // currently unused + + if (!markets[cTokenCollateral].isListed || !markets[cTokenBorrowed].isListed) { + return uint(Error.MARKET_NOT_LISTED); + } + + if (CToken(cTokenCollateral).comptroller() != CToken(cTokenBorrowed).comptroller()) { + return uint(Error.COMPTROLLER_MISMATCH); + } + + // *may include Policy Hook-type checks + + return uint(Error.NO_ERROR); + } + + /** + * @notice Validates seize and reverts on rejection. May emit logs. + * @param cTokenCollateral Asset which was used as collateral and will be seized + * @param cTokenBorrowed Asset which was borrowed by the borrower + * @param liquidator The address repaying the borrow and seizing the collateral + * @param borrower The address of the borrower + * @param seizeTokens The number of collateral tokens to seize + */ + function seizeVerify( + address cTokenCollateral, + address cTokenBorrowed, + address liquidator, + address borrower, + uint seizeTokens) external { + cTokenCollateral; // currently unused + cTokenBorrowed; // currently unused + liquidator; // currently unused + borrower; // currently unused + seizeTokens; // currently unused + + if (false) { + maxAssets = maxAssets; // not pure + } + } + + /** + * @notice Checks if the account should be allowed to transfer tokens in the given market + * @param cToken The market to verify the transfer against + * @param src The account which sources the tokens + * @param dst The account which receives the tokens + * @param transferTokens The number of cTokens to transfer + * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol) + */ + function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { + cToken; // currently unused + src; // currently unused + dst; // currently unused + transferTokens; // currently unused + + // *may include Policy Hook-type checks + + // Currently the only consideration is whether or not + // the src is allowed to redeem this many tokens + return redeemAllowedInternal(cToken, src, transferTokens); + } + + /** + * @notice Validates transfer and reverts on rejection. May emit logs. + * @param cToken Asset being transferred + * @param src The account which sources the tokens + * @param dst The account which receives the tokens + * @param transferTokens The number of cTokens to transfer + */ + function transferVerify(address cToken, address src, address dst, uint transferTokens) external { + cToken; // currently unused + src; // currently unused + dst; // currently unused + transferTokens; // currently unused + + if (false) { + maxAssets = maxAssets; // not pure + } + } + + /*** Liquidity/Liquidation Calculations ***/ + + /** + * @dev Local vars for avoiding stack-depth limits in calculating account liquidity. + * Note that `cTokenBalance` is the number of cTokens the account owns in the market, + * whereas `borrowBalance` is the amount of underlying that the account has borrowed. + */ + struct AccountLiquidityLocalVars { + uint sumCollateral; + uint sumBorrowPlusEffects; + uint cTokenBalance; + uint borrowBalance; + uint exchangeRateMantissa; + uint oraclePriceMantissa; + Exp collateralFactor; + Exp exchangeRate; + Exp oraclePrice; + Exp tokensToEther; + } + + /** + * @notice Determine the current account liquidity wrt collateral requirements + * @return (possible error code (semi-opaque), + account liquidity in excess of collateral requirements, + * account shortfall below collateral requirements) + */ + function getAccountLiquidity(address account) public view returns (uint, uint, uint) { + (Error err, uint liquidity, uint shortfall) = getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); + + return (uint(err), liquidity, shortfall); + } + + /** + * @notice Determine the current account liquidity wrt collateral requirements + * @return (possible error code, + account liquidity in excess of collateral requirements, + * account shortfall below collateral requirements) + */ + function getAccountLiquidityInternal(address account) internal view returns (Error, uint, uint) { + return getHypotheticalAccountLiquidityInternal(account, CToken(0), 0, 0); + } + + /** + * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed + * @param cTokenModify The market to hypothetically redeem/borrow in + * @param account The account to determine liquidity for + * @param redeemTokens The number of tokens to hypothetically redeem + * @param borrowAmount The amount of underlying to hypothetically borrow + * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data, + * without calculating accumulated interest. + * @return (possible error code, + hypothetical account liquidity in excess of collateral requirements, + * hypothetical account shortfall below collateral requirements) + */ + function getHypotheticalAccountLiquidityInternal( + address account, + CToken cTokenModify, + uint redeemTokens, + uint borrowAmount) internal view returns (Error, uint, uint) { + + AccountLiquidityLocalVars memory vars; // Holds all our calculation results + uint oErr; + MathError mErr; + + // For each asset the account is in + CToken[] memory assets = accountAssets[account]; + for (uint i = 0; i < assets.length; i++) { + CToken asset = assets[i]; + + // Read the balances and exchange rate from the cToken + (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(account); + if (oErr != 0) { // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades + return (Error.SNAPSHOT_ERROR, 0, 0); + } + vars.collateralFactor = Exp({mantissa: markets[address(asset)].collateralFactorMantissa}); + vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa}); + + // Get the normalized price of the asset + vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset); + if (vars.oraclePriceMantissa == 0) { + return (Error.PRICE_ERROR, 0, 0); + } + vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa}); + + // Pre-compute a conversion factor from tokens -> ether (normalized price value) + (mErr, vars.tokensToEther) = mulExp3(vars.collateralFactor, vars.exchangeRate, vars.oraclePrice); + if (mErr != MathError.NO_ERROR) { + return (Error.MATH_ERROR, 0, 0); + } + + // sumCollateral += tokensToEther * cTokenBalance + (mErr, vars.sumCollateral) = mulScalarTruncateAddUInt(vars.tokensToEther, vars.cTokenBalance, vars.sumCollateral); + if (mErr != MathError.NO_ERROR) { + return (Error.MATH_ERROR, 0, 0); + } + + // sumBorrowPlusEffects += oraclePrice * borrowBalance + (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, vars.borrowBalance, vars.sumBorrowPlusEffects); + if (mErr != MathError.NO_ERROR) { + return (Error.MATH_ERROR, 0, 0); + } + + // Calculate effects of interacting with cTokenModify + if (asset == cTokenModify) { + // redeem effect + // sumBorrowPlusEffects += tokensToEther * redeemTokens + (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.tokensToEther, redeemTokens, vars.sumBorrowPlusEffects); + if (mErr != MathError.NO_ERROR) { + return (Error.MATH_ERROR, 0, 0); + } + + // borrow effect + // sumBorrowPlusEffects += oraclePrice * borrowAmount + (mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(vars.oraclePrice, borrowAmount, vars.sumBorrowPlusEffects); + if (mErr != MathError.NO_ERROR) { + return (Error.MATH_ERROR, 0, 0); + } + } + } + + // These are safe, as the underflow condition is checked first + if (vars.sumCollateral > vars.sumBorrowPlusEffects) { + return (Error.NO_ERROR, vars.sumCollateral - vars.sumBorrowPlusEffects, 0); + } else { + return (Error.NO_ERROR, 0, vars.sumBorrowPlusEffects - vars.sumCollateral); + } + } + + /** + * @notice Calculate number of tokens of collateral asset to seize given an underlying amount + * @dev Used in liquidation (called in cToken.liquidateBorrowFresh) + * @param cTokenBorrowed The address of the borrowed cToken + * @param cTokenCollateral The address of the collateral cToken + * @param repayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens + * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation) + */ + function liquidateCalculateSeizeTokens(address cTokenBorrowed, address cTokenCollateral, uint repayAmount) external view returns (uint, uint) { + /* Read oracle prices for borrowed and collateral markets */ + uint priceBorrowedMantissa = oracle.getUnderlyingPrice(CToken(cTokenBorrowed)); + uint priceCollateralMantissa = oracle.getUnderlyingPrice(CToken(cTokenCollateral)); + if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) { + return (uint(Error.PRICE_ERROR), 0); + } + + /* + * Get the exchange rate and calculate the number of collateral tokens to seize: + * seizeAmount = repayAmount * liquidationIncentive * priceBorrowed / priceCollateral + * seizeTokens = seizeAmount / exchangeRate + * = repayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate) + */ + uint exchangeRateMantissa = CToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error + uint seizeTokens; + Exp memory numerator; + Exp memory denominator; + Exp memory ratio; + MathError mathErr; + + (mathErr, numerator) = mulExp(liquidationIncentiveMantissa, priceBorrowedMantissa); + if (mathErr != MathError.NO_ERROR) { + return (uint(Error.MATH_ERROR), 0); + } + + (mathErr, denominator) = mulExp(priceCollateralMantissa, exchangeRateMantissa); + if (mathErr != MathError.NO_ERROR) { + return (uint(Error.MATH_ERROR), 0); + } + + (mathErr, ratio) = divExp(numerator, denominator); + if (mathErr != MathError.NO_ERROR) { + return (uint(Error.MATH_ERROR), 0); + } + + (mathErr, seizeTokens) = mulScalarTruncate(ratio, repayAmount); + if (mathErr != MathError.NO_ERROR) { + return (uint(Error.MATH_ERROR), 0); + } + + return (uint(Error.NO_ERROR), seizeTokens); + } + + /*** Admin Functions ***/ + + /** + * @notice Sets a new price oracle for the comptroller + * @dev Admin function to set a new price oracle + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _setPriceOracle(PriceOracle newOracle) public returns (uint) { + // Check caller is admin OR currently initialzing as new unitroller implementation + if (!adminOrInitializing()) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_PRICE_ORACLE_OWNER_CHECK); + } + + // Track the old oracle for the comptroller + PriceOracle oldOracle = oracle; + + // Ensure invoke newOracle.isPriceOracle() returns true + // require(newOracle.isPriceOracle(), "oracle method isPriceOracle returned false"); + + // Set comptroller's oracle to newOracle + oracle = newOracle; + + // Emit NewPriceOracle(oldOracle, newOracle) + emit NewPriceOracle(oldOracle, newOracle); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sets the closeFactor used when liquidating borrows + * @dev Admin function to set closeFactor + * @param newCloseFactorMantissa New close factor, scaled by 1e18 + * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) + */ + function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256) { + // Check caller is admin OR currently initialzing as new unitroller implementation + if (!adminOrInitializing()) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_CLOSE_FACTOR_OWNER_CHECK); + } + + Exp memory newCloseFactorExp = Exp({mantissa: newCloseFactorMantissa}); + Exp memory lowLimit = Exp({mantissa: closeFactorMinMantissa}); + if (lessThanOrEqualExp(newCloseFactorExp, lowLimit)) { + return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); + } + + Exp memory highLimit = Exp({mantissa: closeFactorMaxMantissa}); + if (lessThanExp(highLimit, newCloseFactorExp)) { + return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION); + } + + uint oldCloseFactorMantissa = closeFactorMantissa; + closeFactorMantissa = newCloseFactorMantissa; + emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sets the collateralFactor for a market + * @dev Admin function to set per-market collateralFactor + * @param cToken The market to set the factor on + * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18 + * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) + */ + function _setCollateralFactor(CToken cToken, uint newCollateralFactorMantissa) external returns (uint256) { + // Check caller is admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_COLLATERAL_FACTOR_OWNER_CHECK); + } + + // Verify market is listed + Market storage market = markets[address(cToken)]; + if (!market.isListed) { + return fail(Error.MARKET_NOT_LISTED, FailureInfo.SET_COLLATERAL_FACTOR_NO_EXISTS); + } + + Exp memory newCollateralFactorExp = Exp({mantissa: newCollateralFactorMantissa}); + + // Check collateral factor <= 0.9 + Exp memory highLimit = Exp({mantissa: collateralFactorMaxMantissa}); + if (lessThanExp(highLimit, newCollateralFactorExp)) { + return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION); + } + + // If collateral factor != 0, fail if price == 0 + if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(cToken) == 0) { + return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE); + } + + // Set market's collateral factor to new collateral factor, remember old value + uint oldCollateralFactorMantissa = market.collateralFactorMantissa; + market.collateralFactorMantissa = newCollateralFactorMantissa; + + // Emit event with asset, old collateral factor, and new collateral factor + emit NewCollateralFactor(cToken, oldCollateralFactorMantissa, newCollateralFactorMantissa); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sets maxAssets which controls how many markets can be entered + * @dev Admin function to set maxAssets + * @param newMaxAssets New max assets + * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) + */ + function _setMaxAssets(uint newMaxAssets) external returns (uint) { + // Check caller is admin OR currently initialzing as new unitroller implementation + if (!adminOrInitializing()) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_MAX_ASSETS_OWNER_CHECK); + } + + uint oldMaxAssets = maxAssets; + maxAssets = newMaxAssets; + emit NewMaxAssets(oldMaxAssets, newMaxAssets); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Sets liquidationIncentive + * @dev Admin function to set liquidationIncentive + * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18 + * @return uint 0=success, otherwise a failure. (See ErrorReporter for details) + */ + function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint) { + // Check caller is admin OR currently initialzing as new unitroller implementation + if (!adminOrInitializing()) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_LIQUIDATION_INCENTIVE_OWNER_CHECK); + } + + // Check de-scaled 1 <= newLiquidationDiscount <= 1.5 + Exp memory newLiquidationIncentive = Exp({mantissa: newLiquidationIncentiveMantissa}); + Exp memory minLiquidationIncentive = Exp({mantissa: liquidationIncentiveMinMantissa}); + if (lessThanExp(newLiquidationIncentive, minLiquidationIncentive)) { + return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); + } + + Exp memory maxLiquidationIncentive = Exp({mantissa: liquidationIncentiveMaxMantissa}); + if (lessThanExp(maxLiquidationIncentive, newLiquidationIncentive)) { + return fail(Error.INVALID_LIQUIDATION_INCENTIVE, FailureInfo.SET_LIQUIDATION_INCENTIVE_VALIDATION); + } + + // Save current value for use in log + uint oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa; + + // Set liquidation incentive to new incentive + liquidationIncentiveMantissa = newLiquidationIncentiveMantissa; + + // Emit event with old incentive, new incentive + emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Add the market to the markets mapping and set it as listed + * @dev Admin function to set isListed and add support for the market + * @param cToken The address of the market (token) to list + * @return uint 0=success, otherwise a failure. (See enum Error for details) + */ + function _supportMarket(CToken cToken) external returns (uint) { + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SUPPORT_MARKET_OWNER_CHECK); + } + + if (markets[address(cToken)].isListed) { + return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS); + } + + cToken.isCToken(); // Sanity check to make sure its really a CToken + + markets[address(cToken)] = Market({isListed: true, collateralFactorMantissa: 0}); + emit MarketListed(cToken); + + return uint(Error.NO_ERROR); + } + + function _become(Unitroller unitroller, PriceOracle _oracle, uint _closeFactorMantissa, uint _maxAssets, bool reinitializing) public { + require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); + uint changeStatus = unitroller._acceptImplementation(); + + require(changeStatus == 0, "change not authorized"); + + if (!reinitializing) { + Comptroller freshBrainedComptroller = Comptroller(address(unitroller)); + + // Ensure invoke _setPriceOracle() = 0 + uint err = freshBrainedComptroller._setPriceOracle(_oracle); + require (err == uint(Error.NO_ERROR), "set price oracle error"); + + // Ensure invoke _setCloseFactor() = 0 + err = freshBrainedComptroller._setCloseFactor(_closeFactorMantissa); + require (err == uint(Error.NO_ERROR), "set close factor error"); + + // Ensure invoke _setMaxAssets() = 0 + err = freshBrainedComptroller._setMaxAssets(_maxAssets); + require (err == uint(Error.NO_ERROR), "set max asssets error"); + + // Ensure invoke _setLiquidationIncentive(liquidationIncentiveMinMantissa) = 0 + err = freshBrainedComptroller._setLiquidationIncentive(liquidationIncentiveMinMantissa); + require (err == uint(Error.NO_ERROR), "set liquidation incentive error"); + } + } + + /** + * @dev Check that caller is admin or this contract is initializing itself as + * the new implementation. + * There should be no way to satisfy msg.sender == comptrollerImplementaiton + * without tx.origin also being admin, but both are included for extra safety + */ + function adminOrInitializing() internal view returns (bool) { + bool initializing = ( + msg.sender == comptrollerImplementation + && + //solium-disable-next-line security/no-tx-origin + tx.origin == admin + ); + bool isAdmin = msg.sender == admin; + return isAdmin || initializing; + } +} diff --git a/contracts/ComptrollerInterface.sol b/contracts/ComptrollerInterface.sol new file mode 100644 index 000000000..255fb922b --- /dev/null +++ b/contracts/ComptrollerInterface.sol @@ -0,0 +1,75 @@ +pragma solidity ^0.5.8; + +interface ComptrollerInterface { + /** + * @notice Marker function used for light validation when updating the comptroller of a market + * @dev Implementations should simply return true. + * @return true + */ + function isComptroller() external view returns (bool); + + /*** Assets You Are In ***/ + + function enterMarkets(address[] calldata cTokens) external returns (uint[] memory); + function exitMarket(address cToken) external returns (uint); + + /*** Policy Hooks ***/ + + function mintAllowed(address cToken, address minter, uint mintAmount) external returns (uint); + function mintVerify(address cToken, address minter, uint mintAmount, uint mintTokens) external; + + function redeemAllowed(address cToken, address redeemer, uint redeemTokens) external returns (uint); + function redeemVerify(address cToken, address redeemer, uint redeemAmount, uint redeemTokens) external; + + function borrowAllowed(address cToken, address borrower, uint borrowAmount) external returns (uint); + function borrowVerify(address cToken, address borrower, uint borrowAmount) external; + + function repayBorrowAllowed( + address cToken, + address payer, + address borrower, + uint repayAmount) external returns (uint); + function repayBorrowVerify( + address cToken, + address payer, + address borrower, + uint repayAmount, + uint borrowerIndex) external; + + function liquidateBorrowAllowed( + address cTokenBorrowed, + address cTokenCollateral, + address liquidator, + address borrower, + uint repayAmount) external returns (uint); + function liquidateBorrowVerify( + address cTokenBorrowed, + address cTokenCollateral, + address liquidator, + address borrower, + uint repayAmount, + uint seizeTokens) external; + + function seizeAllowed( + address cTokenCollateral, + address cTokenBorrowed, + address liquidator, + address borrower, + uint seizeTokens) external returns (uint); + function seizeVerify( + address cTokenCollateral, + address cTokenBorrowed, + address liquidator, + address borrower, + uint seizeTokens) external; + + function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint); + function transferVerify(address cToken, address src, address dst, uint transferTokens) external; + + /*** Liquidity/Liquidation Calculations ***/ + + function liquidateCalculateSeizeTokens( + address cTokenBorrowed, + address cTokenCollateral, + uint repayAmount) external view returns (uint, uint); +} diff --git a/contracts/ComptrollerStorage.sol b/contracts/ComptrollerStorage.sol new file mode 100644 index 000000000..1218d3729 --- /dev/null +++ b/contracts/ComptrollerStorage.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.5.8; + +import "./CToken.sol"; +import "./PriceOracle.sol"; + +contract UnitrollerAdminStorage { + /** + * @notice Administrator for this contract + */ + address public admin; + + /** + * @notice Pending administrator for this contract + */ + address public pendingAdmin; + + /** + * @notice Active brains of Unitroller + */ + address public comptrollerImplementation; + + /** + * @notice Pending brains of Unitroller + */ + address public pendingComptrollerImplementation; +} + +contract ComptrollerV1Storage is UnitrollerAdminStorage { + + /** + * @notice Oracle which gives the price of any given asset + */ + PriceOracle public oracle; + + /** + * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow + */ + uint public closeFactorMantissa; + + /** + * @notice Multiplier representing the discount on collateral that a liquidator receives + */ + uint public liquidationIncentiveMantissa; + + /** + * @notice Max number of assets a single account can participate in (borrow or use as collateral) + */ + uint public maxAssets; + + /** + * @notice Per-account mapping of "assets you are in", capped by maxAssets + */ + mapping(address => CToken[]) public accountAssets; + +} diff --git a/contracts/EIP20Interface.sol b/contracts/EIP20Interface.sol new file mode 100644 index 000000000..522e17b5f --- /dev/null +++ b/contracts/EIP20Interface.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.5.8; + +/** + * @title ERC 20 Token Standard Interface + * https://eips.ethereum.org/EIPS/eip-20 + */ +interface EIP20Interface { + + /** + * @notice Get the total number of tokens in circulation + * @return The supply of tokens + */ + function totalSupply() external view returns (uint256); + + /** + * @notice Gets the balance of the specified address + * @param owner The address from which the balance will be retrieved + * @return The balance + */ + function balanceOf(address owner) external view returns (uint256 balance); + + /** + * @notice Transfer `amount` tokens from `msg.sender` to `dst` + * @param dst The address of the destination account + * @param amount The number of tokens to transfer + * @return Whether or not the transfer succeeded + */ + function transfer(address dst, uint256 amount) external returns (bool success); + + /** + * @notice Transfer `amount` tokens from `src` to `dst` + * @param src The address of the source account + * @param dst The address of the destination account + * @param amount The number of tokens to transfer + * @return Whether or not the transfer succeeded + */ + function transferFrom(address src, address dst, uint256 amount) external returns (bool success); + + /** + * @notice Approve `spender` to transfer up to `amount` from `src` + * @dev This will overwrite the approval amount for `spender` + * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) + * @param spender The address of the account which may transfer tokens + * @param amount The number of tokens that are approved (-1 means infinite) + * @return Whether or not the approval succeeded + */ + function approve(address spender, uint256 amount) external returns (bool success); + + /** + * @notice Get the current allowance from `owner` for `spender` + * @param owner The address of the account which owns the tokens to be spent + * @param spender The address of the account which may transfer tokens + * @return The number of tokens allowed to be spent (-1 means infinite) + */ + function allowance(address owner, address spender) external view returns (uint256 remaining); + + event Transfer(address indexed from, address indexed to, uint256 amount); + event Approval(address indexed owner, address indexed spender, uint256 amount); +} diff --git a/contracts/EIP20NonStandardInterface.sol b/contracts/EIP20NonStandardInterface.sol new file mode 100644 index 000000000..1abbcb4c8 --- /dev/null +++ b/contracts/EIP20NonStandardInterface.sol @@ -0,0 +1,70 @@ +pragma solidity ^0.5.8; + +/** + * @title EIP20NonStandardInterface + * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` + * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ +interface EIP20NonStandardInterface { + + /** + * @notice Get the total number of tokens in circulation + * @return The supply of tokens + */ + function totalSupply() external view returns (uint256); + + /** + * @notice Gets the balance of the specified address + * @param owner The address from which the balance will be retrieved + * @return The balance + */ + function balanceOf(address owner) external view returns (uint256 balance); + + /// + /// !!!!!!!!!!!!!! + /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification + /// !!!!!!!!!!!!!! + /// + + /** + * @notice Transfer `amount` tokens from `msg.sender` to `dst` + * @param dst The address of the destination account + * @param amount The number of tokens to transfer + */ + function transfer(address dst, uint256 amount) external; + + /// + /// !!!!!!!!!!!!!! + /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification + /// !!!!!!!!!!!!!! + /// + + /** + * @notice Transfer `amount` tokens from `src` to `dst` + * @param src The address of the source account + * @param dst The address of the destination account + * @param amount The number of tokens to transfer + */ + function transferFrom(address src, address dst, uint256 amount) external; + + /** + * @notice Approve `spender` to transfer up to `amount` from `src` + * @dev This will overwrite the approval amount for `spender` + * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) + * @param spender The address of the account which may transfer tokens + * @param amount The number of tokens that are approved + * @return Whether or not the approval succeeded + */ + function approve(address spender, uint256 amount) external returns (bool success); + + /** + * @notice Get the current allowance from `owner` for `spender` + * @param owner The address of the account which owns the tokens to be spent + * @param spender The address of the account which may transfer tokens + * @return The number of tokens allowed to be spent + */ + function allowance(address owner, address spender) external view returns (uint256 remaining); + + event Transfer(address indexed from, address indexed to, uint256 amount); + event Approval(address indexed owner, address indexed spender, uint256 amount); +} diff --git a/contracts/ErrorReporter.sol b/contracts/ErrorReporter.sol new file mode 100644 index 000000000..ab646813f --- /dev/null +++ b/contracts/ErrorReporter.sol @@ -0,0 +1,204 @@ +pragma solidity ^0.5.8; + +contract ComptrollerErrorReporter { + enum Error { + NO_ERROR, + UNAUTHORIZED, + COMPTROLLER_MISMATCH, + INSUFFICIENT_SHORTFALL, + INSUFFICIENT_LIQUIDITY, + INVALID_CLOSE_FACTOR, + INVALID_COLLATERAL_FACTOR, + INVALID_LIQUIDATION_INCENTIVE, + MARKET_NOT_ENTERED, + MARKET_NOT_LISTED, + MARKET_ALREADY_LISTED, + MATH_ERROR, + NONZERO_BORROW_BALANCE, + PRICE_ERROR, + REJECTION, + SNAPSHOT_ERROR, + TOO_MANY_ASSETS, + TOO_MUCH_REPAY + } + + enum FailureInfo { + ACCEPT_ADMIN_PENDING_ADMIN_CHECK, + ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK, + EXIT_MARKET_BALANCE_OWED, + EXIT_MARKET_REJECTION, + SET_CLOSE_FACTOR_OWNER_CHECK, + SET_CLOSE_FACTOR_VALIDATION, + SET_COLLATERAL_FACTOR_OWNER_CHECK, + SET_COLLATERAL_FACTOR_NO_EXISTS, + SET_COLLATERAL_FACTOR_VALIDATION, + SET_COLLATERAL_FACTOR_WITHOUT_PRICE, + SET_IMPLEMENTATION_OWNER_CHECK, + SET_LIQUIDATION_INCENTIVE_OWNER_CHECK, + SET_LIQUIDATION_INCENTIVE_VALIDATION, + SET_MAX_ASSETS_OWNER_CHECK, + SET_PENDING_ADMIN_OWNER_CHECK, + SET_PENDING_IMPLEMENTATION_OWNER_CHECK, + SET_PRICE_ORACLE_OWNER_CHECK, + SUPPORT_MARKET_EXISTS, + SUPPORT_MARKET_OWNER_CHECK, + ZUNUSED + } + + /** + * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary + * contract-specific code that enables us to report opaque error codes from upgradeable contracts. + **/ + event Failure(uint error, uint info, uint detail); + + /** + * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator + */ + function fail(Error err, FailureInfo info) internal returns (uint) { + emit Failure(uint(err), uint(info), 0); + + return uint(err); + } + + /** + * @dev use this when reporting an opaque error from an upgradeable collaborator contract + */ + function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { + emit Failure(uint(err), uint(info), opaqueError); + + return uint(err); + } +} + +contract TokenErrorReporter { + enum Error { + NO_ERROR, + UNAUTHORIZED, + BAD_INPUT, + COMPTROLLER_REJECTION, + COMPTROLLER_CALCULATION_ERROR, + INTEREST_RATE_MODEL_ERROR, + INVALID_ACCOUNT_PAIR, + INVALID_CLOSE_AMOUNT_REQUESTED, + INVALID_COLLATERAL_FACTOR, + MATH_ERROR, + MARKET_NOT_FRESH, + MARKET_NOT_LISTED, + TOKEN_INSUFFICIENT_ALLOWANCE, + TOKEN_INSUFFICIENT_BALANCE, + TOKEN_INSUFFICIENT_CASH, + TOKEN_TRANSFER_IN_FAILED, + TOKEN_TRANSFER_OUT_FAILED + } + + /* + * Note: FailureInfo (but not Error) is kept in alphabetical order + * This is because FailureInfo grows significantly faster, and + * the order of Error has some meaning, while the order of FailureInfo + * is entirely arbitrary. + */ + enum FailureInfo { + ACCEPT_ADMIN_PENDING_ADMIN_CHECK, + ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED, + ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED, + ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, + ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, + ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED, + ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED, + BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, + BORROW_ACCRUE_INTEREST_FAILED, + BORROW_CASH_NOT_AVAILABLE, + BORROW_FRESHNESS_CHECK, + BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, + BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, + BORROW_MARKET_NOT_LISTED, + BORROW_COMPTROLLER_REJECTION, + LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED, + LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED, + LIQUIDATE_COLLATERAL_FRESHNESS_CHECK, + LIQUIDATE_COMPTROLLER_REJECTION, + LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED, + LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX, + LIQUIDATE_CLOSE_AMOUNT_IS_ZERO, + LIQUIDATE_FRESHNESS_CHECK, + LIQUIDATE_LIQUIDATOR_IS_BORROWER, + LIQUIDATE_REPAY_BORROW_FRESH_FAILED, + LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, + LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, + LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, + LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER, + LIQUIDATE_SEIZE_TOO_MUCH, + MINT_ACCRUE_INTEREST_FAILED, + MINT_COMPTROLLER_REJECTION, + MINT_EXCHANGE_CALCULATION_FAILED, + MINT_EXCHANGE_RATE_READ_FAILED, + MINT_FRESHNESS_CHECK, + MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, + MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, + MINT_TRANSFER_IN_FAILED, + MINT_TRANSFER_IN_NOT_POSSIBLE, + REDEEM_ACCRUE_INTEREST_FAILED, + REDEEM_COMPTROLLER_REJECTION, + REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, + REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, + REDEEM_EXCHANGE_RATE_READ_FAILED, + REDEEM_FRESHNESS_CHECK, + REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, + REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, + REDEEM_TRANSFER_OUT_NOT_POSSIBLE, + REDUCE_RESERVES_ACCRUE_INTEREST_FAILED, + REDUCE_RESERVES_ADMIN_CHECK, + REDUCE_RESERVES_CASH_NOT_AVAILABLE, + REDUCE_RESERVES_FRESH_CHECK, + REDUCE_RESERVES_VALIDATION, + REPAY_BEHALF_ACCRUE_INTEREST_FAILED, + REPAY_BORROW_ACCRUE_INTEREST_FAILED, + REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, + REPAY_BORROW_COMPTROLLER_REJECTION, + REPAY_BORROW_FRESHNESS_CHECK, + REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED, + REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, + REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE, + SET_COLLATERAL_FACTOR_OWNER_CHECK, + SET_COLLATERAL_FACTOR_VALIDATION, + SET_COMPTROLLER_OWNER_CHECK, + SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED, + SET_INTEREST_RATE_MODEL_FRESH_CHECK, + SET_INTEREST_RATE_MODEL_OWNER_CHECK, + SET_MAX_ASSETS_OWNER_CHECK, + SET_ORACLE_MARKET_NOT_LISTED, + SET_PENDING_ADMIN_OWNER_CHECK, + SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED, + SET_RESERVE_FACTOR_ADMIN_CHECK, + SET_RESERVE_FACTOR_FRESH_CHECK, + SET_RESERVE_FACTOR_BOUNDS_CHECK, + TRANSFER_COMPTROLLER_REJECTION, + TRANSFER_NOT_ALLOWED, + TRANSFER_NOT_ENOUGH, + TRANSFER_TOO_MUCH + } + + /** + * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary + * contract-specific code that enables us to report opaque error codes from upgradeable contracts. + **/ + event Failure(uint error, uint info, uint detail); + + /** + * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator + */ + function fail(Error err, FailureInfo info) internal returns (uint) { + emit Failure(uint(err), uint(info), 0); + + return uint(err); + } + + /** + * @dev use this when reporting an opaque error from an upgradeable collaborator contract + */ + function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) { + emit Failure(uint(err), uint(info), opaqueError); + + return uint(err); + } +} diff --git a/contracts/Exponential.sol b/contracts/Exponential.sol new file mode 100644 index 000000000..4320ca01d --- /dev/null +++ b/contracts/Exponential.sol @@ -0,0 +1,226 @@ +pragma solidity ^0.5.8; + +import "./CarefulMath.sol"; + +/** + * @title Exponential module for storing fixed-decision decimals + * @author Compound + * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. + * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: + * `Exp({mantissa: 5100000000000000000})`. + */ +contract Exponential is CarefulMath { + uint constant expScale = 1e18; + uint constant halfExpScale = expScale/2; + uint constant mantissaOne = expScale; + + struct Exp { + uint mantissa; + } + + /** + * @dev Creates an exponential from numerator and denominator values. + * Note: Returns an error if (`num` * 10e18) > MAX_INT, + * or if `denom` is zero. + */ + function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) { + (MathError err0, uint scaledNumerator) = mulUInt(num, expScale); + if (err0 != MathError.NO_ERROR) { + return (err0, Exp({mantissa: 0})); + } + + (MathError err1, uint rational) = divUInt(scaledNumerator, denom); + if (err1 != MathError.NO_ERROR) { + return (err1, Exp({mantissa: 0})); + } + + return (MathError.NO_ERROR, Exp({mantissa: rational})); + } + + /** + * @dev Adds two exponentials, returning a new exponential. + */ + function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { + (MathError error, uint result) = addUInt(a.mantissa, b.mantissa); + + return (error, Exp({mantissa: result})); + } + + /** + * @dev Subtracts two exponentials, returning a new exponential. + */ + function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { + (MathError error, uint result) = subUInt(a.mantissa, b.mantissa); + + return (error, Exp({mantissa: result})); + } + + /** + * @dev Multiply an Exp by a scalar, returning a new Exp. + */ + function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { + (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar); + if (err0 != MathError.NO_ERROR) { + return (err0, Exp({mantissa: 0})); + } + + return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa})); + } + + /** + * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. + */ + function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) { + (MathError err, Exp memory product) = mulScalar(a, scalar); + if (err != MathError.NO_ERROR) { + return (err, 0); + } + + return (MathError.NO_ERROR, truncate(product)); + } + + /** + * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. + */ + function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) { + (MathError err, Exp memory product) = mulScalar(a, scalar); + if (err != MathError.NO_ERROR) { + return (err, 0); + } + + return addUInt(truncate(product), addend); + } + + /** + * @dev Divide an Exp by a scalar, returning a new Exp. + */ + function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { + (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar); + if (err0 != MathError.NO_ERROR) { + return (err0, Exp({mantissa: 0})); + } + + return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa})); + } + + /** + * @dev Divide a scalar by an Exp, returning a new Exp. + */ + function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) { + /* + We are doing this as: + getExp(mulUInt(expScale, scalar), divisor.mantissa) + + How it works: + Exp = a / b; + Scalar = s; + `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale` + */ + (MathError err0, uint numerator) = mulUInt(expScale, scalar); + if (err0 != MathError.NO_ERROR) { + return (err0, Exp({mantissa: 0})); + } + return getExp(numerator, divisor.mantissa); + } + + /** + * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer. + */ + function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) { + (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor); + if (err != MathError.NO_ERROR) { + return (err, 0); + } + + return (MathError.NO_ERROR, truncate(fraction)); + } + + /** + * @dev Multiplies two exponentials, returning a new exponential. + */ + function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { + + (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa); + if (err0 != MathError.NO_ERROR) { + return (err0, Exp({mantissa: 0})); + } + + // We add half the scale before dividing so that we get rounding instead of truncation. + // See "Listing 6" and text above it at https://accu.org/index.php/journals/1717 + // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18. + (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct); + if (err1 != MathError.NO_ERROR) { + return (err1, Exp({mantissa: 0})); + } + + (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale); + // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero. + assert(err2 == MathError.NO_ERROR); + + return (MathError.NO_ERROR, Exp({mantissa: product})); + } + + /** + * @dev Multiplies two exponentials given their mantissas, returning a new exponential. + */ + function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) { + return mulExp(Exp({mantissa: a}), Exp({mantissa: b})); + } + + /** + * @dev Multiplies three exponentials, returning a new exponential. + */ + function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) { + (MathError err, Exp memory ab) = mulExp(a, b); + if (err != MathError.NO_ERROR) { + return (err, ab); + } + return mulExp(ab, c); + } + + /** + * @dev Divides two exponentials, returning a new exponential. + * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b, + * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa) + */ + function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { + return getExp(a.mantissa, b.mantissa); + } + + /** + * @dev Truncates the given exp to a whole number value. + * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 + */ + function truncate(Exp memory exp) pure internal returns (uint) { + // Note: We are not using careful math here as we're performing a division that cannot fail + return exp.mantissa / expScale; + } + + /** + * @dev Checks if first Exp is less than second Exp. + */ + function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { + return left.mantissa < right.mantissa; //TODO: Add some simple tests and this in another PR yo. + } + + /** + * @dev Checks if left Exp <= right Exp. + */ + function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) { + return left.mantissa <= right.mantissa; + } + + /** + * @dev Checks if left Exp > right Exp. + */ + function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { + return left.mantissa > right.mantissa; + } + + /** + * @dev returns true if Exp is exactly zero + */ + function isZeroExp(Exp memory value) pure internal returns (bool) { + return value.mantissa == 0; + } +} diff --git a/contracts/InterestRateModel.sol b/contracts/InterestRateModel.sol new file mode 100644 index 000000000..8ab34b586 --- /dev/null +++ b/contracts/InterestRateModel.sol @@ -0,0 +1,29 @@ +pragma solidity ^0.5.8; + +/** + * @title The Compound InterestRateModel Interface + * @author Compound + * @notice Any interest rate model should derive from this contract. + * @dev These functions are specifically not marked `pure` as implementations of this + * contract may read from storage variables. + */ +interface InterestRateModel { + /** + * @notice Gets the current borrow interest rate based on the given asset, total cash, total borrows + * and total reserves. + * @dev The return value should be scaled by 1e18, thus a return value of + * `(true, 1000000000000)` implies an interest rate of 0.000001 or 0.0001% *per block*. + * @param cash The total cash of the underlying asset in the CToken + * @param borrows The total borrows of the underlying asset in the CToken + * @param reserves The total reserves of the underlying asset in the CToken + * @return Success or failure and the borrow interest rate per block scaled by 10e18 + */ + function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint, uint); + + /** + * @notice Marker function used for light validation when updating the interest rate model of a market + * @dev Marker function used for light validation when updating the interest rate model of a market. Implementations should simply return true. + * @return Success or failure + */ + function isInterestRateModel() external view returns (bool); +} \ No newline at end of file diff --git a/contracts/Maximillion.sol b/contracts/Maximillion.sol new file mode 100644 index 000000000..cfca4b2aa --- /dev/null +++ b/contracts/Maximillion.sol @@ -0,0 +1,49 @@ +pragma solidity ^0.5.8; + +import "./CEther.sol"; + +/** + * @title Compound's Maximillion Contract + * @author Compound + */ +contract Maximillion { + /** + * @notice The default cEther market to repay in + */ + CEther public cEther; + + /** + * @notice Construct a Maximillion to repay max in a CEther market + */ + constructor(CEther cEther_) public { + cEther = cEther_; + } + + /** + * @notice msg.sender sends Ether to repay an account's borrow in the cEther market + * @dev The provided Ether is applied towards the borrow balance, any excess is refunded + * @param borrower The address of the borrower account to repay on behalf of + * @return The initial borrows before the repay + */ + function repayBehalf(address borrower) public payable { + return repayBehalfExplicit(borrower, cEther); + } + + /** + * @notice msg.sender sends Ether to repay an account's borrow in a cEther market + * @dev The provided Ether is applied towards the borrow balance, any excess is refunded + * @param borrower The address of the borrower account to repay on behalf of + * @param cEther_ The address of the cEther contract to repay in + * @return The initial borrows before the repay + */ + function repayBehalfExplicit(address borrower, CEther cEther_) public payable { + uint received = msg.value; + uint borrows = cEther_.borrowBalanceCurrent(borrower); + if (received > borrows) { + cEther_.repayBorrowBehalf.value(borrows)(borrower); + msg.sender.transfer(received - borrows); + } else { + cEther_.repayBorrowBehalf.value(received)(borrower); + } + } +} diff --git a/contracts/PriceOracle.sol b/contracts/PriceOracle.sol new file mode 100644 index 000000000..6fbcb1ab4 --- /dev/null +++ b/contracts/PriceOracle.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.8; + +import "./CToken.sol"; + +interface PriceOracle { + /** + * @notice Indicator that this is a PriceOracle contract (for inspection) + */ + function isPriceOracle() external pure returns (bool); + + /** + * @notice Get the underlying price of a cToken asset + * @param cToken The cToken to get the underlying price of + * @return The underlying asset price mantissa (scaled by 1e18). + * Zero means the price is unavailable. + */ + function getUnderlyingPrice(CToken cToken) external view returns (uint); +} diff --git a/contracts/PriceOracleProxy.sol b/contracts/PriceOracleProxy.sol new file mode 100644 index 000000000..a506673e6 --- /dev/null +++ b/contracts/PriceOracleProxy.sol @@ -0,0 +1,88 @@ +pragma solidity ^0.5.8; + +import "./CErc20.sol"; +import "./CToken.sol"; +import "./PriceOracle.sol"; +import "./Comptroller.sol"; + +interface V1PriceOracleInterface { + function assetPrices(address asset) external view returns (uint); +} + +contract PriceOracleProxy is PriceOracle { + /** + * @notice The v1 price oracle, which will continue to serve prices + * prices for v1 assets + */ + V1PriceOracleInterface public v1PriceOracle; + + /** + * @notice The active comptroller, which will be checked for listing status + * to short circuit and return 0 for unlisted assets. + * + * @dev Listed markets are not part of the comptroller interface used by + * cTokens, so we assumena an instance of v1 comptroller.sol instead + */ + Comptroller public comptroller; + + /** + * @notice address of the cEther contract, which has a constant price + */ + address public cEtherAddress; + + /** + * @notice address of the cUSDC contract, which we hand pick a key for + */ + address public cUsdcAddress; + + /** + * @notice address of the USDC contract, which we hand pick a key for + */ + address constant usdcOracleKey = address(1); + + /** + * @notice Indicator that this is a PriceOracle contract (for inspection) + */ + bool public constant isPriceOracle = true; + + /** + * @param comptroller_ The address of the active comptroller, which will + * be consulted for market listing status. + * @param v1PriceOracle_ The address of the v1 price oracle, which will + * continue to operate and hold prices for collateral assets. + * @param cEtherAddress_ The address of the cEther contract, which will + * return a constant 1e18, since all prices relative to ether + */ + constructor(address comptroller_, address v1PriceOracle_, address cEtherAddress_, address cUsdcAddress_) public { + comptroller = Comptroller(comptroller_); + v1PriceOracle = V1PriceOracleInterface(v1PriceOracle_); + cEtherAddress = cEtherAddress_; + cUsdcAddress = cUsdcAddress_; + } + + /** + * @notice Get the underlying price of a listed cToken asset + * @param cToken The cToken to get the underlying price of + * @return The underlying asset price mantissa (scaled by 1e18). + * Zero means the price is unavailable. + */ + function getUnderlyingPrice(CToken cToken) public view returns (uint) { + address cTokenAddress = address(cToken); + (bool isListed, ) = comptroller.markets(cTokenAddress); + + if (!isListed) { + // not listed, worthless + return 0; + } else if (cTokenAddress == cEtherAddress) { + // ether always worth 1 + return 1e18; + } else if (cTokenAddress == cUsdcAddress) { + // read from hand picked key + return v1PriceOracle.assetPrices(usdcOracleKey); + } else { + // read from v1 oracle + address underlying = CErc20(cTokenAddress).underlying(); + return v1PriceOracle.assetPrices(underlying); + } + } +} diff --git a/contracts/ReentrancyGuard.sol b/contracts/ReentrancyGuard.sol new file mode 100644 index 000000000..6bf885d0f --- /dev/null +++ b/contracts/ReentrancyGuard.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.5.8; + +/** + * @title Helps contracts guard against reentrancy attacks. + * @author Remco Bloemen , Eenae + * @dev If you mark a function `nonReentrant`, you should also + * mark it `external`. + */ +contract ReentrancyGuard { + /// @dev counter to allow mutex lock with only one SSTORE operation + uint256 private _guardCounter; + + constructor () internal { + // The counter starts at one to prevent changing it from zero to a non-zero + // value, which is a more expensive operation. + _guardCounter = 1; + } + + /** + * @dev Prevents a contract from calling itself, directly or indirectly. + * Calling a `nonReentrant` function from another `nonReentrant` + * function is not supported. It is possible to prevent this from happening + * by making the `nonReentrant` function external, and make it call a + * `private` function that does the actual work. + */ + modifier nonReentrant() { + _guardCounter += 1; + uint256 localCounter = _guardCounter; + _; + require(localCounter == _guardCounter, "re-entered"); + } +} diff --git a/contracts/SimplePriceOracle.sol b/contracts/SimplePriceOracle.sol new file mode 100644 index 000000000..afe627a9f --- /dev/null +++ b/contracts/SimplePriceOracle.sol @@ -0,0 +1,26 @@ +pragma solidity ^0.5.8; + +import "./PriceOracle.sol"; +import "./CErc20.sol"; + +contract SimplePriceOracle is PriceOracle { + mapping(address => uint) prices; + bool public constant isPriceOracle = true; + + function getUnderlyingPrice(CToken cToken) public view returns (uint) { + return prices[address(CErc20(address(cToken)).underlying())]; + } + + function setUnderlyingPrice(CToken cToken, uint underlyingPriceMantissa) public { + prices[address(CErc20(address(cToken)).underlying())] = underlyingPriceMantissa; + } + + function setDirectPrice(address a, uint price) public { + prices[a] = price; + } + + // v1 price oracle interface for use as backing of proxy + function assetPrices(address asset) external view returns (uint) { + return prices[asset]; + } +} diff --git a/contracts/Unitroller.sol b/contracts/Unitroller.sol new file mode 100644 index 000000000..1bb0d7368 --- /dev/null +++ b/contracts/Unitroller.sol @@ -0,0 +1,152 @@ +pragma solidity ^0.5.8; + +import "./ErrorReporter.sol"; +import "./ComptrollerStorage.sol"; +/** + * @title ComptrollerCore + * @dev storage for the comptroller will be at this address, and + * cTokens should reference this contract rather than a deployed implementation if + * + */ +contract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter { + + /** + * @notice Emitted when pendingComptrollerImplementation is changed + */ + event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation); + + /** + * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated + */ + event NewImplementation(address oldImplementation, address newImplementation); + + /** + * @notice Emitted when pendingAdmin is changed + */ + event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); + + /** + * @notice Emitted when pendingAdmin is accepted, which means admin is updated + */ + event NewAdmin(address oldAdmin, address newAdmin); + + constructor() public { + // Set admin to caller + admin = msg.sender; + } + + /*** Admin Functions ***/ + function _setPendingImplementation(address newPendingImplementation) public returns (uint) { + + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK); + } + + address oldPendingImplementation = pendingComptrollerImplementation; + + pendingComptrollerImplementation = newPendingImplementation; + + emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation + * @dev Admin function for new implementation to accept it's role as implementation + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _acceptImplementation() public returns (uint) { + // Check caller is pendingImplementation and pendingImplementation ≠ address(0) + if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) { + return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK); + } + + // Save current values for inclusion in log + address oldImplementation = comptrollerImplementation; + address oldPendingImplementation = pendingComptrollerImplementation; + + comptrollerImplementation = pendingComptrollerImplementation; + + pendingComptrollerImplementation = address(0); + + emit NewImplementation(oldImplementation, comptrollerImplementation); + emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation); + + return uint(Error.NO_ERROR); + } + + + /** + * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. + * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer. + * @param newPendingAdmin New pending admin. + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + * + * TODO: Should we add a second arg to verify, like a checksum of `newAdmin` address? + */ + function _setPendingAdmin(address newPendingAdmin) public returns (uint) { + // Check caller = admin + if (msg.sender != admin) { + return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK); + } + + // Save current value, if any, for inclusion in log + address oldPendingAdmin = pendingAdmin; + + // Store pendingAdmin with value newPendingAdmin + pendingAdmin = newPendingAdmin; + + // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin) + emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin); + + return uint(Error.NO_ERROR); + } + + /** + * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin + * @dev Admin function for pending admin to accept role and update admin + * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details) + */ + function _acceptAdmin() public returns (uint) { + // Check caller is pendingAdmin and pendingAdmin ≠ address(0) + if (msg.sender != pendingAdmin || msg.sender == address(0)) { + return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK); + } + + // Save current values for inclusion in log + address oldAdmin = admin; + address oldPendingAdmin = pendingAdmin; + + // Store admin with value pendingAdmin + admin = pendingAdmin; + + // Clear the pending value + pendingAdmin = address(0); + + emit NewAdmin(oldAdmin, admin); + emit NewPendingAdmin(oldPendingAdmin, pendingAdmin); + + return uint(Error.NO_ERROR); + } + + /** + * @dev Delegates execution to an implementation contract. + * It returns to the external caller whatever the implementation returns + * or forwards reverts. + */ + function () payable external { + // delegate all other functions to current implementation + (bool success, ) = comptrollerImplementation.delegatecall(msg.data); + + // solium-disable-next-line security/no-inline-assembly + assembly { + let free_mem_ptr := mload(0x40) + returndatacopy(free_mem_ptr, 0, returndatasize) + + switch success + case 0 { revert(free_mem_ptr, returndatasize) } + default { return(free_mem_ptr, returndatasize) } + } + } +} diff --git a/contracts/WhitePaperInterestRateModel.sol b/contracts/WhitePaperInterestRateModel.sol new file mode 100644 index 000000000..7a7c5b464 --- /dev/null +++ b/contracts/WhitePaperInterestRateModel.sol @@ -0,0 +1,133 @@ +pragma solidity ^0.5.8; + +import "./Exponential.sol"; +import "./InterestRateModel.sol"; + +/** + * @title The Compound Standard Interest Rate Model with pluggable constants + * @author Compound + * @notice See Section 2.4 of the Compound Whitepaper + */ +contract WhitePaperInterestRateModel is InterestRateModel, Exponential { + /** + * @notice Indicator that this is an InterestRateModel contract (for inspection) + */ + bool public constant isInterestRateModel = true; + + /** + * @notice The multiplier of utilization rate that gives the slope of the interest rate + */ + uint public multiplier; + + /** + * @notice The base interest rate which is the y-intercept when utilization rate is 0 + */ + uint public baseRate; + + /** + * @notice The approximate number of blocks per year that is assumed by the interest rate model + */ + uint public constant blocksPerYear = 2102400; + + constructor(uint baseRate_, uint multiplier_) public { + baseRate = baseRate_; + multiplier = multiplier_; + } + + enum IRError { + NO_ERROR, + FAILED_TO_ADD_CASH_PLUS_BORROWS, + FAILED_TO_GET_EXP, + FAILED_TO_MUL_UTILIZATION_RATE, + FAILED_TO_ADD_BASE_RATE + } + + /* + * @dev Calculates the utilization rate (borrows / (cash + borrows)) as an Exp + */ + function getUtilizationRate(uint cash, uint borrows) pure internal returns (IRError, Exp memory) { + if (borrows == 0) { + // Utilization rate is zero when there's no borrows + return (IRError.NO_ERROR, Exp({mantissa: 0})); + } + + (MathError err0, uint cashPlusBorrows) = addUInt(cash, borrows); + if (err0 != MathError.NO_ERROR) { + return (IRError.FAILED_TO_ADD_CASH_PLUS_BORROWS, Exp({mantissa: 0})); + } + + (MathError err1, Exp memory utilizationRate) = getExp(borrows, cashPlusBorrows); + if (err1 != MathError.NO_ERROR) { + return (IRError.FAILED_TO_GET_EXP, Exp({mantissa: 0})); + } + + return (IRError.NO_ERROR, utilizationRate); + } + + /* + * @dev Calculates the utilization and borrow rates for use by getBorrowRate function + */ + function getUtilizationAndAnnualBorrowRate(uint cash, uint borrows) view internal returns (IRError, Exp memory, Exp memory) { + (IRError err0, Exp memory utilizationRate) = getUtilizationRate(cash, borrows); + if (err0 != IRError.NO_ERROR) { + return (err0, Exp({mantissa: 0}), Exp({mantissa: 0})); + } + + // Borrow Rate is 5% + UtilizationRate * 45% (baseRate + UtilizationRate * multiplier); + // 45% of utilizationRate, is `rate * 45 / 100` + (MathError err1, Exp memory utilizationRateMuled) = mulScalar(utilizationRate, multiplier); + // `mulScalar` only overflows when the product is >= 2^256. + // utilizationRate is a real number on the interval [0,1], which means that + // utilizationRate.mantissa is in the interval [0e18,1e18], which means that 45 times + // that is in the interval [0e18,45e18]. That interval has no intersection with 2^256, and therefore + // this can never overflow for the standard rates. + if (err1 != MathError.NO_ERROR) { + return (IRError.FAILED_TO_MUL_UTILIZATION_RATE, Exp({mantissa: 0}), Exp({mantissa: 0})); + } + + (MathError err2, Exp memory utilizationRateScaled) = divScalar(utilizationRateMuled, mantissaOne); + // 100 is a constant, and therefore cannot be zero, which is the only error case of divScalar. + assert(err2 == MathError.NO_ERROR); + + // Add the 5% for (5% + 45% * Ua) + (MathError err3, Exp memory annualBorrowRate) = addExp(utilizationRateScaled, Exp({mantissa: baseRate})); + // `addExp` only fails when the addition of mantissas overflow. + // As per above, utilizationRateMuled is capped at 45e18, + // and utilizationRateScaled is capped at 4.5e17. mantissaFivePercent = 0.5e17, and thus the addition + // is capped at 5e17, which is less than 2^256. This only applies to the standard rates + if (err3 != MathError.NO_ERROR) { + return (IRError.FAILED_TO_ADD_BASE_RATE, Exp({mantissa: 0}), Exp({mantissa: 0})); + } + + return (IRError.NO_ERROR, utilizationRate, annualBorrowRate); + } + + /** + * @notice Gets the current borrow interest rate based on the given asset, total cash, total borrows + * and total reserves. + * @dev The return value should be scaled by 1e18, thus a return value of + * `(true, 1000000000000)` implies an interest rate of 0.000001 or 0.0001% *per block*. + * @param cash The total cash of the underlying asset in the CToken + * @param borrows The total borrows of the underlying asset in the CToken + * @param _reserves The total reserves of the underlying asset in the CToken + * @return Success or failure and the borrow interest rate per block scaled by 10e18 + */ + function getBorrowRate(uint cash, uint borrows, uint _reserves) public view returns (uint, uint) { + _reserves; // pragma ignore unused argument + + (IRError err0, Exp memory _utilizationRate, Exp memory annualBorrowRate) = getUtilizationAndAnnualBorrowRate(cash, borrows); + if (err0 != IRError.NO_ERROR) { + return (uint(err0), 0); + } + + // And then divide down by blocks per year. + (MathError err1, Exp memory borrowRate) = divScalar(annualBorrowRate, blocksPerYear); // basis points * blocks per year + // divScalar only fails when divisor is zero. This is clearly not the case. + assert(err1 == MathError.NO_ERROR); + + _utilizationRate; // pragma ignore unused variable + + // Note: mantissa is the rate scaled 1e18, which matches the expected result + return (uint(IRError.NO_ERROR), borrowRate.mantissa); + } +} diff --git a/docs/CompoundProtocol.pdf b/docs/CompoundProtocol.pdf new file mode 100644 index 0000000000000000000000000000000000000000..64daadc53a9855faabee030777b0d34fad679f38 GIT binary patch literal 1324870 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 z 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%0D`X!5*Mk;r<>Y)n>b{nT;vZcl^BeL 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≪@t#>Lc$km09|p^K@gsjwd8x$PmW|kGvEX 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 z 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

e=^uAECG6N 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%0A8g5oZf1 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

Fs2BU`ewIB81dciJ@!%5b&$D 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≦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 literal 0 HcmV?d00001 diff --git a/docs/CompoundWhitepaper.pdf b/docs/CompoundWhitepaper.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6257549486b5017b212b1cfcaff53fc99cbf1daa GIT binary patch literal 192934 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�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 literal 0 HcmV?d00001 diff --git a/migrations/.gitkeep b/migrations/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/networks/.gitkeep b/networks/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/networks/README.md b/networks/README.md new file mode 100644 index 000000000..06c673c15 --- /dev/null +++ b/networks/README.md @@ -0,0 +1,26 @@ +## Network Configuration + +This folder contains the configuration for given networks (e.g. `rinkeby.json` is the configuration for the Rinkeby test-net). These configuration files are meant to be used to configure external applications (like dApps) and thus contain a base set of information that may be useful (such as the address the Comptroller and a list of cToken markets). These configuration files are auto-generated when doing local development. + +Structure +--------- + +```json +{ + "Contracts": { + "MoneyMarket": "0x{address}", + "Migrations": "0x{address}", + "PriceOracle": "0x{address}", + "InterestRateModel": "0x{address}" + }, + "Tokens": { + "{SYM}": { + "name": "{Full Name}", + "symbol": "{SYM}", + "decimals": 18, + "address": "0x{address}", + "supported": true + } + } +} +``` \ No newline at end of file diff --git a/networks/goerli-abi.json b/networks/goerli-abi.json new file mode 100644 index 000000000..1694872a4 --- /dev/null +++ b/networks/goerli-abi.json @@ -0,0 +1,13952 @@ +{ + "ZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cUSDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "PriceOracle": [ + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "underlyingPriceMantissa", + "type": "uint256" + } + ], + "name": "setUnderlyingPrice", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x127ffda0" + }, + { + "constant": true, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "assetPrices", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5e9a523c" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + } + ], + "PriceOracleProxy": [ + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [], + "name": "cEtherAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xde836acf" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + }, + { + "constant": true, + "inputs": [], + "name": "v1PriceOracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe10c98d" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "v1PriceOracle_", + "type": "address" + }, + { + "name": "cEtherAddress_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Maximillion": [ + { + "constant": true, + "inputs": [], + "name": "cEther", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x19b68c00" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cEther_", + "type": "address" + } + ], + "name": "repayBehalfExplicit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x367b7f05" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x9f35c3d5" + }, + { + "inputs": [ + { + "name": "cEther_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cDAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "DAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "StdComptroller": [ + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Unitroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Comptroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "cBAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base0bps_Slope2000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "BAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cETH": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [], + "name": "mint", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x1249c58b" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": false, + "inputs": [], + "name": "repayBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x4e4d9fea" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xaae40a2a" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBorrowBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xe5974619" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base500bps_Slope1200bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Base200bps_Slope3000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cREP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "WBTC": [ + { + "constant": true, + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x05d2035b" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "name": "reclaimToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17ffc320" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [], + "name": "unpause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3f4ba83a" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x40c10f19" + }, + { + "constant": false, + "inputs": [ + { + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x42966c68" + }, + { + "constant": false, + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4e71e0c8" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5c975abb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x715018a6" + }, + { + "constant": false, + "inputs": [], + "name": "finishMinting", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x7d64bcb4" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x8456cb59" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8da5cb5b" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": true, + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe30c3978" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2fde38b" + }, + { + "anonymous": false, + "inputs": [], + "name": "Pause", + "type": "event", + "signature": "0x6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff625" + }, + { + "anonymous": false, + "inputs": [], + "name": "Unpause", + "type": "event", + "signature": "0x7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b33" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "burner", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event", + "signature": "0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885" + }, + { + "anonymous": false, + "inputs": [], + "name": "MintFinished", + "type": "event", + "signature": "0xae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa08" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + } + ], + "name": "OwnershipRenounced", + "type": "event", + "signature": "0xf8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c64820" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event", + "signature": "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "REP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "cWBTC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "USDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ] +} \ No newline at end of file diff --git a/networks/goerli.json b/networks/goerli.json new file mode 100644 index 000000000..2b18cc67a --- /dev/null +++ b/networks/goerli.json @@ -0,0 +1,296 @@ +{ + "Contracts": { + "ZRX": "0x6c041606A9b4A449dF6B5FF7274B79a869616D65", + "cUSDC": "0xD9FFe966A831089981Bd1539503c9d3cb45E5AAb", + "PriceOracle": "0x9f8376931cd4c3c38C0128A77082ba40e8D4a8a1", + "PriceOracleProxy": "0x83047d759094cBc94df2DE8caF33C6C5990eE095", + "Maximillion": "0xcCb206b7b33F46cB0a8e55Bf1f173fe3e8661076", + "cDAI": "0xd9fd9E875c9C1d567825E431DD6Ed4f0e51aA8Bf", + "DAI": "0xB8C5995387c8086d0B496Bd54755d14D7cED8256", + "StdComptroller": "0xC2210dFFE9DE7eA7A7ed933EeE3e28ae6786b9f5", + "Unitroller": "0xe884DcC3167613A5D6A6EF96F90B74E411F32C8a", + "Comptroller": "0xe884DcC3167613A5D6A6EF96F90B74E411F32C8a", + "cBAT": "0xc31211101e6D98bEA24F1f32cbeBa3e9ac7c9749", + "Base0bps_Slope2000bps": "0x23E8731b39E46941f73951b7f39d921bFd6C2E05", + "BAT": "0x3e0d325ABA23E9562281D48b2Bd52594Db48CC18", + "cETH": "0x2B2aA9c7967eFAd4B73BFD8801333928806409A1", + "Base500bps_Slope1200bps": "0x63cFb6469408a64d6713C28231c8d90a609aeB23", + "Base200bps_Slope3000bps": "0x8cD09AF719A93fB3b52a05Dbc4eC0Fa559EEC9C2", + "cREP": "0x0812e50F3740b89899Ce889C2ab913eA2565f626", + "WBTC": "0xFD1853eb1391B094dd9DfAB566d94F8b6400316c", + "REP": "0x4308246f8806135d840c8C81bF658d58c0Fd295C", + "cZRX": "0xf412f4d0eE1D96eb486C6C2836bEDc4912bA294E", + "cWBTC": "0xe43d693C6d063BDF4A9681f9A6D9D1439344f4f7", + "USDC": "0x7Dc9912705FfDb928F62D9694fEfdD3a09F3eCD0" + }, + "Blocks": { + "ZRX": 924883, + "cUSDC": 924929, + "PriceOracle": 924871, + "PriceOracleProxy": 924948, + "Maximillion": 924932, + "cDAI": 924893, + "DAI": 924885, + "StdComptroller": 924875, + "Unitroller": 924873, + "cBAT": 924892, + "Base0bps_Slope2000bps": 924879, + "BAT": 924884, + "cETH": 924895, + "Base500bps_Slope1200bps": 924878, + "Base200bps_Slope3000bps": 924881, + "cREP": 924894, + "WBTC": 924889, + "REP": 924886, + "cZRX": 924891, + "cWBTC": 924931, + "USDC": 924887 + }, + "PriceOracle": { + "description": "Simple Price Oracle", + "address": "0x9f8376931cd4c3c38C0128A77082ba40e8D4a8a1" + }, + "Maximillion": { + "description": "Maximillion", + "cEtherAddress": "0x2B2aA9c7967eFAd4B73BFD8801333928806409A1", + "address": "0xcCb206b7b33F46cB0a8e55Bf1f173fe3e8661076" + }, + "Unitroller": { + "description": "Unitroller", + "address": "0xe884DcC3167613A5D6A6EF96F90B74E411F32C8a" + }, + "Comptroller": { + "StdComptroller": { + "address": "0xC2210dFFE9DE7eA7A7ed933EeE3e28ae6786b9f5", + "contract": "Comptroller", + "description": "Standard Comptroller Impl" + } + }, + "Constructors": { + "ZRX": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002307800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a52580000000000000000000000000000000000000000000000000000000000", + "cUSDC": "0x0000000000000000000000007dc9912705ffdb928f62d9694fefdd3a09f3ecd0000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a00000000000000000000000023e8731b39e46941f73951b7f39d921bfd6c2e050000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000016436f6d706f756e642055534420436f696e20f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000056355534443000000000000000000000000000000000000000000000000000000", + "PriceOracle": "0x", + "PriceOracleProxy": "0x000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a0000000000000000000000009f8376931cd4c3c38c0128a77082ba40e8d4a8a10000000000000000000000002b2aa9c7967efad4b73bfd8801333928806409a1", + "Maximillion": "0x0000000000000000000000002b2aa9c7967efad4b73bfd8801333928806409a1", + "cDAI": "0x000000000000000000000000b8c5995387c8086d0b496bd54755d14d7ced8256000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a00000000000000000000000063cfb6469408a64d6713c28231c8d90a609aeb23000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000011436f6d706f756e642044616920f09f938800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046344414900000000000000000000000000000000000000000000000000000000", + "DAI": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003446169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000", + "StdComptroller": "0x", + "Unitroller": "0x", + "cBAT": "0x0000000000000000000000003e0d325aba23e9562281d48b2bd52594db48cc18000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a0000000000000000000000008cd09af719a93fb3b52a05dbc4ec0fa559eec9c2000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000023436f6d706f756e6420426173696320417474656e74696f6e20546f6b656e20f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046342415400000000000000000000000000000000000000000000000000000000", + "Base0bps_Slope2000bps": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "BAT": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000015426173696320417474656e74696f6e20546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000034241540000000000000000000000000000000000000000000000000000000000", + "cETH": "0x000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a00000000000000000000000023e8731b39e46941f73951b7f39d921bfd6c2e05000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420457468657220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000", + "Base500bps_Slope1200bps": "0x00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000", + "Base200bps_Slope3000bps": "0x00000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000429d069189e0000", + "cREP": "0x0000000000000000000000004308246f8806135d840c8c81bf658d58c0fd295c000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a0000000000000000000000008cd09af719a93fb3b52a05dbc4ec0fa559eec9c2000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420417567757220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046352455000000000000000000000000000000000000000000000000000000000", + "WBTC": "0x", + "REP": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000005417567757200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035245500000000000000000000000000000000000000000000000000000000000", + "cZRX": "0x0000000000000000000000006c041606a9b4a449df6b5ff7274b79a869616d65000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a0000000000000000000000008cd09af719a93fb3b52a05dbc4ec0fa559eec9c2000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010436f6d706f756e6420307820f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004635a525800000000000000000000000000000000000000000000000000000000", + "cWBTC": "0x000000000000000000000000fd1853eb1391b094dd9dfab566d94f8b6400316c000000000000000000000000e884dcc3167613a5d6a6ef96f90b74e411f32c8a0000000000000000000000008cd09af719a93fb3b52a05dbc4ec0fa559eec9c200000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000019436f6d706f756e6420577261707065642042544320f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000056357425443000000000000000000000000000000000000000000000000000000", + "USDC": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000855534420436f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000" + }, + "Tokens": { + "ZRX": { + "description": "Standard", + "name": "0x", + "symbol": "ZRX", + "decimals": 18, + "contract": "FaucetToken", + "address": "0x6c041606A9b4A449dF6B5FF7274B79a869616D65" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x7Dc9912705FfDb928F62D9694fEfdD3a09F3eCD0", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0xD9FFe966A831089981Bd1539503c9d3cb45E5AAb" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0xB8C5995387c8086d0B496Bd54755d14D7cED8256", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xd9fd9E875c9C1d567825E431DD6Ed4f0e51aA8Bf" + }, + "DAI": { + "description": "Standard", + "name": "Dai", + "symbol": "DAI", + "decimals": 18, + "contract": "FaucetToken", + "address": "0xB8C5995387c8086d0B496Bd54755d14D7cED8256" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0x3e0d325ABA23E9562281D48b2Bd52594Db48CC18", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xc31211101e6D98bEA24F1f32cbeBa3e9ac7c9749" + }, + "BAT": { + "description": "NonStandard", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "contract": "FaucetNonStandardToken", + "address": "0x3e0d325ABA23E9562281D48b2Bd52594Db48CC18" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x2B2aA9c7967eFAd4B73BFD8801333928806409A1" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x4308246f8806135d840c8C81bF658d58c0Fd295C", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x0812e50F3740b89899Ce889C2ab913eA2565f626" + }, + "WBTC": { + "description": "WBTC", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "contract": "WBTCToken", + "address": "0xFD1853eb1391B094dd9DfAB566d94F8b6400316c" + }, + "REP": { + "description": "Standard", + "name": "Augur", + "symbol": "REP", + "decimals": 18, + "contract": "FaucetToken", + "address": "0x4308246f8806135d840c8C81bF658d58c0Fd295C" + }, + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0x6c041606A9b4A449dF6B5FF7274B79a869616D65", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xf412f4d0eE1D96eb486C6C2836bEDc4912bA294E" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0xFD1853eb1391B094dd9DfAB566d94F8b6400316c", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0xe43d693C6d063BDF4A9681f9A6D9D1439344f4f7" + }, + "USDC": { + "description": "Standard", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "contract": "FaucetToken", + "address": "0x7Dc9912705FfDb928F62D9694fEfdD3a09F3eCD0" + } + }, + "cTokens": { + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0x6c041606A9b4A449dF6B5FF7274B79a869616D65", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xf412f4d0eE1D96eb486C6C2836bEDc4912bA294E" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0x3e0d325ABA23E9562281D48b2Bd52594Db48CC18", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xc31211101e6D98bEA24F1f32cbeBa3e9ac7c9749" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0xB8C5995387c8086d0B496Bd54755d14D7cED8256", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xd9fd9E875c9C1d567825E431DD6Ed4f0e51aA8Bf" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x4308246f8806135d840c8C81bF658d58c0Fd295C", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x0812e50F3740b89899Ce889C2ab913eA2565f626" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x2B2aA9c7967eFAd4B73BFD8801333928806409A1" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x7Dc9912705FfDb928F62D9694fEfdD3a09F3eCD0", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0xD9FFe966A831089981Bd1539503c9d3cb45E5AAb" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0xFD1853eb1391B094dd9DfAB566d94F8b6400316c", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0xe43d693C6d063BDF4A9681f9A6D9D1439344f4f7" + } + }, + "InterestRateModel": { + "Base500bps_Slope1200bps": { + "name": "Base500bps_Slope1200bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=50000000000000000 multiplier=120000000000000000", + "base": "50000000000000000", + "slope": "120000000000000000", + "address": "0x63cFb6469408a64d6713C28231c8d90a609aeB23" + }, + "Base0bps_Slope2000bps": { + "name": "Base0bps_Slope2000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=0 multiplier=200000000000000000", + "base": "0", + "slope": "200000000000000000", + "address": "0x23E8731b39E46941f73951b7f39d921bFd6C2E05" + }, + "Base200bps_Slope3000bps": { + "name": "Base200bps_Slope3000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=20000000000000000 multiplier=300000000000000000", + "base": "20000000000000000", + "slope": "300000000000000000", + "address": "0x8cD09AF719A93fB3b52a05Dbc4eC0Fa559EEC9C2" + } + } +} \ No newline at end of file diff --git a/networks/kovan-abi.json b/networks/kovan-abi.json new file mode 100644 index 000000000..1694872a4 --- /dev/null +++ b/networks/kovan-abi.json @@ -0,0 +1,13952 @@ +{ + "ZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cUSDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "PriceOracle": [ + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "underlyingPriceMantissa", + "type": "uint256" + } + ], + "name": "setUnderlyingPrice", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x127ffda0" + }, + { + "constant": true, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "assetPrices", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5e9a523c" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + } + ], + "PriceOracleProxy": [ + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [], + "name": "cEtherAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xde836acf" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + }, + { + "constant": true, + "inputs": [], + "name": "v1PriceOracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe10c98d" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "v1PriceOracle_", + "type": "address" + }, + { + "name": "cEtherAddress_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Maximillion": [ + { + "constant": true, + "inputs": [], + "name": "cEther", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x19b68c00" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cEther_", + "type": "address" + } + ], + "name": "repayBehalfExplicit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x367b7f05" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x9f35c3d5" + }, + { + "inputs": [ + { + "name": "cEther_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cDAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "DAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "StdComptroller": [ + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Unitroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Comptroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "cBAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base0bps_Slope2000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "BAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cETH": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [], + "name": "mint", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x1249c58b" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": false, + "inputs": [], + "name": "repayBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x4e4d9fea" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xaae40a2a" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBorrowBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xe5974619" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base500bps_Slope1200bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Base200bps_Slope3000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cREP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "WBTC": [ + { + "constant": true, + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x05d2035b" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "name": "reclaimToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17ffc320" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [], + "name": "unpause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3f4ba83a" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x40c10f19" + }, + { + "constant": false, + "inputs": [ + { + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x42966c68" + }, + { + "constant": false, + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4e71e0c8" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5c975abb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x715018a6" + }, + { + "constant": false, + "inputs": [], + "name": "finishMinting", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x7d64bcb4" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x8456cb59" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8da5cb5b" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": true, + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe30c3978" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2fde38b" + }, + { + "anonymous": false, + "inputs": [], + "name": "Pause", + "type": "event", + "signature": "0x6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff625" + }, + { + "anonymous": false, + "inputs": [], + "name": "Unpause", + "type": "event", + "signature": "0x7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b33" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "burner", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event", + "signature": "0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885" + }, + { + "anonymous": false, + "inputs": [], + "name": "MintFinished", + "type": "event", + "signature": "0xae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa08" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + } + ], + "name": "OwnershipRenounced", + "type": "event", + "signature": "0xf8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c64820" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event", + "signature": "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "REP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "cWBTC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "USDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ] +} \ No newline at end of file diff --git a/networks/kovan.json b/networks/kovan.json new file mode 100644 index 000000000..e96a24792 --- /dev/null +++ b/networks/kovan.json @@ -0,0 +1,296 @@ +{ + "Contracts": { + "ZRX": "0x7CfF490cfb21B130619055Ba62665ECCDCc12C17", + "cUSDC": "0xDff375162cfE7D77473C1BEC4560dEDE974E138c", + "PriceOracle": "0x5C46CBeEa623dAD6e08560ee487d5aC5afD57997", + "PriceOracleProxy": "0x0314440102f1b2be6b4Dd797371fc2E42d8F9c5f", + "Maximillion": "0x2B536482a01E620eE111747F8334B395a42A555E", + "cDAI": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496", + "DAI": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "StdComptroller": "0x04396A3e673980dAfa3BCC1EfD3632f075E57447", + "Unitroller": "0x142D11CB90a2b40f7d0C55ed1804988DfC316fAe", + "Comptroller": "0x142D11CB90a2b40f7d0C55ed1804988DfC316fAe", + "cBAT": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd", + "Base0bps_Slope2000bps": "0xb081cf57B1e422B3E627544Ec95992CBe8Eaf9cb", + "BAT": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6", + "cETH": "0xD83F707f003A1f0B1535028AB356FCE2667ab855", + "Base500bps_Slope1200bps": "0x5dEA9621f23e79003eCC294b4cc1e4c9362dFECc", + "Base200bps_Slope3000bps": "0xe622DB19D5bf1F4e61Dd57FB11FE887100E5e59E", + "cREP": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f", + "WBTC": "0x19787bcF63E228a6669d905E90aF397DCA313CFC", + "REP": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "cZRX": "0x9636246bf34E688c6652Af544418B38eB51D2c43", + "cWBTC": "0x189CA88bE39C9c1B8c8dd437F5ff1DB1f584b14b", + "USDC": "0x6e894660985207feb7cf89Faf048998c71E8EE89" + }, + "Blocks": { + "ZRX": 12162495, + "cUSDC": 12162506, + "PriceOracle": 12162487, + "PriceOracleProxy": 12162521, + "Maximillion": 12162508, + "cDAI": 12162503, + "DAI": 12162497, + "StdComptroller": 12162489, + "Unitroller": 12162488, + "cBAT": 12162502, + "Base0bps_Slope2000bps": 12162493, + "BAT": 12162496, + "cETH": 12162505, + "Base500bps_Slope1200bps": 12162492, + "Base200bps_Slope3000bps": 12162494, + "cREP": 12162504, + "WBTC": 12162500, + "REP": 12162498, + "cZRX": 12162501, + "cWBTC": 12162507, + "USDC": 12162499 + }, + "PriceOracle": { + "description": "Simple Price Oracle", + "address": "0x5C46CBeEa623dAD6e08560ee487d5aC5afD57997" + }, + "Maximillion": { + "description": "Maximillion", + "cEtherAddress": "0xD83F707f003A1f0B1535028AB356FCE2667ab855", + "address": "0x2B536482a01E620eE111747F8334B395a42A555E" + }, + "Unitroller": { + "description": "Unitroller", + "address": "0x142D11CB90a2b40f7d0C55ed1804988DfC316fAe" + }, + "Comptroller": { + "StdComptroller": { + "address": "0x04396A3e673980dAfa3BCC1EfD3632f075E57447", + "contract": "Comptroller", + "description": "Standard Comptroller Impl" + } + }, + "Constructors": { + "ZRX": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002307800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a52580000000000000000000000000000000000000000000000000000000000", + "cUSDC": "0x0000000000000000000000006e894660985207feb7cf89faf048998c71e8ee89000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000016436f6d706f756e642055534420436f696e20f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000056355534443000000000000000000000000000000000000000000000000000000", + "PriceOracle": "0x", + "PriceOracleProxy": "0x000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae0000000000000000000000005c46cbeea623dad6e08560ee487d5ac5afd57997000000000000000000000000d83f707f003a1f0b1535028ab356fce2667ab855", + "Maximillion": "0x000000000000000000000000d83f707f003a1f0b1535028ab356fce2667ab855", + "cDAI": "0x000000000000000000000000bf7a7169562078c96f0ec1a8afd6ae50f12e5a99000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae0000000000000000000000005dea9621f23e79003ecc294b4cc1e4c9362dfecc000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000011436f6d706f756e642044616920f09f938800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046344414900000000000000000000000000000000000000000000000000000000", + "DAI": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003446169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000", + "StdComptroller": "0x", + "Unitroller": "0x", + "cBAT": "0x000000000000000000000000ddea378a6ddc8afec82c36e9b0078826bf9e68b6000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae000000000000000000000000e622db19d5bf1f4e61dd57fb11fe887100e5e59e000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000023436f6d706f756e6420426173696320417474656e74696f6e20546f6b656e20f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046342415400000000000000000000000000000000000000000000000000000000", + "Base0bps_Slope2000bps": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "BAT": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000015426173696320417474656e74696f6e20546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000034241540000000000000000000000000000000000000000000000000000000000", + "cETH": "0x000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420457468657220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000", + "Base500bps_Slope1200bps": "0x00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000", + "Base200bps_Slope3000bps": "0x00000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000429d069189e0000", + "cREP": "0x0000000000000000000000005592ec0cfb4dbc12d3ab100b257153436a1f0fea000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae000000000000000000000000e622db19d5bf1f4e61dd57fb11fe887100e5e59e000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420417567757220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046352455000000000000000000000000000000000000000000000000000000000", + "WBTC": "0x", + "REP": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000005417567757200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035245500000000000000000000000000000000000000000000000000000000000", + "cZRX": "0x0000000000000000000000007cff490cfb21b130619055ba62665eccdcc12c17000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae000000000000000000000000e622db19d5bf1f4e61dd57fb11fe887100e5e59e000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010436f6d706f756e6420307820f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004635a525800000000000000000000000000000000000000000000000000000000", + "cWBTC": "0x00000000000000000000000019787bcf63e228a6669d905e90af397dca313cfc000000000000000000000000142d11cb90a2b40f7d0c55ed1804988dfc316fae000000000000000000000000e622db19d5bf1f4e61dd57fb11fe887100e5e59e00000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000019436f6d706f756e6420577261707065642042544320f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000056357425443000000000000000000000000000000000000000000000000000000", + "USDC": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000855534420436f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000" + }, + "Tokens": { + "ZRX": { + "description": "Standard", + "name": "0x", + "symbol": "ZRX", + "decimals": 18, + "contract": "FaucetToken", + "address": "0x7CfF490cfb21B130619055Ba62665ECCDCc12C17" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x6e894660985207feb7cf89Faf048998c71E8EE89", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0xDff375162cfE7D77473C1BEC4560dEDE974E138c" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496" + }, + "DAI": { + "description": "Standard", + "name": "Dai", + "symbol": "DAI", + "decimals": 18, + "contract": "FaucetToken", + "address": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd" + }, + "BAT": { + "description": "NonStandard", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "contract": "FaucetNonStandardToken", + "address": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xD83F707f003A1f0B1535028AB356FCE2667ab855" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f" + }, + "WBTC": { + "description": "WBTC", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "contract": "WBTCToken", + "address": "0x19787bcF63E228a6669d905E90aF397DCA313CFC" + }, + "REP": { + "description": "Standard", + "name": "Augur", + "symbol": "REP", + "decimals": 18, + "contract": "FaucetToken", + "address": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa" + }, + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0x7CfF490cfb21B130619055Ba62665ECCDCc12C17", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x9636246bf34E688c6652Af544418B38eB51D2c43" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0x19787bcF63E228a6669d905E90aF397DCA313CFC", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0x189CA88bE39C9c1B8c8dd437F5ff1DB1f584b14b" + }, + "USDC": { + "description": "Standard", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "contract": "FaucetToken", + "address": "0x6e894660985207feb7cf89Faf048998c71E8EE89" + } + }, + "cTokens": { + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0x7CfF490cfb21B130619055Ba62665ECCDCc12C17", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x9636246bf34E688c6652Af544418B38eB51D2c43" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xD83F707f003A1f0B1535028AB356FCE2667ab855" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x6e894660985207feb7cf89Faf048998c71E8EE89", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0xDff375162cfE7D77473C1BEC4560dEDE974E138c" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0x19787bcF63E228a6669d905E90aF397DCA313CFC", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0x189CA88bE39C9c1B8c8dd437F5ff1DB1f584b14b" + } + }, + "InterestRateModel": { + "Base500bps_Slope1200bps": { + "name": "Base500bps_Slope1200bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=50000000000000000 multiplier=120000000000000000", + "base": "50000000000000000", + "slope": "120000000000000000", + "address": "0x5dEA9621f23e79003eCC294b4cc1e4c9362dFECc" + }, + "Base0bps_Slope2000bps": { + "name": "Base0bps_Slope2000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=0 multiplier=200000000000000000", + "base": "0", + "slope": "200000000000000000", + "address": "0xb081cf57B1e422B3E627544Ec95992CBe8Eaf9cb" + }, + "Base200bps_Slope3000bps": { + "name": "Base200bps_Slope3000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=20000000000000000 multiplier=300000000000000000", + "base": "20000000000000000", + "slope": "300000000000000000", + "address": "0xe622DB19D5bf1F4e61Dd57FB11FE887100E5e59E" + } + } +} \ No newline at end of file diff --git a/networks/mainnet-abi.json b/networks/mainnet-abi.json new file mode 100644 index 000000000..dcaf6a272 --- /dev/null +++ b/networks/mainnet-abi.json @@ -0,0 +1,13598 @@ +{ + "cUSDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "StandardInterestRateModel": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "_asset", + "type": "address" + }, + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_asset", + "type": "address" + }, + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "Migrations": [ + { + "constant": true, + "inputs": [], + "name": "last_completed_migration", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "constant": false, + "inputs": [ + { + "name": "completed", + "type": "uint256" + } + ], + "name": "setCompleted", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "new_address", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "PriceOracle": [ + { + "constant": true, + "inputs": [], + "name": "anchorAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxSwingMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "_assetPrices", + "outputs": [ + { + "name": "mantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAnchorAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "numBlocksPerPeriod", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "readers", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "anchors", + "outputs": [ + { + "name": "period", + "type": "uint256" + }, + { + "name": "priceMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "poster", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "pendingAnchors", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxSwing", + "outputs": [ + { + "name": "mantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "_poster", + "type": "address" + }, + { + "name": "addr0", + "type": "address" + }, + { + "name": "reader0", + "type": "address" + }, + { + "name": "addr1", + "type": "address" + }, + { + "name": "reader1", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "msgSender", + "type": "address" + }, + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "OracleFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "anchorAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "oldScaledPrice", + "type": "uint256" + }, + { + "indexed": false, + "name": "newScaledPrice", + "type": "uint256" + } + ], + "name": "NewPendingAnchor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "previousPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "requestedPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newPriceMantissa", + "type": "uint256" + } + ], + "name": "PricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "requestedPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "anchorPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "cappedPriceMantissa", + "type": "uint256" + } + ], + "name": "CappedPricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newState", + "type": "bool" + } + ], + "name": "SetPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAnchorAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAnchorAdmin", + "type": "address" + } + ], + "name": "NewPendingAnchorAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAnchorAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAnchorAdmin", + "type": "address" + } + ], + "name": "NewAnchorAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "newScaledPrice", + "type": "uint256" + } + ], + "name": "_setPendingAnchor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "requestedState", + "type": "bool" + } + ], + "name": "_setPaused", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAnchorAdmin", + "type": "address" + } + ], + "name": "_setPendingAnchorAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAnchorAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "assetPrices", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "requestedPriceMantissa", + "type": "uint256" + } + ], + "name": "setPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "assets", + "type": "address[]" + }, + { + "name": "requestedPriceMantissas", + "type": "uint256[]" + } + ], + "name": "setPrices", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "PriceOracleProxy": [ + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [], + "name": "cEtherAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xde836acf" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + }, + { + "constant": true, + "inputs": [], + "name": "v1PriceOracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe10c98d" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "v1PriceOracle_", + "type": "address" + }, + { + "name": "cEtherAddress_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Maximillion": [ + { + "constant": true, + "inputs": [], + "name": "cEther", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x19b68c00" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cEther_", + "type": "address" + } + ], + "name": "repayBehalfExplicit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x367b7f05" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x9f35c3d5" + }, + { + "inputs": [ + { + "name": "cEther_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cDAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "StdComptroller": [ + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Unitroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Comptroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "cBAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "StableCoinInterestRateModel": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "_asset", + "type": "address" + }, + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + } + ], + "name": "getSupplyRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_asset", + "type": "address" + }, + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "Base0bps_Slope2000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cETH": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [], + "name": "mint", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x1249c58b" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": false, + "inputs": [], + "name": "repayBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x4e4d9fea" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xaae40a2a" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBorrowBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xe5974619" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base500bps_Slope1200bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Base200bps_Slope3000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cREP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "MoneyMarket": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationDiscount", + "outputs": [ + { + "name": "mantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isSupported", + "type": "bool" + }, + { + "name": "blockNumber", + "type": "uint256" + }, + { + "name": "interestRateModel", + "type": "address" + }, + { + "name": "totalSupply", + "type": "uint256" + }, + { + "name": "supplyRateMantissa", + "type": "uint256" + }, + { + "name": "supplyIndex", + "type": "uint256" + }, + { + "name": "totalBorrows", + "type": "uint256" + }, + { + "name": "borrowRateMantissa", + "type": "uint256" + }, + { + "name": "borrowIndex", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "collateralRatio", + "outputs": [ + { + "name": "mantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "supplyBalances", + "outputs": [ + { + "name": "principal", + "type": "uint256" + }, + { + "name": "interestIndex", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "originationFee", + "outputs": [ + { + "name": "mantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "collateralMarkets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "borrowBalances", + "outputs": [ + { + "name": "principal", + "type": "uint256" + }, + { + "name": "interestIndex", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "account", + "type": "address" + }, + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SupplyReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "account", + "type": "address" + }, + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SupplyWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "account", + "type": "address" + }, + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowAmountWithFee", + "type": "uint256" + }, + { + "indexed": false, + "name": "newBalance", + "type": "uint256" + } + ], + "name": "BorrowTaken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "account", + "type": "address" + }, + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "name": "newBalance", + "type": "uint256" + } + ], + "name": "BorrowRepaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "targetAccount", + "type": "address" + }, + { + "indexed": false, + "name": "assetBorrow", + "type": "address" + }, + { + "indexed": false, + "name": "borrowBalanceBefore", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowBalanceAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "amountRepaid", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowBalanceAfter", + "type": "uint256" + }, + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "assetCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "collateralBalanceBefore", + "type": "uint256" + }, + { + "indexed": false, + "name": "collateralBalanceAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "amountSeized", + "type": "uint256" + }, + { + "indexed": false, + "name": "collateralBalanceAfter", + "type": "uint256" + } + ], + "name": "BorrowLiquidated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newOracle", + "type": "address" + } + ], + "name": "NewOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "interestRateModel", + "type": "address" + } + ], + "name": "SupportedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCollateralRatioMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralRatioMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "oldLiquidationDiscountMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationDiscountMantissa", + "type": "uint256" + } + ], + "name": "NewRiskParameters", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldOriginationFeeMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newOriginationFeeMantissa", + "type": "uint256" + } + ], + "name": "NewOriginationFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "interestRateModel", + "type": "address" + } + ], + "name": "SetMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "name": "equityAvailableBefore", + "type": "uint256" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "owner", + "type": "address" + } + ], + "name": "EquityWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "asset", + "type": "address" + } + ], + "name": "SuspendedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newState", + "type": "bool" + } + ], + "name": "SetPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "getCollateralMarketsLength", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "assetPrices", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "requestedState", + "type": "bool" + } + ], + "name": "_setPaused", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "int256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "asset", + "type": "address" + } + ], + "name": "getSupplyBalance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "asset", + "type": "address" + } + ], + "name": "getBorrowBalance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "interestRateModel", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "_suspendMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "collateralRatioMantissa", + "type": "uint256" + }, + { + "name": "liquidationDiscountMantissa", + "type": "uint256" + } + ], + "name": "_setRiskParameters", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "originationFeeMantissa", + "type": "uint256" + } + ], + "name": "_setOriginationFee", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "interestRateModel", + "type": "address" + } + ], + "name": "_setMarketInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "_withdrawEquity", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "supply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "requestedAmount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "userAddress", + "type": "address" + } + ], + "name": "calculateAccountValues", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "targetAccount", + "type": "address" + }, + { + "name": "assetBorrow", + "type": "address" + }, + { + "name": "assetCollateral", + "type": "address" + }, + { + "name": "requestedAmountClose", + "type": "uint256" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "asset", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "cZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "cWBTC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ] +} \ No newline at end of file diff --git a/networks/mainnet.json b/networks/mainnet.json new file mode 100644 index 000000000..e38e96a61 --- /dev/null +++ b/networks/mainnet.json @@ -0,0 +1,269 @@ +{ + "Contracts": { + "ZRX": "0xE41d2489571d322189246DaFA5ebDe1F4699F498", + "cUSDC": "0x39AA39c021dfbaE8faC545936693aC917d5E7563", + "PriceOracle": "0x02557a5e05defeffd4cae6d83ea3d173b272c904", + "PriceOracleProxy": "0x28F829F473638ba82710c8404A778f9a66029aAD", + "Maximillion": "0xf859A1AD94BcF445A406B892eF0d3082f4174088", + "cDAI": "0xF5DCe57282A584D2746FaF1593d3121Fcac444dC", + "DAI": "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359", + "StdComptroller": "0x62F18C451af964197341d3c86D27e98C41BB8fcC", + "Poster": "0x3c6809319201b978d821190ba03fa19a3523bd96", + "Unitroller": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B", + "Comptroller": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B", + "cBAT": "0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E", + "Base0bps_Slope2000bps": "0xc64C4cBA055eFA614CE01F4BAD8A9F519C4f8FaB", + "BAT": "0x0D8775F648430679A709E98d2b0Cb6250d2887EF", + "cETH": "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5", + "Base500bps_Slope1200bps": "0xa1046abfc2598F48C44Fb320d281d3F3c0733c9a", + "Base200bps_Slope3000bps": "0xBAE04CbF96391086dC643e842b517734E214D698", + "cREP": "0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1", + "WBTC": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", + "REP": "0x1985365e9f78359a9B6AD760e32412f4a445E862", + "cZRX": "0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407", + "cWBTC": "0xC11b1268C1A384e55C48c2391d8d480264A3A7F4", + "USDC": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + }, + "Blocks": { + "cUSDC": 7710760, + "PriceOracle": 6747538, + "PriceOracleProxy": 7710793, + "Maximillion": 7710775, + "cDAI": 7710752, + "StdComptroller": 7710672, + "Unitroller": 7710671, + "cBAT": 7710735, + "Base0bps_Slope2000bps": 7710727, + "cETH": 7710758, + "Base500bps_Slope1200bps": 7710726, + "Base200bps_Slope3000bps": 7710728, + "cREP": 7710755, + "cZRX": 7710733, + "cWBTC": 8163813 + }, + "Maximillion": { + "description": "Maximillion", + "cEtherAddress": "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5", + "address": "0xf859A1AD94BcF445A406B892eF0d3082f4174088" + }, + "Unitroller": { + "description": "Unitroller", + "address": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B" + }, + "Comptroller": { + "StdComptroller": { + "address": "0x62F18C451af964197341d3c86D27e98C41BB8fcC", + "contract": "Comptroller", + "description": "Standard Comptroller Impl" + } + }, + "Constructors": { + "cUSDC": "0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000c64c4cba055efa614ce01f4bad8a9f519c4f8fab0000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000011436f6d706f756e642055534420436f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000056355534443000000000000000000000000000000000000000000000000000000", + "PriceOracleProxy": "0x0000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b00000000000000000000000002557a5e05defeffd4cae6d83ea3d173b272c9040000000000000000000000004ddc2d193948926d02f9b1fe9e1daa0718270ed5", + "Maximillion": "0x0000000000000000000000004ddc2d193948926d02f9b1fe9e1daa0718270ed5", + "cDAI": "0x00000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a232603590000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000a1046abfc2598f48c44fb320d281d3f3c0733c9a000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c436f6d706f756e6420446169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046344414900000000000000000000000000000000000000000000000000000000", + "StdComptroller": "0x", + "Unitroller": "0x", + "cBAT": "0x0000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef0000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000bae04cbf96391086dc643e842b517734e214d698000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001e436f6d706f756e6420426173696320417474656e74696f6e20546f6b656e000000000000000000000000000000000000000000000000000000000000000000046342415400000000000000000000000000000000000000000000000000000000", + "Base0bps_Slope2000bps": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "cETH": "0x0000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000c64c4cba055efa614ce01f4bad8a9f519c4f8fab000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e436f6d706f756e6420457468657200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000", + "Base500bps_Slope1200bps": "0x00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000", + "Base200bps_Slope3000bps": "0x00000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000429d069189e0000", + "cREP": "0x0000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e8620000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000bae04cbf96391086dc643e842b517734e214d698000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e436f6d706f756e6420417567757200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046352455000000000000000000000000000000000000000000000000000000000", + "cZRX": "0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f4980000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000bae04cbf96391086dc643e842b517734e214d698000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000b436f6d706f756e642030780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004635a525800000000000000000000000000000000000000000000000000000000", + "cWBTC": "0x0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000003d9819210a31b4961b30ef54be2aed79b9c9cd3b000000000000000000000000bae04cbf96391086dc643e842b517734e214d69800000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000014436f6d706f756e6420577261707065642042544300000000000000000000000000000000000000000000000000000000000000000000000000000000000000056357425443000000000000000000000000000000000000000000000000000000" + }, + "Tokens": { + "ZRX": { + "name": "0x", + "symbol": "ZRX", + "decimals": 18, + "address": "0xE41d2489571d322189246DaFA5ebDe1F4699F498" + }, + "cUSDC": { + "name": "Compound USD Coin", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0x39AA39c021dfbaE8faC545936693aC917d5E7563" + }, + "cDAI": { + "name": "Compound Dai", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xF5DCe57282A584D2746FaF1593d3121Fcac444dC" + }, + "DAI": { + "name": "Dai", + "symbol": "DAI", + "decimals": 18, + "address": "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359", + "reader": "0x729D19f657BD0614b4985Cf1D82531c67569197B" + }, + "cBAT": { + "name": "Compound Basic Attention Token", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0x0D8775F648430679A709E98d2b0Cb6250d2887EF", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E" + }, + "BAT": { + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "address": "0x0D8775F648430679A709E98d2b0Cb6250d2887EF" + }, + "cETH": { + "name": "Compound Ether", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5" + }, + "cREP": { + "name": "Compound Augur", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x1985365e9f78359a9B6AD760e32412f4a445E862", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1" + }, + "WBTC": { + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "address": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" + }, + "REP": { + "name": "Augur", + "symbol": "REP", + "decimals": 18, + "address": "0x1985365e9f78359a9B6AD760e32412f4a445E862" + }, + "cZRX": { + "name": "Compound 0x", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0xE41d2489571d322189246DaFA5ebDe1F4699F498", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407" + }, + "cWBTC": { + "name": "Compound Wrapped BTC", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0xC11b1268C1A384e55C48c2391d8d480264A3A7F4" + }, + "USDC": { + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + } + }, + "cTokens": { + "cZRX": { + "name": "Compound 0x", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0xE41d2489571d322189246DaFA5ebDe1F4699F498", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407" + }, + "cBAT": { + "name": "Compound Basic Attention Token", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0x0D8775F648430679A709E98d2b0Cb6250d2887EF", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E" + }, + "cDAI": { + "name": "Compound Dai", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xF5DCe57282A584D2746FaF1593d3121Fcac444dC" + }, + "cREP": { + "name": "Compound Augur", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x1985365e9f78359a9B6AD760e32412f4a445E862", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1" + }, + "cETH": { + "name": "Compound Ether", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5" + }, + "cUSDC": { + "name": "Compound USD Coin", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0x39AA39c021dfbaE8faC545936693aC917d5E7563" + }, + "cWBTC": { + "name": "Compound Wrapped BTC", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0xC11b1268C1A384e55C48c2391d8d480264A3A7F4" + } + }, + "InterestRateModel": { + "Base500bps_Slope1200bps": { + "name": "Base500bps_Slope1200bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=50000000000000000 multiplier=120000000000000000", + "base": "50000000000000000", + "slope": "120000000000000000", + "address": "0xa1046abfc2598F48C44Fb320d281d3F3c0733c9a" + }, + "Base0bps_Slope2000bps": { + "name": "Base0bps_Slope2000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=0 multiplier=200000000000000000", + "base": "0", + "slope": "200000000000000000", + "address": "0xc64C4cBA055eFA614CE01F4BAD8A9F519C4f8FaB" + }, + "Base200bps_Slope3000bps": { + "name": "Base200bps_Slope3000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=20000000000000000 multiplier=300000000000000000", + "base": "20000000000000000", + "slope": "300000000000000000", + "address": "0xBAE04CbF96391086dC643e842b517734E214D698" + } + } +} \ No newline at end of file diff --git a/networks/rinkeby-abi.json b/networks/rinkeby-abi.json new file mode 100644 index 000000000..550d04c42 --- /dev/null +++ b/networks/rinkeby-abi.json @@ -0,0 +1,15614 @@ +{ + "ZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + } + ], + "cUSDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "StableInterest": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "PriceOracle": [ + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + } + ], + "StandardInterest": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "ZeroComptroller": [ + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "PriceOracleProxy": [ + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [], + "name": "cEtherAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xde836acf" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + }, + { + "constant": true, + "inputs": [], + "name": "v1PriceOracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe10c98d" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "v1PriceOracle_", + "type": "address" + }, + { + "name": "cEtherAddress_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Maximillion": [ + { + "constant": true, + "inputs": [], + "name": "cEther", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x19b68c00" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cEther_", + "type": "address" + } + ], + "name": "repayBehalfExplicit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x367b7f05" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x9f35c3d5" + }, + { + "inputs": [ + { + "name": "cEther_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cDAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "DAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + } + ], + "StdComptroller": [ + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Unitroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Comptroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "cBAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base0bps_Slope2000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "BAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + } + ], + "cETH": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [], + "name": "mint", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x1249c58b" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": false, + "inputs": [], + "name": "repayBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x4e4d9fea" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xaae40a2a" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBorrowBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xe5974619" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base500bps_Slope1200bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Base200bps_Slope3000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cREP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "REP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + } + ], + "cZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "USDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + } + ], + "cWBTC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ] +} \ No newline at end of file diff --git a/networks/rinkeby.json b/networks/rinkeby.json new file mode 100644 index 000000000..c8349eae5 --- /dev/null +++ b/networks/rinkeby.json @@ -0,0 +1,291 @@ +{ + "Contracts": { + "ZRX": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6", + "cUSDC": "0x5B281A6DdA0B271e91ae35DE655Ad301C976edb1", + "PriceOracle": "0xD2B1eCa822550d9358e97e72c6C1a93AE28408d0", + "ZeroComptroller": "0x16e175eE9f555E43FD01f3aFa359A37b10e5139b", + "PriceOracleProxy": "0x332B6e69f21ACdBA5fb3e8DaC56ff81878527E06", + "Maximillion": "0xFBBDBa59516adA2eADf50f96cE0151edC9e0A674", + "cDAI": "0x6D7F0754FFeb405d23C51CE938289d4835bE3b14", + "DAI": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "StdComptroller": "0x99127FD9840Cbc2bBfF43dF443887f4d96268916", + "Unitroller": "0x2EAa9D77AE4D8f9cdD9FAAcd44016E746485bddb", + "Comptroller": "0x2EAa9D77AE4D8f9cdD9FAAcd44016E746485bddb", + "cBAT": "0xEBf1A11532b93a529b5bC942B4bAA98647913002", + "Base0bps_Slope2000bps": "0x1A43BFd39B15DcF444e17Ab408C4b5be32DEB7F5", + "BAT": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "cETH": "0xd6801a1DfFCd0a410336Ef88DeF4320D6DF1883e", + "Base500bps_Slope1200bps": "0xE12630c8Fdd7d0096c9Cd72Cd228598AEBe58795", + "Base200bps_Slope3000bps": "0x6330D442A2D7eE4DC66C0adb9969e8702aEfc9fE", + "cREP": "0xEBe09eB3411D18F4FF8D859e096C533CAC5c6B60", + "WBTC": "0x577D296678535e4903D59A4C929B718e1D575e0A", + "REP": "0x6e894660985207feb7cf89Faf048998c71E8EE89", + "cZRX": "0x52201ff1720134bBbBB2f6BC97Bf3715490EC19B", + "cWBTC": "0x0014F450B8Ae7708593F4A46F8fa6E5D50620F96", + "USDC": "0x4DBCdF9B62e891a7cec5A2568C3F4FAF9E8Abe2b" + }, + "Blocks": { + "cUSDC": 4319847, + "ZeroComptroller": 4347719, + "PriceOracleProxy": 4319855, + "Maximillion": 4319848, + "cDAI": 4319844, + "StdComptroller": 4319836, + "Unitroller": 4319835, + "cBAT": 4319843, + "Base0bps_Slope2000bps": 4319840, + "cETH": 4319846, + "Base500bps_Slope1200bps": 4319839, + "Base200bps_Slope3000bps": 4319841, + "cREP": 4319845, + "WBTC": 4717533, + "cZRX": 4319842, + "cWBTC": 4717535 + }, + "PriceOracleProxy": { + "description": "Price Oracle Proxy", + "cEther": "0xd6801a1DfFCd0a410336Ef88DeF4320D6DF1883e", + "cUSDC": "0x5B281A6DdA0B271e91ae35DE655Ad301C976edb1", + "address": "0xee1E6a73937757fdBf9d23F857f7788b282386c6" + }, + "Maximillion": { + "description": "Maximillion", + "cEtherAddress": "0xd6801a1DfFCd0a410336Ef88DeF4320D6DF1883e", + "address": "0xFBBDBa59516adA2eADf50f96cE0151edC9e0A674" + }, + "Unitroller": { + "description": "Unitroller", + "address": "0x2EAa9D77AE4D8f9cdD9FAAcd44016E746485bddb" + }, + "Comptroller": { + "StdComptroller": { + "address": "0x99127FD9840Cbc2bBfF43dF443887f4d96268916", + "contract": "Comptroller", + "description": "Standard Comptroller Impl" + }, + "ZeroComptroller": { + "address": "0x16e175eE9f555E43FD01f3aFa359A37b10e5139b", + "contract": "Comptroller", + "description": "Standard Comptroller Impl" + } + }, + "Constructors": { + "ZRX": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002307800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a52580000000000000000000000000000000000000000000000000000000000", + "cUSDC": "0x0000000000000000000000004dbcdf9b62e891a7cec5a2568c3f4faf9e8abe2b0000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb0000000000000000000000001a43bfd39b15dcf444e17ab408c4b5be32deb7f50000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000016436f6d706f756e642055534420436f696e20f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000056355534443000000000000000000000000000000000000000000000000000000", + "ZeroComptroller": "0x", + "PriceOracleProxy": "0x0000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb000000000000000000000000d2b1eca822550d9358e97e72c6c1a93ae28408d0000000000000000000000000d6801a1dffcd0a410336ef88def4320d6df1883e", + "Maximillion": "0x000000000000000000000000d6801a1dffcd0a410336ef88def4320d6df1883e", + "cDAI": "0x0000000000000000000000005592ec0cfb4dbc12d3ab100b257153436a1f0fea0000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb000000000000000000000000e12630c8fdd7d0096c9cd72cd228598aebe58795000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000011436f6d706f756e642044616920f09f938800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046344414900000000000000000000000000000000000000000000000000000000", + "DAI": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003446169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000", + "StdComptroller": "0x", + "Unitroller": "0x", + "cBAT": "0x000000000000000000000000bf7a7169562078c96f0ec1a8afd6ae50f12e5a990000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb0000000000000000000000006330d442a2d7ee4dc66c0adb9969e8702aefc9fe000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000023436f6d706f756e6420426173696320417474656e74696f6e20546f6b656e20f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046342415400000000000000000000000000000000000000000000000000000000", + "Base0bps_Slope2000bps": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "BAT": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000015426173696320417474656e74696f6e20546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000034241540000000000000000000000000000000000000000000000000000000000", + "cETH": "0x0000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb0000000000000000000000001a43bfd39b15dcf444e17ab408c4b5be32deb7f5000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420457468657220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000", + "Base500bps_Slope1200bps": "0x00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000", + "Base200bps_Slope3000bps": "0x00000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000429d069189e0000", + "cREP": "0x0000000000000000000000006e894660985207feb7cf89faf048998c71e8ee890000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb0000000000000000000000006330d442a2d7ee4dc66c0adb9969e8702aefc9fe000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420417567757220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046352455000000000000000000000000000000000000000000000000000000000", + "WBTC": "0x", + "REP": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000005417567757200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035245500000000000000000000000000000000000000000000000000000000000", + "cZRX": "0x000000000000000000000000ddea378a6ddc8afec82c36e9b0078826bf9e68b60000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb0000000000000000000000006330d442a2d7ee4dc66c0adb9969e8702aefc9fe000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010436f6d706f756e6420307820f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004635a525800000000000000000000000000000000000000000000000000000000", + "cWBTC": "0x000000000000000000000000577d296678535e4903d59a4c929b718e1d575e0a0000000000000000000000002eaa9d77ae4d8f9cdd9faacd44016e746485bddb0000000000000000000000006330d442a2d7ee4dc66c0adb9969e8702aefc9fe00000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000019436f6d706f756e6420577261707065642042544320f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000056357425443000000000000000000000000000000000000000000000000000000", + "USDC": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000855534420436f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000" + }, + "Tokens": { + "ZRX": { + "name": "0x", + "symbol": "ZRX", + "decimals": 18, + "address": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x4DBCdF9B62e891a7cec5A2568C3F4FAF9E8Abe2b", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0x5B281A6DdA0B271e91ae35DE655Ad301C976edb1" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x6D7F0754FFeb405d23C51CE938289d4835bE3b14" + }, + "DAI": { + "name": "Dai", + "symbol": "DAI", + "decimals": 18, + "address": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xEBf1A11532b93a529b5bC942B4bAA98647913002" + }, + "BAT": { + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "address": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xd6801a1DfFCd0a410336Ef88DeF4320D6DF1883e" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x6e894660985207feb7cf89Faf048998c71E8EE89", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xEBe09eB3411D18F4FF8D859e096C533CAC5c6B60" + }, + "WBTC": { + "description": "WBTC", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "contract": "WBTCToken", + "address": "0x577D296678535e4903D59A4C929B718e1D575e0A" + }, + "REP": { + "name": "Augur", + "symbol": "REP", + "decimals": 18, + "address": "0x6e894660985207feb7cf89Faf048998c71E8EE89" + }, + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x52201ff1720134bBbBB2f6BC97Bf3715490EC19B" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0x0014F450B8Ae7708593F4A46F8fa6E5D50620F96" + }, + "USDC": { + "description": "Standard", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "address": "0x4DBCdF9B62e891a7cec5A2568C3F4FAF9E8Abe2b", + "contract": "FaucetToken" + } + }, + "cTokens": { + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x52201ff1720134bBbBB2f6BC97Bf3715490EC19B" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xEBf1A11532b93a529b5bC942B4bAA98647913002" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x6D7F0754FFeb405d23C51CE938289d4835bE3b14" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x6e894660985207feb7cf89Faf048998c71E8EE89", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xEBe09eB3411D18F4FF8D859e096C533CAC5c6B60" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xd6801a1DfFCd0a410336Ef88DeF4320D6DF1883e" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x4DBCdF9B62e891a7cec5A2568C3F4FAF9E8Abe2b", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0x5B281A6DdA0B271e91ae35DE655Ad301C976edb1" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0x0014F450B8Ae7708593F4A46F8fa6E5D50620F96" + } + }, + "InterestRateModel": { + "Base500bps_Slope1200bps": { + "name": "Base500bps_Slope1200bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=50000000000000000 multiplier=120000000000000000", + "base": "50000000000000000", + "slope": "120000000000000000", + "address": "0xE12630c8Fdd7d0096c9Cd72Cd228598AEBe58795" + }, + "Base0bps_Slope2000bps": { + "name": "Base0bps_Slope2000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=0 multiplier=200000000000000000", + "base": "0", + "slope": "200000000000000000", + "address": "0x1A43BFd39B15DcF444e17Ab408C4b5be32DEB7F5" + }, + "Base200bps_Slope3000bps": { + "name": "Base200bps_Slope3000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=20000000000000000 multiplier=300000000000000000", + "base": "20000000000000000", + "slope": "300000000000000000", + "address": "0x6330D442A2D7eE4DC66C0adb9969e8702aEfc9fE" + } + } +} \ No newline at end of file diff --git a/networks/ropsten-abi.json b/networks/ropsten-abi.json new file mode 100644 index 000000000..1694872a4 --- /dev/null +++ b/networks/ropsten-abi.json @@ -0,0 +1,13952 @@ +{ + "ZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cUSDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "PriceOracle": [ + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "underlyingPriceMantissa", + "type": "uint256" + } + ], + "name": "setUnderlyingPrice", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x127ffda0" + }, + { + "constant": true, + "inputs": [ + { + "name": "asset", + "type": "address" + } + ], + "name": "assetPrices", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5e9a523c" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + } + ], + "PriceOracleProxy": [ + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": true, + "inputs": [], + "name": "isPriceOracle", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x66331bba" + }, + { + "constant": true, + "inputs": [], + "name": "cEtherAddress", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xde836acf" + }, + { + "constant": true, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfc57d4df" + }, + { + "constant": true, + "inputs": [], + "name": "v1PriceOracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe10c98d" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "v1PriceOracle_", + "type": "address" + }, + { + "name": "cEtherAddress_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Maximillion": [ + { + "constant": true, + "inputs": [], + "name": "cEther", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x19b68c00" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cEther_", + "type": "address" + } + ], + "name": "repayBehalfExplicit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x367b7f05" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x9f35c3d5" + }, + { + "inputs": [ + { + "name": "cEther_", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cDAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "DAI": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "StdComptroller": [ + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Unitroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "Comptroller": [ + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc1e80334" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe992a041" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event", + "signature": "0xe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d815" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event", + "signature": "0xd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "constant": true, + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x007e3dd2" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x1ededc91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "payer", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x24008a62" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": false, + "inputs": [ + { + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x317b0b77" + }, + { + "constant": false, + "inputs": [ + { + "name": "unitroller", + "type": "address" + }, + { + "name": "_oracle", + "type": "address" + }, + { + "name": "_closeFactorMantissa", + "type": "uint256" + }, + { + "name": "_maxAssets", + "type": "uint256" + }, + { + "name": "reinitializing", + "type": "bool" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x32000e00" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + }, + { + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x41c728b9" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x47ef3b3b" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x4ada90af" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "minter", + "type": "address" + }, + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4ef4c3e1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "_setLiquidationIncentive", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4fd42e17" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemAmount", + "type": "uint256" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x51dff989" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x55ee1fe1" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5c778605" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5ec88c79" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x5fc7e71e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6a56947e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x6d35bf91" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x7dc0d1d0" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "name": "isListed", + "type": "bool" + }, + { + "name": "collateralFactorMantissa", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8e8f294b" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "cToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x929fe9a1" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x94b2294b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa76b3fda" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xabfceffc" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xbb82aa5e" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbdcdc258" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc2998238" + }, + { + "constant": true, + "inputs": [ + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc488847b" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenCollateral", + "type": "address" + }, + { + "name": "cTokenBorrowed", + "type": "address" + }, + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd02f7351" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "_setMaxAssets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd9226ced" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xda3d454c" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdce15449" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdcfbc0c7" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCollateralFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe4028eee" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe8755446" + }, + { + "constant": false, + "inputs": [ + { + "name": "cToken", + "type": "address" + }, + { + "name": "redeemer", + "type": "address" + }, + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xeabe7d91" + }, + { + "constant": false, + "inputs": [ + { + "name": "cTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xede4edd0" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event", + "signature": "0xcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event", + "signature": "0x3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event", + "signature": "0xe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event", + "signature": "0x3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "cToken", + "type": "address" + }, + { + "indexed": false, + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event", + "signature": "0x70483e6592cd5182d45ac970e05bc62cdcc90e9d8ef2c2dbe686cf383bcd7fc5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event", + "signature": "0xaeba5a6c40a8ac138134bff1aaa65debf25971188a58804bad717f82f0ec1316" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldMaxAssets", + "type": "uint256" + }, + { + "indexed": false, + "name": "newMaxAssets", + "type": "uint256" + } + ], + "name": "NewMaxAssets", + "type": "event", + "signature": "0x7093cf1eb653f749c3ff531d6df7f92764536a7fa0d13530cd26e070780c32ea" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event", + "signature": "0xd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e22" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + } + ], + "cBAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base0bps_Slope2000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "BAT": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cETH": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [], + "name": "mint", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x1249c58b" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": false, + "inputs": [], + "name": "repayBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0x4e4d9fea" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xaae40a2a" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "repayBorrowBehalf", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function", + "signature": "0xe5974619" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "Base500bps_Slope1200bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "Base200bps_Slope3000bps": [ + { + "constant": true, + "inputs": [ + { + "name": "cash", + "type": "uint256" + }, + { + "name": "borrows", + "type": "uint256" + }, + { + "name": "_reserves", + "type": "uint256" + } + ], + "name": "getBorrowRate", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x15f24053" + }, + { + "constant": true, + "inputs": [], + "name": "multiplier", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1b3ed722" + }, + { + "constant": true, + "inputs": [], + "name": "baseRate", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x1f68f20a" + }, + { + "constant": true, + "inputs": [], + "name": "isInterestRateModel", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x2191f92a" + }, + { + "constant": true, + "inputs": [], + "name": "blocksPerYear", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xa385fb96" + }, + { + "inputs": [ + { + "name": "baseRate_", + "type": "uint256" + }, + { + "name": "multiplier_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + } + ], + "cREP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "WBTC": [ + { + "constant": true, + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x05d2035b" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "_token", + "type": "address" + } + ], + "name": "reclaimToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17ffc320" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [], + "name": "unpause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3f4ba83a" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x40c10f19" + }, + { + "constant": false, + "inputs": [ + { + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x42966c68" + }, + { + "constant": false, + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4e71e0c8" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5c975abb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x715018a6" + }, + { + "constant": false, + "inputs": [], + "name": "finishMinting", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x7d64bcb4" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x8456cb59" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8da5cb5b" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": true, + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xe30c3978" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2fde38b" + }, + { + "anonymous": false, + "inputs": [], + "name": "Pause", + "type": "event", + "signature": "0x6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff625" + }, + { + "anonymous": false, + "inputs": [], + "name": "Unpause", + "type": "event", + "signature": "0x7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b33" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "burner", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Burn", + "type": "event", + "signature": "0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885" + }, + { + "anonymous": false, + "inputs": [], + "name": "MintFinished", + "type": "event", + "signature": "0xae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa08" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + } + ], + "name": "OwnershipRenounced", + "type": "event", + "signature": "0xf8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c64820" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event", + "signature": "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "REP": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ], + "cZRX": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "cWBTC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": false, + "inputs": [ + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x0e752702" + }, + { + "constant": true, + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x173b9904" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x17bfdfbc" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x182df0f5" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x2608f818" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x26782247" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x3af9e669" + }, + { + "constant": true, + "inputs": [], + "name": "getCash", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x3b1d21a2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newComptroller", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x4576b5db" + }, + { + "constant": true, + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x47bd3718" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x5fe3b567" + }, + { + "constant": false, + "inputs": [ + { + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "_reduceReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x601a0bf1" + }, + { + "constant": true, + "inputs": [], + "name": "initialExchangeRateMantissa", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x675d972c" + }, + { + "constant": true, + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6c540baf" + }, + { + "constant": true, + "inputs": [], + "name": "underlying", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x6f307dc3" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": false, + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x73acee98" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x852a12e3" + }, + { + "constant": true, + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x8f840ddd" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95dd9193" + }, + { + "constant": false, + "inputs": [ + { + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa0712d68" + }, + { + "constant": false, + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa6afed95" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": true, + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xaa5af0fd" + }, + { + "constant": true, + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xae9d70b0" + }, + { + "constant": false, + "inputs": [ + { + "name": "liquidator", + "type": "address" + }, + { + "name": "borrower", + "type": "address" + }, + { + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb2a02ff1" + }, + { + "constant": false, + "inputs": [ + { + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xb71d1a0c" + }, + { + "constant": false, + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xbd6d894d" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xc37f68e2" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xc5ebeaec" + }, + { + "constant": false, + "inputs": [ + { + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xdb006a75" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xe9c714f2" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "_setInterestRateModel", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf2b3abbd" + }, + { + "constant": true, + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf3fdb15a" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "repayAmount", + "type": "uint256" + }, + { + "name": "cTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xf5e3c462" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf851a440" + }, + { + "constant": true, + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xf8f9da28" + }, + { + "constant": false, + "inputs": [ + { + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "_setReserveFactor", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xfca7820b" + }, + { + "constant": true, + "inputs": [], + "name": "isCToken", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xfe9c44ae" + }, + { + "inputs": [ + { + "name": "underlying_", + "type": "address" + }, + { + "name": "comptroller_", + "type": "address" + }, + { + "name": "interestRateModel_", + "type": "address" + }, + { + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "name": "name_", + "type": "string" + }, + { + "name": "symbol_", + "type": "string" + }, + { + "name": "decimals_", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event", + "signature": "0x875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event", + "signature": "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event", + "signature": "0xe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event", + "signature": "0x13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event", + "signature": "0x1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "cTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event", + "signature": "0x298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb52" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event", + "signature": "0xca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event", + "signature": "0xf9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event", + "signature": "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event", + "signature": "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event", + "signature": "0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesReduced", + "type": "event", + "signature": "0x3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event", + "signature": "0x45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + } + ], + "USDC": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x06fdde03" + }, + { + "constant": false, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x08bca566" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x095ea7b3" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x18160ddd" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x23b872dd" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x313ce567" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0x66188463" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x70a08231" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0x95d89b41" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xa9059cbb" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function", + "signature": "0xd73dd623" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function", + "signature": "0xdd62ed3e" + }, + { + "inputs": [ + { + "name": "_initialAmount", + "type": "uint256" + }, + { + "name": "_tokenName", + "type": "string" + }, + { + "name": "_decimalUnits", + "type": "uint8" + }, + { + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor", + "signature": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event", + "signature": "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event", + "signature": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + } + ] +} \ No newline at end of file diff --git a/networks/ropsten.json b/networks/ropsten.json new file mode 100644 index 000000000..6ec3e4fc8 --- /dev/null +++ b/networks/ropsten.json @@ -0,0 +1,296 @@ +{ + "Contracts": { + "ZRX": "0x19787bcF63E228a6669d905E90aF397DCA313CFC", + "cUSDC": "0x43a1363AFB28235720FCbDF0C2dAb7759091F7e0", + "PriceOracle": "0x5dEA9621f23e79003eCC294b4cc1e4c9362dFECc", + "PriceOracleProxy": "0xc7E20CF485b8E0Bcec3e2fCc23e3aD93b1b0cB39", + "Maximillion": "0xE77Ce01B692FcF66E2F632e518b9449D18D582d8", + "cDAI": "0x2B536482a01E620eE111747F8334B395a42A555E", + "DAI": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd", + "StdComptroller": "0xe622DB19D5bf1F4e61Dd57FB11FE887100E5e59E", + "Unitroller": "0xb081cf57B1e422B3E627544Ec95992CBe8Eaf9cb", + "Comptroller": "0xb081cf57B1e422B3E627544Ec95992CBe8Eaf9cb", + "cBAT": "0x189CA88bE39C9c1B8c8dd437F5ff1DB1f584b14b", + "Base0bps_Slope2000bps": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa", + "BAT": "0x9636246bf34E688c6652Af544418B38eB51D2c43", + "cETH": "0x42a628e0c5F3767930097B34b08dCF77e78e4F2B", + "Base500bps_Slope1200bps": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99", + "Base200bps_Slope3000bps": "0x6e894660985207feb7cf89Faf048998c71E8EE89", + "cREP": "0xA3C2c1618214549281E1b15dee9D682C8aa0DC1C", + "WBTC": "0xD83F707f003A1f0B1535028AB356FCE2667ab855", + "REP": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496", + "cZRX": "0xDff375162cfE7D77473C1BEC4560dEDE974E138c", + "cWBTC": "0x06E728D7907C164649427D2ACFD4c81669D453Bf", + "USDC": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f" + }, + "Blocks": { + "ZRX": 5970747, + "cUSDC": 5970770, + "PriceOracle": 5970733, + "PriceOracleProxy": 5970796, + "Maximillion": 5970773, + "cDAI": 5970763, + "DAI": 5970751, + "StdComptroller": 5970737, + "Unitroller": 5970735, + "cBAT": 5970761, + "Base0bps_Slope2000bps": 5970744, + "BAT": 5970749, + "cETH": 5970768, + "Base500bps_Slope1200bps": 5970743, + "Base200bps_Slope3000bps": 5970745, + "cREP": 5970764, + "WBTC": 5970757, + "REP": 5970753, + "cZRX": 5970759, + "cWBTC": 5970772, + "USDC": 5970755 + }, + "PriceOracle": { + "description": "Simple Price Oracle", + "address": "0x5dEA9621f23e79003eCC294b4cc1e4c9362dFECc" + }, + "Maximillion": { + "description": "Maximillion", + "cEtherAddress": "0x42a628e0c5F3767930097B34b08dCF77e78e4F2B", + "address": "0xE77Ce01B692FcF66E2F632e518b9449D18D582d8" + }, + "Unitroller": { + "description": "Unitroller", + "address": "0xb081cf57B1e422B3E627544Ec95992CBe8Eaf9cb" + }, + "Comptroller": { + "StdComptroller": { + "address": "0xe622DB19D5bf1F4e61Dd57FB11FE887100E5e59E", + "contract": "Comptroller", + "description": "Standard Comptroller Impl" + } + }, + "Constructors": { + "ZRX": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002307800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a52580000000000000000000000000000000000000000000000000000000000", + "cUSDC": "0x0000000000000000000000008a9447df1fb47209d36204e6d56767a33bf20f9f000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000005592ec0cfb4dbc12d3ab100b257153436a1f0fea0000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000016436f6d706f756e642055534420436f696e20f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000056355534443000000000000000000000000000000000000000000000000000000", + "PriceOracle": "0x", + "PriceOracleProxy": "0x000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000005dea9621f23e79003ecc294b4cc1e4c9362dfecc00000000000000000000000042a628e0c5f3767930097b34b08dcf77e78e4f2b", + "Maximillion": "0x00000000000000000000000042a628e0c5f3767930097b34b08dcf77e78e4f2b", + "cDAI": "0x000000000000000000000000b5e5d0f8c0cba267cd3d7035d6adc8eba7df7cdd000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb000000000000000000000000bf7a7169562078c96f0ec1a8afd6ae50f12e5a99000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000011436f6d706f756e642044616920f09f938800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046344414900000000000000000000000000000000000000000000000000000000", + "DAI": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000003446169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000", + "StdComptroller": "0x", + "Unitroller": "0x", + "cBAT": "0x0000000000000000000000009636246bf34e688c6652af544418b38eb51d2c43000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000006e894660985207feb7cf89faf048998c71e8ee89000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000023436f6d706f756e6420426173696320417474656e74696f6e20546f6b656e20f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046342415400000000000000000000000000000000000000000000000000000000", + "Base0bps_Slope2000bps": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c68af0bb140000", + "BAT": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000015426173696320417474656e74696f6e20546f6b656e000000000000000000000000000000000000000000000000000000000000000000000000000000000000034241540000000000000000000000000000000000000000000000000000000000", + "cETH": "0x000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000005592ec0cfb4dbc12d3ab100b257153436a1f0fea000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420457468657220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046345544800000000000000000000000000000000000000000000000000000000", + "Base500bps_Slope1200bps": "0x00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000", + "Base200bps_Slope3000bps": "0x00000000000000000000000000000000000000000000000000470de4df8200000000000000000000000000000000000000000000000000000429d069189e0000", + "cREP": "0x0000000000000000000000000a1e4d0b5c71b955c0a5993023fc48ba6e380496000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000006e894660985207feb7cf89faf048998c71e8ee89000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000013436f6d706f756e6420417567757220f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046352455000000000000000000000000000000000000000000000000000000000", + "WBTC": "0x", + "REP": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000005417567757200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035245500000000000000000000000000000000000000000000000000000000000", + "cZRX": "0x00000000000000000000000019787bcf63e228a6669d905e90af397dca313cfc000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000006e894660985207feb7cf89faf048998c71e8ee89000000000000000000000000000000000000000000a56fa5b99019a5c800000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010436f6d706f756e6420307820f09f9388000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004635a525800000000000000000000000000000000000000000000000000000000", + "cWBTC": "0x000000000000000000000000d83f707f003a1f0b1535028ab356fce2667ab855000000000000000000000000b081cf57b1e422b3e627544ec95992cbe8eaf9cb0000000000000000000000006e894660985207feb7cf89faf048998c71e8ee8900000000000000000000000000000000000000000000000000470de4df82000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000019436f6d706f756e6420577261707065642042544320f09f93880000000000000000000000000000000000000000000000000000000000000000000000000000056357425443000000000000000000000000000000000000000000000000000000", + "USDC": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000855534420436f696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000" + }, + "Tokens": { + "ZRX": { + "description": "Standard", + "name": "0x", + "symbol": "ZRX", + "decimals": 18, + "contract": "FaucetToken", + "address": "0x19787bcF63E228a6669d905E90aF397DCA313CFC" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0x43a1363AFB28235720FCbDF0C2dAb7759091F7e0" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x2B536482a01E620eE111747F8334B395a42A555E" + }, + "DAI": { + "description": "Standard", + "name": "Dai", + "symbol": "DAI", + "decimals": 18, + "contract": "FaucetToken", + "address": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0x9636246bf34E688c6652Af544418B38eB51D2c43", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x189CA88bE39C9c1B8c8dd437F5ff1DB1f584b14b" + }, + "BAT": { + "description": "NonStandard", + "name": "Basic Attention Token", + "symbol": "BAT", + "decimals": 18, + "contract": "FaucetNonStandardToken", + "address": "0x9636246bf34E688c6652Af544418B38eB51D2c43" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x42a628e0c5F3767930097B34b08dCF77e78e4F2B" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xA3C2c1618214549281E1b15dee9D682C8aa0DC1C" + }, + "WBTC": { + "description": "WBTC", + "name": "Wrapped BTC", + "symbol": "WBTC", + "decimals": 8, + "contract": "WBTCToken", + "address": "0xD83F707f003A1f0B1535028AB356FCE2667ab855" + }, + "REP": { + "description": "Standard", + "name": "Augur", + "symbol": "REP", + "decimals": 18, + "contract": "FaucetToken", + "address": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496" + }, + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0x19787bcF63E228a6669d905E90aF397DCA313CFC", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xDff375162cfE7D77473C1BEC4560dEDE974E138c" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0xD83F707f003A1f0B1535028AB356FCE2667ab855", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0x06E728D7907C164649427D2ACFD4c81669D453Bf" + }, + "USDC": { + "description": "Standard", + "name": "USD Coin", + "symbol": "USDC", + "decimals": 6, + "contract": "FaucetToken", + "address": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f" + } + }, + "cTokens": { + "cZRX": { + "name": "Compound 0x 📈", + "symbol": "cZRX", + "decimals": 8, + "underlying": "0x19787bcF63E228a6669d905E90aF397DCA313CFC", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xDff375162cfE7D77473C1BEC4560dEDE974E138c" + }, + "cBAT": { + "name": "Compound Basic Attention Token 📈", + "symbol": "cBAT", + "decimals": 8, + "underlying": "0x9636246bf34E688c6652Af544418B38eB51D2c43", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x189CA88bE39C9c1B8c8dd437F5ff1DB1f584b14b" + }, + "cDAI": { + "name": "Compound Dai 📈", + "symbol": "cDAI", + "decimals": 8, + "underlying": "0xB5E5D0F8C0cbA267CD3D7035d6AdC8eBA7Df7Cdd", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x2B536482a01E620eE111747F8334B395a42A555E" + }, + "cREP": { + "name": "Compound Augur 📈", + "symbol": "cREP", + "decimals": 8, + "underlying": "0x0A1e4D0B5c71B955c0a5993023fc48bA6E380496", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0xA3C2c1618214549281E1b15dee9D682C8aa0DC1C" + }, + "cETH": { + "name": "Compound Ether 📈", + "symbol": "cETH", + "decimals": 8, + "underlying": "", + "contract": "CEther", + "initial_exchange_rate_mantissa": "200000000000000000000000000", + "address": "0x42a628e0c5F3767930097B34b08dCF77e78e4F2B" + }, + "cUSDC": { + "name": "Compound USD Coin 📈", + "symbol": "cUSDC", + "decimals": 8, + "underlying": "0x8a9447df1FB47209D36204e6D56767a33bf20f9f", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "200000000000000", + "address": "0x43a1363AFB28235720FCbDF0C2dAb7759091F7e0" + }, + "cWBTC": { + "name": "Compound Wrapped BTC 📈", + "symbol": "cWBTC", + "decimals": 8, + "underlying": "0xD83F707f003A1f0B1535028AB356FCE2667ab855", + "contract": "CErc20", + "initial_exchange_rate_mantissa": "20000000000000000", + "address": "0x06E728D7907C164649427D2ACFD4c81669D453Bf" + } + }, + "InterestRateModel": { + "Base500bps_Slope1200bps": { + "name": "Base500bps_Slope1200bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=50000000000000000 multiplier=120000000000000000", + "base": "50000000000000000", + "slope": "120000000000000000", + "address": "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99" + }, + "Base0bps_Slope2000bps": { + "name": "Base0bps_Slope2000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=0 multiplier=200000000000000000", + "base": "0", + "slope": "200000000000000000", + "address": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa" + }, + "Base200bps_Slope3000bps": { + "name": "Base200bps_Slope3000bps", + "contract": "WhitePaperInterestRateModel", + "description": "WhitePaper baseRate=20000000000000000 multiplier=300000000000000000", + "base": "20000000000000000", + "slope": "300000000000000000", + "address": "0x6e894660985207feb7cf89Faf048998c71E8EE89" + } + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 000000000..3776f9507 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "compound-money-market", + "version": "0.2.1", + "description": "The Compound Protocol", + "main": "index.js", + "scripts": { + "console": "./script/console", + "coverage": "./script/coverage", + "deploy": "./scenario/script/repl -s ./script/scen/deploy.scen", + "lint": "./script/lint", + "repl": "./scenario/script/repl", + "scenario": "./script/scenario", + "test": "./script/test" + }, + "repository": "git@github.com:compound-finance/compound-protocol.git", + "author": "Compound Finance", + "license": "UNLICENSED", + "devDependencies": { + "bignumber.js": "8.0.1", + "ganache-cli": "^6.3.0", + "immutable": "^4.0.0-rc.12", + "mocha-junit-reporter": "^1.18.0", + "mocha-multi-reporters": "^1.1.7", + "request": "^2.88.0", + "solc": "0.5.8", + "solidity-coverage": "^0.6.3", + "solparse": "^2.2.8", + "truffle-config": "^1.1.17", + "truffle-flattener": "^1.3.0", + "truffle-resolver": "^5.0.0", + "web3": "^1.2.0" + }, + "dependencies": { + "ethlint": "^1.2.2", + "truffle": "^5.0.30", + "truffle-hdwallet-provider": "1.0.5" + } +} diff --git a/reporterConfig.json b/reporterConfig.json new file mode 100644 index 000000000..7a0c716ed --- /dev/null +++ b/reporterConfig.json @@ -0,0 +1,3 @@ +{ + "reporterEnabled": "spec, mocha-junit-reporter" +} \ No newline at end of file diff --git a/scenario/Grammar.pegjs b/scenario/Grammar.pegjs new file mode 100644 index 000000000..30bb16dbd --- /dev/null +++ b/scenario/Grammar.pegjs @@ -0,0 +1,318 @@ +// See: https://pegjs.org/online + +// Scenario Grammar + +{ + if (!Array.prototype.flat) { + Object.defineProperty(Array.prototype, 'flat', { + configurable: true, + value: function flat (x) { + var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); + + return depth ? Array.prototype.reduce.call(this, function (acc, cur) { + if (Array.isArray(cur)) { + acc.push.apply(acc, flat.call(cur, depth - 1)); + } else { + acc.push(cur); + } + + return acc; + }, []) : Array.prototype.slice.call(this); + }, + writable: true + }); + } + + function getString(str) { + let val; + if (Array.isArray(str)) { + if (str.length !== 2 || str[0] !== 'String') { + throw new Error(`Expected string, got ${str}`); + } + + val = str[1]; + } else { + val = str; + } + + if (typeof val !== 'string') { + throw new Error(`Expected string, got ${val} (${typeof val})`); + } + + return val; + } + + function expandEvent(macros, step) { + const [eventName, ...eventArgs] = step; + + if (macros[eventName]) { + let expanded = expandMacro(macros[eventName], eventArgs); + + // Recursively expand steps + return expanded.map(event => expandEvent(macros, event)).flat(); + } else { + return [step]; + } + } + + function getArgValues(eventArgs, macroArgs) { + const eventArgNameMap = {}; + const eventArgIndexed = new Array(); + const argValues = {}; + let usedNamedArg = false; + let usedSplat = false; + + eventArgs.forEach((eventArg) => { + if (eventArg.argName) { + const {argName, argValue} = eventArg; + + eventArgNameMap[argName] = argValue; + usedNamedArg = true; + } else { + if (usedNamedArg) { + throw new Error(`Cannot use positional arg after named arg in macro invokation ${JSON.stringify(eventArgs)} looking at ${eventArg.toString()}`); + } + + eventArgIndexed.push(eventArg); + } + }); + + macroArgs.forEach(({arg, def, splat}, argIndex) => { + if (usedSplat) { + throw new Error("Cannot have arg after splat arg"); + } + + let val; + if (eventArgNameMap[arg] !== undefined) { + val = eventArgNameMap[arg]; + } else if (splat) { + val = eventArgIndexed.slice(argIndex); // Clear out any remaining args + usedSplat = true; + } else if (eventArgIndexed[argIndex] !== undefined) { + val = eventArgIndexed[argIndex]; + } else if (def !== undefined) { + val = def; + } else { + throw new Error("Macro cannot find arg value for " + arg); + } + argValues[arg] = val; + }); + + return argValues; + } + + function expandMacro(macro, eventArgs) { + const argValues = getArgValues(eventArgs, macro.args); + + function expandStep(step) { + return step.map((token) => { + if (argValues[token] !== undefined) { + return argValues[token]; + } else { + if (Array.isArray(token)) { + return expandStep(token); + } else { + return token; + } + } + }); + }; + + return macro.steps.map(expandStep); + } + + function addTopLevelEl(state, el) { + const macros = state.macros; + const tests = state.tests; + const pending = state.pending; + + switch (el.type) { + case 'macro': + const macro = {[el.name]: {args: el.args, steps: el.steps}}; + + return { + tests: tests, + macros: ({...macros, ...macro}) + }; + case 'test': + const steps = el.steps; + const expandedSteps = steps.map((step) => { + return expandEvent(macros, step) + }).flat(); + + const test = {[el.test]: expandedSteps}; + + return { + tests: {...tests, ...test}, + macros: macros + } + } + } +} + +tests + = values:( + head:top_level_el + tail:(line_separator t:top_level_el { return t; })* + { return tail.reduce((acc, el) => addTopLevelEl(acc, el), addTopLevelEl({macros: {}, tests: {}}, head)); } + )? + full_ws + { return values !== null ? values.tests : {}; } + +macros + = values:( + head:top_level_el + tail:(line_separator t:top_level_el { return t; })* + { return tail.reduce((acc, el) => addTopLevelEl(acc, el), addTopLevelEl({macros: {}, tests: {}}, head)); } + )? + full_ws + { return values !== null ? values.macros : {}; } + +top_level_el + = test + / macro + / gastest + / pending + / only + / skip + +test + = full_ws? "Test" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: steps}; } + +gastest + = full_ws? "GasTest" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Gas"].concat(steps)}; } + +pending + = full_ws? "Pending" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Pending"].concat(steps)}; } + +only + = full_ws? "Only" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Only"].concat(steps)}; } + +skip + = full_ws? "Skip" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Skip"].concat(steps)}; } + +macro + = full_ws? "Macro" ws name:token ws args:args? line_separator steps:steps { return {type: 'macro', name: getString(name), args: args || [], steps: steps}; } + +args + = args:( + head:arg + tail:(ws t:args { return t; })* + { return [head].concat(tail).filter((x) => !!x); } + ) + { return args !== null ? args.flat() : []; } + +arg + = splat:("..."?) arg:token def:(ws? "=" t:token ws? { return t; })? { return { arg, def, splat }; } + +token_set + = tokens:( + head:token + tail:(ws t:token_set { return t; })* + { return [head].concat(tail).filter((x) => !!x); } + ) + { return tokens !== null ? tokens.flat() : []; } + +steps + = steps:( + head:full_expr + tail:(line_separator step:full_expr { return step; })* + { return [head].concat(tail).filter((x) => !!x); } + )? + { return steps !== null ? steps : []; } + +full_expr + = tab_separator step:step { return step; } + / comment { return null; } + / tab_separator ws { return null; } + +step + = val:expr comment? { return val; } + / comment { return null; } + / tab_separator? ws { return null; } + +expr + = ( + head:token + tail:(ws continuation? value:expr { return value })* + { return [head].concat(tail.flat(1)); } + ) + / begin_compound inner:expr end_compound { return [inner]; } + / begin_list inner:list_inner? end_list { return [["List"].concat((inner || []).flat())] }; + +comment + = ws "--" [^\n]* { return null; } + / ws "#" [^\n]* { return null; } + +token = + token1:simple_token ":" token2:simple_token { return {argName: token1, argValue: token2} } + / simple_token + +simple_token = + hex + / number + / ( t:([A-Za-z0-9_]+) { return t.join("") } ) + / string + +hex = hex:("0x" [0-9a-fA-F]+) { return ["Hex", hex.flat().flat().join("")] } +number = + n:(("-" / "+")? [0-9]+ ("." [0-9]+)? ("e" "-"? [0-9]+)?) { return ["Exactly", n.flat().flat().join("")] } + +list_inner + = ( + head:expr + tail:(ws? value:list_inner { return value })* + { return [head].concat(tail.flat()); } + ) + +begin_compound = ws "(" ws +end_compound = ws ")" ws + +begin_list = ws "[" ws +end_list = ws "]" ws + +line_separator = "\r"?"\n" +tab_separator = "\t" + / " " + +continuation = "\\" line_separator tab_separator tab_separator + +ws "whitespace" = [ \t]* +full_ws = comment full_ws + / [ \t\r\n] full_ws? + +string "string" + = quotation_mark chars:char* quotation_mark { return ["String", chars.join("")]; } + +char + = unescaped + / escape + sequence:( + '"' + / "\\" + / "/" + / "b" { return "\b"; } + / "f" { return "\f"; } + / "n" { return "\n"; } + / "r" { return "\r"; } + / "t" { return "\t"; } + / "u" digits:$(HEXDIG HEXDIG HEXDIG HEXDIG) { + return String.fromCharCode(parseInt(digits, 16)); + } + ) + { return sequence; } + +escape + = "\\" + +quotation_mark + = '"' + +unescaped + = [^\0-\x1F\x22\x5C] + +// ----- Core ABNF Rules ----- + +// See RFC 4234, Appendix B (http://tools.ietf.org/html/rfc4234). +DIGIT = [0-9] +HEXDIG = [0-9a-f]i \ No newline at end of file diff --git a/scenario/SCENARIO.md b/scenario/SCENARIO.md new file mode 100644 index 000000000..3ee226eaf --- /dev/null +++ b/scenario/SCENARIO.md @@ -0,0 +1,219 @@ + +# Types +* `name:` - Helper to describe arguments with names, not actually input this way +* `` - `True` or `False` +* `` - A standard number (e.g. `5` or `6.0` or `10.0e18`) +* `` - The local name for a given cToken when created, e.g. `cZRX` +* `` - One of: `Admin, Bank, Geoff, Torrey, Robert, Coburn, Jared` +* `` - A string, may be quoted but does not have to be if a single-word (e.g. `"Mint"` or `Mint`) +* `

` - TODO +* `` - See assertions below. + +# Events + +## Core Events + +* "History n:=5" - Prints history of actions + * E.g. "History" + * E.g. "History 10" +* `Read ...` - Reads given value and prints result + * E.g. `Read CToken cBAT ExchangeRateStored` - Returns exchange rate of cBAT +* `Assert ` - Validates given assertion, raising an exception if assertion fails + * E.g. `Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 5.0)` - Returns exchange rate of cBAT +* `FastForward n: Blocks` - For `CTokenScenario`, moves the block number forward n blocks. Note: in `CTokenScenario` the current block number is mocked (starting at 100000). Thus, this is the only way for the protocol to see a higher block number (for accruing interest). + * E.g. `FastForward 5 Blocks` - Move block number forward 5 blocks. +* `Inspect` - Prints debugging information about the world +* `Debug message:` - Same as inspect but prepends with a string +* `From ` - Runs event as the given user + * E.g. `From Geoff (CToken cZRX Mint 5e18)` +* `Invariant ` - Adds a new invariant to the world which is checked after each transaction + * E.g. `Invariant Static (CToken cZRX TotalSupply)` +* `WipeInvariants` - Removes all invariants. +* `Comptroller ` - Runs given Comptroller event + * E.g. `Comptroller _setReserveFactor 0.5` +* `CToken ` - Runs given CToken event + * E.g. `CToken cZRX Mint 5e18` +* `Erc20 ` - Runs given Erc20 event + * E.g. `Erc20 ZRX Facuet Geoff 5e18` +* `InterestRateModel ...event` - Runs given interest rate model event + * E.g. `InterestRateModel Deployed (Fixed 0.5)` +* `PriceOracle ` - Runs given Price Oracle event + * E.g. `PriceOracle SetPrice cZRX 1.5` + +## Comptroller Events + +* "Comptroller Deploy ...comptrollerParams" - Generates a new Comptroller + * E.g. "Comptroller Deploy Scenario (PriceOracle Address) 0.1 10" +* `Comptroller SetPaused action: paused:` - Pauses or unpaused given cToken function (e.g. Mint) + * E.g. `Comptroller SetPaused Mint True` +* `Comptroller SupportMarket ` - Adds support in the Comptroller for the given cToken + * E.g. `Comptroller SupportMarket cZRX` +* `Comptroller EnterMarkets ...` - User enters the given markets + * E.g. `Comptroller EnterMarkets Geoff cZRX cETH` +* `Comptroller SetMaxAssets ` - Sets (or resets) the max allowed asset count + * E.g. `Comptroller SetMaxAssets 4` +* `CToken SetOracle oracle:` - Sets the oracle + * E.g. `Comptroller SetOracle (Fixed 1.5)` +* `Comptroller SetCollateralFactor ` - Sets the collateral factor for given cToken to number + * E.g. `Comptroller SetCollateralFactor cZRX 0.1` +* `FastForward n: Blocks` - Moves the block number forward `n` blocks. Note: in `CTokenScenario` and `ComptrollerScenario` the current block number is mocked (starting at 100000). This is the only way for the protocol to see a higher block number (for accruing interest). + * E.g. `Comptroller FastForward 5 Blocks` - Move block number forward 5 blocks. + +## cToken Events + +* `CToken Deploy name: underlying: comptroller: interestRateModel: initialExchangeRate: decimals:` - Generates a new comptroller and sets to world global + * E.g. `CToken Deploy cZRX (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 18` +* `CToken AccrueInterest` - Accrues interest for given token + * E.g. `CToken cZRX AccrueInterest` +* `CToken Mint amount:` - Mints the given amount of cToken as specified user + * E.g. `CToken cZRX Mint Geoff 1.0` +* `CToken Redeem amount:` - Redeems the given amount of cToken as specified user + * E.g. `CToken cZRX Redeem Geoff 1.0e18` +* `CToken Borrow amount:` - Borrows the given amount of this cToken as specified user + * E.g. `CToken cZRX Borrow Geoff 1.0e18` +* `CToken ReduceReserves amount:` - Reduces the reserves of the cToken + * E.g. `CToken cZRX ReduceReserves 1.0e18` +* `CToken SetReserveFactor amount:` - Sets the reserve factor for the cToken + * E.g. `CToken cZRX SetReserveFactor 0.1` +* `CToken SetInterestRateModel interestRateModel:` - Sets the interest rate model for the given cToken + * E.g. `CToken cZRX SetInterestRateModel (Fixed 1.5)` +* `CToken SetComptroller comptroller:` - Sets the comptroller for the given cToken + * E.g. `CToken cZRX SetComptroller Comptroller` +* `CToken Mock variable: value:` - Mocks a given value on cToken. Note: value must be a supported mock and this will only work on a CTokenScenario contract. + * E.g. `CToken cZRX Mock totalBorrows 5.0e18` + * E.g. `CToken cZRX Mock totalReserves 0.5e18` + +## Erc-20 Events + +* `Erc20 Deploy name:` - Generates a new ERC-20 token by name + * E.g. `Erc20 Deploy ZRX` +* `Erc20 Approve
` - Adds an allowance between user and address + * E.g. `Erc20 ZRX Approve Geoff cZRX 1.0e18` +* `Erc20 Faucet
` - Adds an arbitrary balance to given user + * E.g. `Erc20 ZRX Facuet Geoff 1.0e18` + +## Price Oracle Events + +* `Deploy` - Generates a new price oracle (note: defaults to (Fixed 1.0)) + * E.g. `PriceOracle Deploy (Fixed 1.0)` + * E.g. `PriceOracle Deploy Simple` + * E.g. `PriceOracle Deploy NotPriceOracle` +* `SetPrice ` - Sets the per-ether price for the given cToken + * E.g. `PriceOracle SetPrice cZRX 1.0` + +## Interest Rate Model Events + +## Deploy + +* `Deploy params:` - Generates a new interest rate model (note: defaults to (Fixed 0.25)) + * E.g. `InterestRateModel Deploy (Fixed 0.5)` + * E.g. `InterestRateModel Deploy Whitepaper` + +# Values + +## Core Values + +* `True` - Returns true +* `False` - Returns false +* `Zero` - Returns 0 +* `Some` - Returns 100e18 +* `Little` - Returns 100e10 +* `Exactly ` - Returns a strict numerical value + * E.g. `Exactly 5.0` +* `Exp ` - Returns the mantissa for a given exp + * E.g. `Exp 5.5` +* `Precisely ` - Matches a number to given number of significant figures + * E.g. `Exactly 5.1000` - Matches to 5 sig figs +* `Anything` - Matches anything +* `Nothing` - Matches nothing +* `Default value: default:` - Returns value if truthy, otherwise default. Note: this does short-circuit +* `LastContract` - Returns the address of last constructed contract +* `User <...>` - Returns User value (see below) +* `Comptroller <...>` - Returns Comptroller value (see below) +* `CToken <...>` - Returns CToken value (see below) +* `Erc20 <...>` - Returns Erc20 value (see below) +* `InterestRateModel <...>` - Returns InterestRateModel value (see below) +* `PriceOracle <...>` - Returns PriceOracle value (see below) + +## User Values + +* `User Address` - Returns address of user + * E.g. `User Geoff Address` - Returns Geoff's address + +## Comptroller Values + +* `Comptroller Liquidity ` - Returns a given user's trued up liquidity + * E.g. `Comptroller Liquidity Geoff` +* `Comptroller MembershipLength ` - Returns a given user's length of membership + * E.g. `Comptroller MembershipLength Geoff` +* `Comptroller CheckMembership ` - Returns one if user is in asset, zero otherwise. + * E.g. `Comptroller CheckMembership Geoff cZRX` +* "Comptroller CheckListed " - Returns true if market is listed, false otherwise. + * E.g. "Comptroller CheckListed cZRX" + +## CToken Values +* `CToken UnderlyingBalance ` - Returns a user's underlying balance (based on given exchange rate) + * E.g. `CToken cZRX UnderlyingBalance Geoff` +* `CToken BorrowBalance ` - Returns a user's borrow balance (including interest) + * E.g. `CToken cZRX BorrowBalance Geoff` +* `CToken TotalBorrowBalance` - Returns the cToken's total borrow balance + * E.g. `CToken cZRX TotalBorrowBalance` +* `CToken Reserves` - Returns the cToken's total reserves + * E.g. `CToken cZRX Reserves` +* `CToken Comptroller` - Returns the cToken's comptroller + * E.g. `CToken cZRX Comptroller` +* `CToken PriceOracle` - Returns the cToken's price oracle + * E.g. `CToken cZRX PriceOracle` +* `CToken ExchangeRateStored` - Returns the cToken's exchange rate (based on balances stored) + * E.g. `CToken cZRX ExchangeRateStored` +* `CToken ExchangeRate` - Returns the cToken's current exchange rate + * E.g. `CToken cZRX ExchangeRate` + +## Erc-20 Values + +* `Erc20 Address` - Returns address of ERC-20 contract + * E.g. `Erc20 ZRX Address` - Returns ZRX's address +* `Erc20 Name` - Returns name of ERC-20 contract + * E.g. `Erc20 ZRX Address` - Returns ZRX's name +* `Erc20 Symbol` - Returns symbol of ERC-20 contract + * E.g. `Erc20 ZRX Symbol` - Returns ZRX's symbol +* `Erc20 Decimals` - Returns number of decimals in ERC-20 contract + * E.g. `Erc20 ZRX Decimals` - Returns ZRX's decimals +* `Erc20 TotalSupply` - Returns the ERC-20 token's total supply + * E.g. `Erc20 ZRX TotalSupply` + * E.g. `Erc20 cZRX TotalSupply` +* `Erc20 TokenBalance
` - Returns the ERC-20 token balance of a given address + * E.g. `Erc20 ZRX TokenBalance Geoff` - Returns a user's ZRX balance + * E.g. `Erc20 cZRX TokenBalance Geoff` - Returns a user's cZRX balance + * E.g. `Erc20 ZRX TokenBalance cZRX` - Returns cZRX's ZRX balance +* `Erc20 Allowance owner:
spender:
` - Returns the ERC-20 allowance from owner to spender + * E.g. `Erc20 ZRX Allowance Geoff Torrey` - Returns the ZRX allowance of Geoff to Torrey + * E.g. `Erc20 cZRX Allowance Geoff Coburn` - Returns the cZRX allowance of Geoff to Coburn + * E.g. `Erc20 ZRX Allowance Geoff cZRX` - Returns the ZRX allowance of Geoff to the cZRX cToken + +## PriceOracle Values + +* `Address` - Gets the address of the global price oracle +* `Price asset:
` - Gets the price of the given asset + +## Interest Rate Model Values + +* `Address` - Gets the address of the global interest rate model + +# Assertions + +* `Equal given: expected:` - Asserts that given matches expected. + * E.g. `Assert Equal (Exactly 0) Zero` + * E.g. `Assert Equal (CToken cZRX TotalSupply) (Exactly 55)` + * E.g. `Assert Equal (CToken cZRX Comptroller) (Comptroller Address)` +* `True given:` - Asserts that given is true. + * E.g. `Assert True (Comptroller CheckMembership Geoff cETH)` +* `False given:` - Asserts that given is false. + * E.g. `Assert False (Comptroller CheckMembership Geoff cETH)` +* `Failure error: info: detail:` - Asserts that last transaction had a graceful failure with given error, info and detail. + * E.g. `Assert Failure UNAUTHORIZED SUPPORT_MARKET_OWNER_CHECK` + * E.g. `Assert Failure MATH_ERROR MINT_CALCULATE_BALANCE 5` +* `Revert` - Asserts that the last transaction reverted. +* `Success` - Asserts that the last transaction completed successfully (that is, did not revert nor emit graceful failure). +* `Log name: ((key: value:) ...)` - Asserts that last transaction emitted log with given name and key-value pairs. + * E.g. `Assert Log Minted (("account" (User Geoff address)) ("amount" (Exactly 55)))` diff --git a/scenario/package.json b/scenario/package.json new file mode 100644 index 000000000..37d5c8b5c --- /dev/null +++ b/scenario/package.json @@ -0,0 +1,30 @@ +{ + "name": "compound-money-market", + "version": "0.2.1", + "description": "The Compound Money Market", + "main": "index.js", + "scripts": { + "build": "./script/webpack" + }, + "repository": "git@github.com:compound-finance/money-market.git", + "author": "Compound Finance", + "license": "UNLICENSED", + "devDependencies": { + "request": "^2.88.0", + "solparse": "^2.2.8", + "ts-loader": "^5.3.3", + "ts-pegjs": "^0.2.2", + "typescript": "^3.3.3", + "webpack": "^4.29.6", + "webpack-bundle-analyzer": "^3.1.0", + "webpack-cli": "^3.3.0" + }, + "dependencies": { + "bignumber.js": "8.0.1", + "ethers": "^4.0.0-beta.1", + "immutable": "^4.0.0-rc.12", + "truffle-flattener": "^1.3.0", + "truffle-hdwallet-provider": "1.0.5", + "web3": "1.0.0-beta.37" + } +} diff --git a/scenario/script/generate_parser b/scenario/script/generate_parser new file mode 100755 index 000000000..1d889fcdd --- /dev/null +++ b/scenario/script/generate_parser @@ -0,0 +1,11 @@ +#!/bin/bash + +dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +scenario_dir="$(cd $dir/.. && pwd)" + +"$scenario_dir/node_modules/.bin/pegjs" \ + --plugin "$scenario_dir/node_modules/ts-pegjs" \ + -o "$scenario_dir/src/Parser.ts" \ + --cache \ + --allowed-start-rules tests,step,macros \ + "$scenario_dir/Grammar.pegjs" diff --git a/scenario/script/repl b/scenario/script/repl new file mode 100755 index 000000000..28f51b39e --- /dev/null +++ b/scenario/script/repl @@ -0,0 +1,78 @@ +#!/usr/bin/env sh + +set -eo + +dir=`dirname $0` +tsc_root="$(cd "$dir/.." && pwd)" +proj_root="$(cd "$dir/../.." && pwd)" +networks_root="$(cd "$dir/../../networks" && pwd)" +test_root="$(cd "$dir/../../test" && pwd)" +contracts_root="$(cd "$dir/../../contracts" && pwd)" +network=${NETWORK:-development} +script="$SCRIPT" +verbose="$VERBOSE" +dry_run="$DRY_RUN" +no_tsc="$NO_TSC" + +usage() { echo "$0 usage:" && grep ".)\ #" $0; exit 0; } +while getopts ":hdn:e:s:vt" arg; do + case $arg in + c) # Don't compile + no_compile="true" + ;; + d) # Dry run + dry_run="true" + ;; + e) # Add variables for script (key=value,key2=value2) + env_vars="$OPTARG" + ;; + n) # Specify network + network=$OPTARG + ;; + s) # Specify a script to run + if [[ "$OSTYPE" == "darwin"* ]]; then + # Darwin doesn't support readlink -f to get absolute path... + script=$OPTARG + else + script=$(readlink -f "$OPTARG") + fi + + [ ! -f "$script" ] \ + && echo "Cannot find script $script" \ + && exit 1 + ;; + t) # Don't build TSC + no_tsc="true" + ;; + + v) # Verbose + verbose="true" + ;; + + h | *) # Display help. + usage + exit 0 + ;; + esac +done + +if [ $network = "test" -o $network = "development" -o -n "$add_test_contracts" ]; then + function cleanup { + mv "$contracts_root/test" "$test_root/contracts" + } + + trap cleanup EXIT + + mv "$test_root/contracts" "$contracts_root/test" + + # Compile with test contracts + [[ -z $no_compile ]] && solc --combined-json bin,abi --optimize contracts/*.sol contracts/**/*.sol --allow-paths ./contracts,./contracts/test > networks/${network}-contracts.json +else + # Compile without test contracts + [[ -z $no_compile ]] && solc --combined-json bin,abi --optimize contracts/*.sol > networks/${network}-contracts.json +fi + +[[ ! -d ./.tsbuilt || -z $no_tsc ]] && . "$dir/tsc" + + +proj_root="$proj_root" env_vars="$env_vars" dry_run="$dry_run" script="$script" network="$network" verbose="$verbose" npx truffle exec --network "$network" "$tsc_root/.tsbuilt/Repl.js" diff --git a/scenario/script/tsc b/scenario/script/tsc new file mode 100755 index 000000000..5d45f8aff --- /dev/null +++ b/scenario/script/tsc @@ -0,0 +1,14 @@ +#!/bin/sh + +set -eo + +dir=`dirname $0` +scenario_dir="$(cd $dir/.. && pwd)" + +if [ ! -d "$scenario_dir/node_modules" ]; then + echo "Getting scenario packages..." + cd "$scenario_dir" && yarn +fi + +echo "Building Scenario Runner..." +cd "$scenario_dir" && node "$scenario_dir/node_modules/.bin/tsc" ${TSC_ARGS-"--skipLibCheck"} diff --git a/scenario/script/webpack b/scenario/script/webpack new file mode 100755 index 000000000..4e7c69ad0 --- /dev/null +++ b/scenario/script/webpack @@ -0,0 +1,16 @@ +#!/bin/bash + +dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +scenario_dir="$(cd $dir/.. && pwd)" + +cd "$scenario_dir" && + mkdir -p ./build && + ./node_modules/.bin/webpack \ + --mode production \ + --config ./webpack.config.js \ + --entry ./src/Web.ts \ + --module-bind 'ts=ts-loader' \ + --module-bind 'exports-loader?parse' \ + --resolve-extensions ".ts,.js" \ + --output-library-target window \ + --output ./build/scenario.js diff --git a/scenario/src/Accounts.ts b/scenario/src/Accounts.ts new file mode 100644 index 000000000..2845c5d75 --- /dev/null +++ b/scenario/src/Accounts.ts @@ -0,0 +1,48 @@ +import {World} from './World'; +import {Map} from 'immutable'; + +export const accountMap = { + "default": 0, + "root": 0, + "admin": 0, + "first": 0, + + "bank": 1, + "second": 1, + + "geoff": 2, + "third": 2, + + "torrey": 3, + "fourth": 3, + + "robert": 4, + "fifth": 4, + + "coburn": 5, + "sixth": 5, + + "jared": 6, + "seventh": 6 +}; + +export interface Account { + name: string + address: string +} + +export type Accounts = Map + +export function accountAliases(index: number): string[] { + return Object.entries(accountMap).filter(([k,v]) => v === index).map(([k,v]) => k); +} + +export function loadAccounts(accounts: string[]): Accounts { + return Object.entries(accountMap).reduce((acc, [name, index]) => { + if (accounts[index]) { + return acc.set(name, { name: name, address: accounts[index] }); + } else { + return acc; + } + }, >Map({})); +} diff --git a/scenario/src/Action.ts b/scenario/src/Action.ts new file mode 100644 index 000000000..81eaabc11 --- /dev/null +++ b/scenario/src/Action.ts @@ -0,0 +1,15 @@ +import {Invokation} from './Invokation'; + +export class Action { + log: string; + invokation: Invokation; + + constructor(log: string, invokation: Invokation) { + this.log = log; + this.invokation = invokation; + } + + toString() { + return `Action: log=${this.log}, result=${this.invokation.toString()}`; + } +} diff --git a/scenario/src/Artifact.ts b/scenario/src/Artifact.ts new file mode 100644 index 000000000..3083e932e --- /dev/null +++ b/scenario/src/Artifact.ts @@ -0,0 +1,5 @@ + +export interface Artifact {} +export interface Artifacts { + require(file: string): Artifact +} diff --git a/scenario/src/Assert.ts b/scenario/src/Assert.ts new file mode 100644 index 000000000..e604371f3 --- /dev/null +++ b/scenario/src/Assert.ts @@ -0,0 +1,21 @@ +export interface Assert { + fail(x: any, y: any, reason: string) + equal(x: any, y: any, reason: string) + deepEqual(x: any, y: any, reason: string) +} + +export const throwAssert: Assert = { + fail: (x, y, reason) => { + throw new Error(reason) + }, + equal: (x, y, reason) => { + if (x != y) { + throw new Error(reason); + } + }, + deepEqual: (x, y, reason) => { + if (JSON.stringify(x) != JSON.stringify(y)) { + throw new Error(reason); + } + } +}; diff --git a/scenario/src/Builder/CTokenBuilder.ts b/scenario/src/Builder/CTokenBuilder.ts new file mode 100644 index 000000000..d90bf2253 --- /dev/null +++ b/scenario/src/Builder/CTokenBuilder.ts @@ -0,0 +1,244 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {CToken} from '../Contract/CToken'; +import {Invokation, invoke} from '../Invokation'; +import { + getAddressV, + getExpNumberV, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + NumberV, + StringV +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract, getTestContract} from '../Contract'; + +const CErc20Contract = getContract('CErc20'); +const CEtherContract = getContract('CEther'); +const CErc20ScenarioContract = getTestContract('CErc20Scenario'); +const CEtherScenarioContract = getTestContract('CEtherScenario'); +const CEvilContract = getTestContract('CEvil'); + +export interface TokenData { + invokation: Invokation + name: string + symbol: string + decimals: number + underlying: string + address?: string + contract: string + initial_exchange_rate_mantissa: string +} + +export async function buildCToken(world: World, from: string, params: Event): Promise<{world: World, cToken: CToken, tokenData: TokenData}> { + const fetchers = [ + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` + #### Scenario + + * "Scenario symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: " - A CToken Scenario for local testing + * E.g. "CToken Deploy Scenario cZRX (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" + `, + "Scenario", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("underlying", getAddressV), + new Arg("comptroller", getAddressV), + new Arg("interestRateModel", getAddressV), + new Arg("initialExchangeRate", getExpNumberV), + new Arg("decimals", getNumberV) + ], + async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals}) => { + return { + invokation: await CErc20ScenarioContract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: underlying.val, + contract: 'CErc20Scenario', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` + #### CEtherScenario + + * "CEtherScenario symbol: name: comptroller:
interestRateModel:
initialExchangeRate: decimals: " - A CToken Scenario for local testing + * E.g. "CToken Deploy CEtherScenario (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" + `, + "CEtherScenario", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("comptroller", getAddressV), + new Arg("interestRateModel", getAddressV), + new Arg("initialExchangeRate", getExpNumberV), + new Arg("decimals", getNumberV) + ], + async (world, {symbol, name, comptroller, interestRateModel, initialExchangeRate, decimals}) => { + return { + invokation: await CEtherScenarioContract.deploy(world, from, [name.val, symbol.val, decimals.val, comptroller.val, interestRateModel.val, initialExchangeRate.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: "", + contract: 'CEtherScenario', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` + #### CEther + + * "CEther symbol: name: comptroller:
interestRateModel:
initialExchangeRate: decimals: " - A CToken Scenario for local testing + * E.g. "CToken Deploy CEther cETH (Comptroller Address) (InterestRateModel Address) 1.0 8" + `, + "CEther", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("comptroller", getAddressV), + new Arg("interestRateModel", getAddressV), + new Arg("initialExchangeRate", getExpNumberV), + new Arg("decimals", getNumberV) + ], + async (world, {symbol, name, comptroller, interestRateModel, initialExchangeRate, decimals}) => { + return { + invokation: await CEtherContract.deploy(world, from, [comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: "", + contract: 'CEther', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` + #### CErc20 + + * "CErc20 symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: " - A official CToken contract + * E.g. "CToken Deploy CErc20 cZRX (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" + `, + "CErc20", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("underlying", getAddressV), + new Arg("comptroller", getAddressV), + new Arg("interestRateModel", getAddressV), + new Arg("initialExchangeRate", getExpNumberV), + new Arg("decimals", getNumberV) + ], + async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals}) => { + return { + invokation: await CErc20Contract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: underlying.val, + contract: 'CErc20', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` + #### CEvil + + * "CEvil symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: " - A malicious CToken contract + * E.g. "CToken Deploy CEvil cEVL (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" + `, + "CEvil", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("underlying", getAddressV), + new Arg("comptroller", getAddressV), + new Arg("interestRateModel", getAddressV), + new Arg("initialExchangeRate", getExpNumberV), + new Arg("decimals", getNumberV) + ], + async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals}) => { + return { + invokation: await CEvilContract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: underlying.val, + contract: 'CEvil', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` + #### Standard + + * "symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: " - A official CToken contract + * E.g. "CToken Deploy cZRX (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" + `, + "Standard", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("underlying", getAddressV), + new Arg("comptroller", getAddressV), + new Arg("interestRateModel", getAddressV), + new Arg("initialExchangeRate", getExpNumberV), + new Arg("decimals", getNumberV) + ], + async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals}) => { + // Note: we're going to use the scenario contract as the standard deployment on local networks + if (world.isLocalNetwork()) { + return { + invokation: await CErc20ScenarioContract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: underlying.val, + contract: 'CErc20Scenario', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } else { + return { + invokation: await CErc20Contract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val]), + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + underlying: underlying.val, + contract: 'CErc20', + initial_exchange_rate_mantissa: initialExchangeRate.encode().toString() + }; + } + }, + {catchall: true} + ) + ]; + + let tokenData = await getFetcherValue("DeployCToken", fetchers, world, params); + let invokation = tokenData.invokation; + delete tokenData.invokation; + + if (invokation.error) { + throw invokation.error; + } + + const cToken = invokation.value!; + tokenData.address = cToken._address; + + world = await storeAndSaveContract( + world, + cToken, + tokenData.symbol, + invokation, + [ + { index: ['cTokens', tokenData.symbol], data: tokenData }, + { index: ['Tokens', tokenData.symbol], data: tokenData } + ] + ); + + return {world, cToken, tokenData}; +} diff --git a/scenario/src/Builder/ComptrollerImplBuilder.ts b/scenario/src/Builder/ComptrollerImplBuilder.ts new file mode 100644 index 000000000..33e04c6a5 --- /dev/null +++ b/scenario/src/Builder/ComptrollerImplBuilder.ts @@ -0,0 +1,175 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; +import {Invokation, invoke} from '../Invokation'; +import { + getAddressV, + getExpNumberV, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + NothingV, + NumberV, + StringV +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract, getTestContract} from '../Contract'; + +const ComptrollerContract = getContract("Comptroller"); +const ComptrollerScenarioContract = getTestContract('ComptrollerScenario'); +const ComptrollerBorkedContract = getTestContract('ComptrollerBorked'); +const ComptrollerBoolContract = getTestContract('BoolComptroller'); + +export interface ComptrollerImplData { + invokation: Invokation + name: string + contract: string + description: string +} + +export async function buildComptrollerImpl(world: World, from: string, event: Event): Promise<{world: World, comptrollerImpl: ComptrollerImpl, comptrollerImplData: ComptrollerImplData}> { + const fetchers = [ + new Fetcher<{name: StringV | NothingV}, ComptrollerImplData>(` + #### Scenario + + * "Scenario name:" - The Comptroller Scenario for local testing + * E.g. "ComptrollerImpl Deploy Scenario MyScen" + `, + "Scenario", + [ + new Arg("name", getStringV, {nullable: true}), + ], + async (world, {name}) => ({ + invokation: await ComptrollerScenarioContract.deploy(world, from, []), + name: name instanceof StringV ? name.val : "Comptroller", + contract: "ComptrollerScenario", + description: "Scenario Comptroller Impl" + }) + ), + new Fetcher<{name: StringV | NothingV}, ComptrollerImplData>(` + #### Standard + + * "Standard name:" - The standard Comptroller contract + * E.g. "Comptroller Deploy Standard MyStandard" + `, + "Standard", + [ + new Arg("name", getStringV, {nullable: true}) + ], + async (world, {name}) => { + let invokation; + let contract; + + return { + invokation: await ComptrollerContract.deploy(world, from, []), + name: name instanceof StringV ? name.val : "Comptroller", + contract: "Comptroller", + description: "Standard Comptroller Impl" + }; + }, + ), + new Fetcher<{name: StringV | NothingV}, ComptrollerImplData>(` + #### YesNo + + * "YesNo name:" - The bool Comptroller contract + * E.g. "Comptroller Deploy YesNo MyBool" + `, + "YesNo", + [ + new Arg("name", getStringV, {nullable: true}) + ], + async (world, {name}) => { + let invokation; + let contract; + + return { + invokation: await ComptrollerBoolContract.deploy(world, from, []), + name: name instanceof StringV ? name.val : "Comptroller", + contract: "Comptroller", + description: "YesNo Comptroller" + }; + }, + ), + new Fetcher<{name: StringV | NothingV}, ComptrollerImplData>(` + #### Borked + + * "Borked name:" - A Borked Comptroller for testing + * E.g. "ComptrollerImpl Deploy Borked MyBork" + `, + "Borked", + [ + new Arg("name", getStringV, {nullable: true}) + ], + async (world, {name}) => ({ + invokation: await ComptrollerBorkedContract.deploy(world, from, []), + name: name instanceof StringV ? name.val : "Comptroller", + contract: "ComptrollerBorked", + description: "Borked Comptroller Impl" + }) + ), + new Fetcher<{name: StringV | NothingV}, ComptrollerImplData>(` + #### Default + + * "name:" - The standard Comptroller contract + * E.g. "ComptrollerImpl Deploy MyDefault" + `, + "Default", + [ + new Arg("name", getStringV, {nullable: true}) + ], + async (world, {name}) => { + let invokation; + let contract; + + if (world.isLocalNetwork()) { + // Note: we're going to use the scenario contract as the standard deployment on local networks + return { + invokation: await ComptrollerScenarioContract.deploy(world, from, []), + name: name instanceof StringV ? name.val : "Comptroller", + contract: "ComptrollerScenario", + description: "Scenario Comptroller Impl" + }; + } else { + return { + invokation: await ComptrollerContract.deploy(world, from, []), + name: name instanceof StringV ? name.val : "Comptroller", + contract: "Comptroller", + description: "Standard Comptroller Impl" + }; + } + }, + {catchall: true} + ) + ]; + + let comptrollerImplData = await getFetcherValue("DeployComptrollerImpl", fetchers, world, event); + let invokation = comptrollerImplData.invokation; + delete comptrollerImplData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const comptrollerImpl = invokation.value!; + + world = await storeAndSaveContract( + world, + comptrollerImpl, + comptrollerImplData.name, + invokation, + [ + { + index: ['Comptroller', comptrollerImplData.name], + data: { + address: comptrollerImpl._address, + contract: comptrollerImplData.contract, + description: comptrollerImplData.description + } + } + ] + ); + + return {world, comptrollerImpl, comptrollerImplData}; +} diff --git a/scenario/src/Builder/Erc20Builder.ts b/scenario/src/Builder/Erc20Builder.ts new file mode 100644 index 000000000..8e76791e8 --- /dev/null +++ b/scenario/src/Builder/Erc20Builder.ts @@ -0,0 +1,185 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {Erc20} from '../Contract/Erc20'; +import {Invokation, invoke} from '../Invokation'; +import { + getAddressV, + getCoreValue, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + NumberV, + StringV, + Value +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract, getTestContract} from '../Contract'; +import {encodeABI} from '../Utils'; + +const FaucetTokenHarness = getContract("FaucetToken"); +const FaucetTokenNonStandardHarness = getContract("FaucetNonStandardToken"); +const FaucetTokenReEntrantHarness = getContract("FaucetTokenReEntrantHarness"); +const EvilTokenHarness = getContract("EvilToken"); +const WBTCTokenHarness = getContract("WBTCToken"); + +export interface TokenData { + invokation: Invokation, + description: string, + name: string, + symbol: string, + decimals: number, + address?: string, + contract: string +} + +export async function buildErc20(world: World, from: string, event: Event): Promise<{world: World, erc20: Erc20, tokenData: TokenData}> { + const fetchers = [ + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV}, TokenData>(` + #### NonStandard + + * "NonStandard symbol: name: decimals:" - A non-standard token, like BAT + * E.g. "Erc20 Deploy NonStandard BAT 18" + `, + "NonStandard", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("decimals", getNumberV, {default: new NumberV(18)}), + ], + async (world, {symbol, name, decimals}) => { + return { + invokation: await FaucetTokenNonStandardHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val]), + description: "NonStandard", + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + contract: 'FaucetNonStandardToken' + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, fun:StringV, reEntryFunSig: StringV, reEntryFunArgs: StringV[]}, TokenData>(` + #### ReEntrant + + * "ReEntrant symbol: name:string fun: funSig: ...funArgs:" - A token that loves to call back to spook its caller + * E.g. "Erc20 Deploy ReEntrant PHREAK PHREAK "transfer" "mint(uint256)" 0 - A token that will call back to a CToken's mint function + + Note: valid functions: totalSupply, balanceOf, transfer, transferFrom, approve, allowance + `, + "ReEntrant", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("fun", getStringV), + new Arg("reEntryFunSig", getStringV), + new Arg("reEntryFunArgs", getStringV, {variadic: true, mapped: true}) + ], + async (world, {symbol, name, fun, reEntryFunSig, reEntryFunArgs}) => { + const fnData = encodeABI(world, reEntryFunSig.val, reEntryFunArgs.map((a) => a.val)); + + return { + invokation: await FaucetTokenReEntrantHarness.deploy(world, from, [0, name.val, 18, symbol.val, fnData, fun.val]), + description: "ReEntrant", + name: name.val, + symbol: symbol.val, + decimals: 18, + contract: 'FaucetTokenReEntrantHarness' + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV}, TokenData>(` + #### Evil + + * "Evil symbol: name: decimals:" - A less vanilla ERC-20 contract that fails transfers + * E.g. "Erc20 Deploy Evil BAT 18" + `, + "Evil", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("decimals", getNumberV, {default: new NumberV(18)}) + ], + async (world, {symbol, name, decimals}) => { + return { + invokation: await EvilTokenHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val]), + description: "Evil", + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + contract: 'EvilToken' + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV}, TokenData>(` + #### Standard + + * "Standard symbol: name: decimals:" - A vanilla ERC-20 contract + * E.g. "Erc20 Deploy Standard BAT 18" + `, + "Standard", + [ + new Arg("symbol", getStringV), + new Arg("name", getStringV), + new Arg("decimals", getNumberV, {default: new NumberV(18)}) + ], + async (world, {symbol, name, decimals}) => { + return { + invokation: await FaucetTokenHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val]), + description: "Standard", + name: name.val, + symbol: symbol.val, + decimals: decimals.toNumber(), + contract: 'FaucetToken' + }; + } + ), + new Fetcher<{symbol: StringV, name: StringV}, TokenData>(` + #### WBTC + + * "WBTC symbol: name:" - The WBTC contract + * E.g. "Erc20 Deploy WBTC WBTC \"Wrapped Bitcoin\"" + `, + "WBTC", + [ + new Arg("symbol", getStringV, {default: new StringV("WBTC")}), + new Arg("name", getStringV, {default: new StringV("Wrapped Bitcoin")}) + ], + async (world, {symbol, name}) => { + let decimals = 8; + + return { + invokation: await WBTCTokenHarness.deploy(world, from, []), + description: "WBTC", + name: name.val, + symbol: symbol.val, + decimals: decimals, + contract: 'WBTCToken' + }; + } + ) + ]; + + let tokenData = await getFetcherValue("DeployErc20", fetchers, world, event); + let invokation = tokenData.invokation; + delete tokenData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const erc20 = invokation.value!; + tokenData.address = erc20._address; + + world = await storeAndSaveContract( + world, + erc20, + tokenData.symbol, + invokation, + [ + { index: ['Tokens', tokenData.symbol], data: tokenData } + ] + ); + + return {world, erc20, tokenData}; +} diff --git a/scenario/src/Builder/InterestRateModelBuilder.ts b/scenario/src/Builder/InterestRateModelBuilder.ts new file mode 100644 index 000000000..29280451f --- /dev/null +++ b/scenario/src/Builder/InterestRateModelBuilder.ts @@ -0,0 +1,100 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {InterestRateModel} from '../Contract/InterestRateModel'; +import {Invokation, invoke} from '../Invokation'; +import { + getExpNumberV, + getPercentV, + getStringV, +} from '../CoreValue'; +import { + EventV, + NumberV, + StringV, +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract, getTestContract} from '../Contract'; + +const FixedInterestRateModel = getTestContract('InterestRateModelHarness'); +const WhitePaperInterestRateModel = getContract('WhitePaperInterestRateModel'); + +export interface InterestRateModelData { + invokation: Invokation + address?: string + name: string + contract: string + description: string + base?: string + slope?: string +} + +export async function buildInterestRateModel(world: World, from: string, event: Event): Promise<{world: World, interestRateModel: InterestRateModel, interestRateModelData: InterestRateModelData}> { + const fetchers = [ + new Fetcher<{name: StringV, rate: NumberV}, InterestRateModelData>(` + #### Fixed + + * "Fixed name: rate:" - Fixed interest **per-block** rate + * E.g. "InterestRateModel Deploy Fixed MyInterestRateModel 0.5" + `, + "Fixed", + [ + new Arg("name", getStringV), + new Arg("rate", getPercentV), + ], + async (world, {name, rate}) => ({ + invokation: await FixedInterestRateModel.deploy(world, from, [rate.val]), + name: name.val, + contract: "InterestRateModelHarness", + description: `Fixed rate ${rate.show()} per block` + }) + ), + + new Fetcher<{name: StringV, baseRate: NumberV, multiplier: NumberV}, InterestRateModelData>(` + #### WhitePaper + + * "WhitePaper name: baseRate: multiplier:" - The WhitePaper interest rate + * E.g. "InterestRateModel Deploy WhitePaper MyInterestRateModel 0.05 0.2" - 5% base rate and 20% utilization multiplier + `, + "WhitePaper", + [ + new Arg("name", getStringV), + new Arg("baseRate", getExpNumberV), + new Arg("multiplier", getExpNumberV) + ], + async (world, {name, baseRate, multiplier}) => ({ + invokation: await WhitePaperInterestRateModel.deploy(world, from, [baseRate.val, multiplier.val]), + name: name.val, + contract: "WhitePaperInterestRateModel", + description: `WhitePaper baseRate=${baseRate.val} multiplier=${multiplier.val}`, + base: baseRate.encode().toString(), + slope: multiplier.encode().toString() + }) + ) + ]; + + let interestRateModelData = await getFetcherValue("DeployInterestRateModel", fetchers, world, event); + let invokation = interestRateModelData.invokation; + delete interestRateModelData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const interestRateModel = invokation.value!; + interestRateModelData.address = interestRateModel._address; + + world = await storeAndSaveContract( + world, + interestRateModel, + interestRateModelData.name, + invokation, + [ + { + index: ['InterestRateModel', interestRateModelData.name], + data: interestRateModelData + } + ] + ); + + return {world, interestRateModel, interestRateModelData}; +} diff --git a/scenario/src/Builder/MaximillionBuilder.ts b/scenario/src/Builder/MaximillionBuilder.ts new file mode 100644 index 000000000..c8eb81a03 --- /dev/null +++ b/scenario/src/Builder/MaximillionBuilder.ts @@ -0,0 +1,64 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {Maximillion} from '../Contract/Maximillion'; +import {Invokation} from '../Invokation'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract} from '../Contract'; +import {getAddressV} from '../CoreValue'; +import {AddressV} from '../Value'; + +const MaximillionContract = getContract("Maximillion"); + +export interface MaximillionData { + invokation: Invokation, + description: string, + cEtherAddress: string, + address?: string +} + +export async function buildMaximillion(world: World, from: string, event: Event): Promise<{world: World, maximillion: Maximillion, maximillionData: MaximillionData}> { + const fetchers = [ + new Fetcher<{cEther: AddressV}, MaximillionData>(` + #### Maximillion + + * "" - Maximum Eth Repays Contract + * E.g. "Maximillion Deploy" + `, + "Maximillion", + [ + new Arg("cEther", getAddressV) + ], + async (world, {cEther}) => { + return { + invokation: await MaximillionContract.deploy(world, from, [cEther.val]), + description: "Maximillion", + cEtherAddress: cEther.val + }; + }, + {catchall: true} + ) + ]; + + let maximillionData = await getFetcherValue("DeployMaximillion", fetchers, world, event); + let invokation = maximillionData.invokation; + delete maximillionData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const maximillion = invokation.value!; + maximillionData.address = maximillion._address; + + world = await storeAndSaveContract( + world, + maximillion, + 'Maximillion', + invokation, + [ + { index: ['Maximillion'], data: maximillionData } + ] + ); + + return {world, maximillion, maximillionData}; +} diff --git a/scenario/src/Builder/PriceOracleBuilder.ts b/scenario/src/Builder/PriceOracleBuilder.ts new file mode 100644 index 000000000..5888bd623 --- /dev/null +++ b/scenario/src/Builder/PriceOracleBuilder.ts @@ -0,0 +1,165 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {PriceOracle} from '../Contract/PriceOracle'; +import {Invokation, invoke} from '../Invokation'; +import { + getAddressV, + getExpNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + EventV, + NothingV, + NumberV, + StringV +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract, getTestContract} from '../Contract'; + +const FixedPriceOracle = getTestContract('FixedPriceOracle'); +const SimplePriceOracle = getContract('SimplePriceOracle'); +const AnchorPriceOracle = getContract('AnchorPriceOracle'); +const NotPriceOracle = getTestContract('NotPriceOracle'); +const PriceOracleInterface = getTestContract('PriceOracle'); + +export interface PriceOracleData { + invokation?: Invokation, + contract?: PriceOracle, + description: string, + address?: string +} + +export async function buildPriceOracle(world: World, from: string, event: Event): Promise<{world: World, priceOracle: PriceOracle, priceOracleData: PriceOracleData}> { + const fetchers = [ + new Fetcher<{price: NumberV}, PriceOracleData>(` + #### Fixed + + * "Fixed price:" - Fixed price + * E.g. "PriceOracle Deploy (Fixed 20.0)" + `, + "Fixed", + [ + new Arg("price", getExpNumberV), + ], + async (world, {price}) => { + return { + invokation: await FixedPriceOracle.deploy(world, from, [price.val]), + description: "Fixed Price Oracle" + }; + } + ), + new Fetcher<{}, PriceOracleData>(` + #### Simple + + * "Simple" - The a simple price oracle that has a harness price setter + * E.g. "PriceOracle Deploy Simple" + `, + "Simple", + [], + async (world, {}) => { + return { + invokation: await SimplePriceOracle.deploy(world, from, []), + description: "Simple Price Oracle" + }; + } + ), + new Fetcher<{poster: AddressV}, PriceOracleData>(` + #### Anchor + + * "Anchor " - The anchor price oracle that caps price movements to anchors + * E.g. "PriceOracle Deploy Anchor 0x..." + `, + "Anchor", + [ + new Arg("poster", getAddressV) + ], + async (world, {poster}) => { + return { + invokation: await AnchorPriceOracle.deploy(world, from, [poster.val]), + description: "Anchor Price Oracle", + poster: poster.val + }; + } + ), + new Fetcher<{}, PriceOracleData>(` + #### NotPriceOracle + + * "NotPriceOracle" - Not actually a price oracle + * E.g. "PriceOracle Deploy NotPriceOracle" + `, + "NotPriceOracle", + [], + async (world, {}) => { + return { + invokation: await NotPriceOracle.deploy(world, from, []), + description: "Not a Price Oracle" + }; + } + ) + ]; + + let priceOracleData = await getFetcherValue("DeployPriceOracle", fetchers, world, event); + let invokation = priceOracleData.invokation!; + delete priceOracleData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const priceOracle = invokation.value!; + priceOracleData.address = priceOracle._address; + + world = await storeAndSaveContract( + world, + priceOracle, + 'PriceOracle', + invokation, + [ + { index: ['PriceOracle'], data: priceOracleData } + ] + ); + + return {world, priceOracle, priceOracleData}; +} + +export async function setPriceOracle(world: World, event: Event): Promise<{world: World, priceOracle: PriceOracle, priceOracleData: PriceOracleData}> { + const fetchers = [ + new Fetcher<{address: AddressV, description: StringV}, PriceOracleData>(` + #### Standard + + * "Standard" - The standard price oracle + * E.g. "PriceOracle Set Standard \"0x...\" \"Standard Price Oracle\"" + `, + "Standard", + [ + new Arg("address", getAddressV), + new Arg("description", getStringV), + ], + async (world, {address, description}) => { + return { + contract: await PriceOracleInterface.at(world, address.val), + description: description.val + }; + } + ) + ]; + + let priceOracleData = await getFetcherValue("SetPriceOracle", fetchers, world, event); + let priceOracle = priceOracleData.contract!; + delete priceOracleData.contract; + + priceOracleData.address = priceOracle._address; + + world = await storeAndSaveContract( + world, + priceOracle, + 'PriceOracle', + null, + [ + { index: ['PriceOracle'], data: priceOracleData } + ] + ); + + return {world, priceOracle, priceOracleData}; +} diff --git a/scenario/src/Builder/PriceOracleProxyBuilder.ts b/scenario/src/Builder/PriceOracleProxyBuilder.ts new file mode 100644 index 000000000..4b3033429 --- /dev/null +++ b/scenario/src/Builder/PriceOracleProxyBuilder.ts @@ -0,0 +1,70 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {PriceOracleProxy} from '../Contract/PriceOracleProxy'; +import {Invokation} from '../Invokation'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract} from '../Contract'; +import {getAddressV} from '../CoreValue'; +import {AddressV} from '../Value'; + +const PriceOracleProxyContract = getContract("PriceOracleProxy"); + +export interface PriceOracleProxyData { + invokation?: Invokation, + contract?: PriceOracleProxy, + description: string, + address?: string, + cEther: string, + cUSDC: string, +} + +export async function buildPriceOracleProxy(world: World, from: string, event: Event): Promise<{world: World, priceOracleProxy: PriceOracleProxy, invokation: Invokation}> { + const fetchers = [ + new Fetcher<{comptroller: AddressV, priceOracle: AddressV, cEther: AddressV, cUSDC: AddressV}, PriceOracleProxyData>(` + #### Price Oracle Proxy + + * "Deploy " - The Price Oracle which proxies to a backing oracle + * E.g. "PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) cETH cUSDC" + `, + "PriceOracleProxy", + [ + new Arg("comptroller", getAddressV), + new Arg("priceOracle", getAddressV), + new Arg("cEther", getAddressV), + new Arg("cUSDC", getAddressV) + ], + async (world, {comptroller, priceOracle, cEther, cUSDC}) => { + return { + invokation: await PriceOracleProxyContract.deploy(world, from, [comptroller.val, priceOracle.val, cEther.val, cUSDC.val]), + description: "Price Oracle Proxy", + cEther: cEther.val, + cUSDC: cUSDC.val + }; + }, + {catchall: true} + ) + ]; + + let priceOracleProxyData = await getFetcherValue("DeployPriceOracleProxy", fetchers, world, event); + let invokation = priceOracleProxyData.invokation!; + delete priceOracleProxyData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const priceOracleProxy = invokation.value!; + priceOracleProxyData.address = priceOracleProxy._address; + + world = await storeAndSaveContract( + world, + priceOracleProxy, + 'PriceOracleProxy', + invokation, + [ + { index: ['PriceOracleProxy'], data: priceOracleProxyData } + ] + ); + + return {world, priceOracleProxy, invokation}; +} diff --git a/scenario/src/Builder/UnitrollerBuilder.ts b/scenario/src/Builder/UnitrollerBuilder.ts new file mode 100644 index 000000000..d934dec9f --- /dev/null +++ b/scenario/src/Builder/UnitrollerBuilder.ts @@ -0,0 +1,58 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {Unitroller} from '../Contract/Unitroller'; +import {Invokation} from '../Invokation'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {storeAndSaveContract} from '../Networks'; +import {getContract} from '../Contract'; + +const UnitrollerContract = getContract("Unitroller"); + +export interface UnitrollerData { + invokation: Invokation, + description: string, + address?: string +} + +export async function buildUnitroller(world: World, from: string, event: Event): Promise<{world: World, unitroller: Unitroller, unitrollerData: UnitrollerData}> { + const fetchers = [ + new Fetcher<{}, UnitrollerData>(` + #### Unitroller + + * "" - The Upgradable Comptroller + * E.g. "Unitroller Deploy" + `, + "Unitroller", + [], + async (world, {}) => { + return { + invokation: await UnitrollerContract.deploy(world, from, []), + description: "Unitroller" + }; + }, + {catchall: true} + ) + ]; + + let unitrollerData = await getFetcherValue("DeployUnitroller", fetchers, world, event); + let invokation = unitrollerData.invokation; + delete unitrollerData.invokation; + + if (invokation.error) { + throw invokation.error; + } + const unitroller = invokation.value!; + unitrollerData.address = unitroller._address; + + world = await storeAndSaveContract( + world, + unitroller, + 'Unitroller', + invokation, + [ + { index: ['Unitroller'], data: unitrollerData } + ] + ); + + return {world, unitroller, unitrollerData}; +} diff --git a/scenario/src/Command.ts b/scenario/src/Command.ts new file mode 100644 index 000000000..596e05f2c --- /dev/null +++ b/scenario/src/Command.ts @@ -0,0 +1,248 @@ +import {Event} from './Event'; +import {World} from './World'; +import {mustArray} from './Utils'; +import {NothingV} from './Value'; + +interface ArgOpts { + default?: T + implicit?: boolean + variadic?: boolean + mapped?: boolean + nullable?: boolean + rescue?: T +} + +export class Arg { + name: string + type: any + getter: (World, Event?) => Promise + defaultValue: T | undefined + implicit: boolean + variadic: boolean + mapped: boolean + nullable: boolean + rescue: T | undefined + + constructor(name: string, getter: (World, Event?) => Promise, opts = >{}) { + this.name = name; + this.getter = getter; + this.defaultValue = opts.default; + this.implicit = !!opts.implicit; + this.variadic = !!opts.variadic; + this.mapped = !!opts.mapped; + this.nullable = !!opts.nullable; + this.rescue = opts.rescue; + } +} + +interface ExpressionOpts { + namePos?: number + catchall?: boolean + subExpressions?: Expression[] +} + +export abstract class Expression { + doc: string + name: string + args: Arg[] + namePos: number + catchall: boolean + subExpressions: Expression[] + + constructor(doc: string, name: string, args: Arg[], opts: ExpressionOpts={}) { + this.doc = Command.cleanDoc(doc); + this.name = name; + this.args = args; + this.namePos = opts.namePos || 0; + this.catchall = opts.catchall || false; + this.subExpressions = opts.subExpressions || []; + } + + getNameArgs(event: Event): [string | null, Event] { + // Unwrap double-wrapped expressions e.g. [[Exactly, "1.0"]] -> ["Exactly", "1.0"] + if (Array.isArray(event) && event.length === 1 && Array.isArray(event[0])) { + const [eventInner] = event; + + return this.getNameArgs(eventInner); + } + + // Let's allow single-length complex expressions to be passed without parens e.g. "True" -> ["True"] + if (!Array.isArray(event)) { + event = [event]; + } + + if (this.catchall) { + return [this.name, event]; + } else { + let args = event.slice(); + let [name] = args.splice(this.namePos, 1); + + if (Array.isArray(name)) { + return [null, event]; + } + + return [name, args]; + } + } + + matches(event: Event): boolean { + if (this.catchall) { + return true; + } + + const [name, _args] = this.getNameArgs(event); + + return !!name && name.toLowerCase().trim() === this.name.toLowerCase().trim(); + } + + async getArgs(world: World, event: Event): Promise { + const [_name, eventArgs] = this.getNameArgs(event); + + let initialAcc = <{currArgs: Args, currEvents: Event}>{currArgs: {}, currEvents: eventArgs}; + + const {currArgs: args, currEvents: restEvent} = await this.args.reduce(async (acc, arg) => { + let {currArgs, currEvents} = await acc; + let val: any; + let restEventArgs: Event; + + if (arg.nullable && currEvents.length === 0) { // Note this is zero-length string or zero-length array + val = new NothingV(); + restEventArgs = currEvents; + } else if (arg.variadic) { + if (arg.mapped) { + // If mapped, mapped the function over each event arg + val = await Promise.all(currEvents.map((event) => arg.getter(world, event))); + } else { + val = await arg.getter(world, currEvents); + } + restEventArgs = []; + } else if (arg.implicit) { + val = await arg.getter(world); + restEventArgs = currEvents; + } else { + let eventArg; + + [eventArg, ...restEventArgs] = currEvents; + + if (eventArg === undefined) { + if (arg.defaultValue) { + val = arg.defaultValue; + } else { + throw new Error(`Missing argument ${arg.name} when processing ${this.name}`); + } + } else { + try { + if (arg.mapped) { + val = await await Promise.all(mustArray(eventArg).map((el) => arg.getter(world, el))); + } else { + val = await arg.getter(world, eventArg); + } + } catch (err) { + if (arg.rescue) { + // Rescue is meant to allow Gate to work for checks that + // fail due to the missing components, e.g.: + // `Gate (CToken Eth Address) (... deploy cToken)` + // could be used to deploy a cToken if it doesn't exist, but + // since there is no CToken, that check would raise (when we'd + // hope it just returns null). So here, we allow our code to rescue + // errors and recover, but we need to be smarter about catching specific + // errors instead of all errors. For now, to assist debugging, we may print + // any error that comes up, even if it was intended. + // world.printer.printError(err); + + val = arg.rescue; + } else { + throw err; + } + } + } + } + + let newArgs = { + ...currArgs, + [arg.name]: val + }; + + return { + currArgs: newArgs, + currEvents: restEventArgs + }; + }, Promise.resolve(initialAcc)); + + if (restEvent.length !== 0) { + throw new Error(`Found extra args: ${restEvent.toString()} when processing ${this.name}`); + } + + return args; + } + + static cleanDoc(doc: string): string { + return doc.replace(/^\s+/mg, '').replace(/"/g, '`'); + } +} + +export class Command extends Expression { + processor: (world: World, from: string, args: Args) => Promise + requireFrom: boolean = true; + + constructor(doc: string, name: string, args: Arg[], processor: (world: World, from: string, args: Args) => Promise, opts: ExpressionOpts={}) { + super(doc, name, args, opts); + + this.processor = processor; + } + + async process(world: World, from: string | null, event: Event): Promise { + let args = await this.getArgs(world, event); + if (this.requireFrom) { + if (!from) { + throw new Error(`From required but not given for ${this.name}. Please set a default alias or open unlocked account`); + } + + return await this.processor(world, from, args); + } else { + return await this.processor(world, null, args); + } + } +} + +export class View extends Command { + constructor(doc: string, name: string, args: Arg[], processor: (world: World, args: Args) => Promise, opts: ExpressionOpts={}) { + super(doc, name, args, (world, from, args) => processor(world, args), opts); + this.requireFrom = false; + } +} + +export class Fetcher extends Expression { + fetcher: (world: World, args: Args) => Promise + + constructor(doc: string, name: string, args: Arg[], fetcher: (world: World, args: Args) => Promise, opts: ExpressionOpts={}) { + super(doc, name, args, opts); + + this.fetcher = fetcher; + } + + async fetch(world: World, event: Event): Promise { + let args = await this.getArgs(world, event); + return await this.fetcher(world, args); + } +} + +export async function processCommandEvent(type: string, commands: Command[], world: World, event: Event, from: string | null): Promise { + let matchingCommand = commands.find((command) => command.matches(event)); + + if (!matchingCommand) { + throw new Error(`Found unknown ${type} event type ${event.toString()}`); + } + + return matchingCommand.process(world, from, event); +} + +export async function getFetcherValue(type: string, fetchers: Fetcher[], world: World, event: Event): Promise { + let matchingFetcher = fetchers.find((fetcher) => fetcher.matches(event)); + + if (!matchingFetcher) { + throw new Error(`Found unknown ${type} value type ${JSON.stringify(event)}`); + } + + return matchingFetcher.fetch(world, event); +} diff --git a/scenario/src/Completer.ts b/scenario/src/Completer.ts new file mode 100644 index 000000000..35f90782b --- /dev/null +++ b/scenario/src/Completer.ts @@ -0,0 +1,36 @@ +import {World} from './World'; +import {Macros} from './Macro'; + +// TODO: Get smarter about storing actions as data +const actions: string[] = [ + "Read", + "Assert", + "FastForward", + "Inspect", + "Debug", + "From", + "Invariant", + "Comptroller", + "cToken", + "Erc20", +]; + +function caseInsensitiveSort(a: string, b: string): number { + let A = a.toUpperCase(); + let B = b.toUpperCase(); + + if (A < B) { + return -1; + } else if (A > B) { + return 1; + } else { + return 0; + } +} + +export function complete(world: World, macros: Macros, line: string) { + let allActions = actions.concat(Object.keys(macros)).sort(caseInsensitiveSort); + const hits = allActions.filter((c) => c.toLowerCase().startsWith(line.toLowerCase())); + + return [hits, line]; +} diff --git a/scenario/src/Contract.ts b/scenario/src/Contract.ts new file mode 100644 index 000000000..7581937b1 --- /dev/null +++ b/scenario/src/Contract.ts @@ -0,0 +1,221 @@ +import * as path from 'path'; +import * as crypto from 'crypto'; +import {World} from './World'; +import {Artifact} from './Artifact'; +import {Invokation} from './Invokation'; +import {ErrorReporter, NoErrorReporter} from './ErrorReporter'; +import {getNetworkPath, readFile} from './File'; + +export interface ABIInput { + name: string + type: string +} + +export interface ABIOutput { + name: string + type: string +} + +export interface ABI { + type: string + name: string + constant: boolean + payable: boolean + stateMutability: string + inputs: ABIInput[] + outputs: ABIOutput[] +} + +export interface Raw { + data: string + topics: string[] +} + +export interface Event { + event: string + signature: string | null + address: string + returnValues: object + logIndex: number + transactionIndex: number + blockHash: string + blockNumber: number + raw: Raw +} + +export interface Contract { + _address: string + name: string + methods: any + _jsonInterface: ABI[] + constructorAbi?: string + getPastEvents: (event: string, options: { filter: object, fromBlock: number, toBlock: number | string }) => Event[] +} + +function randomAddress(): string { + return crypto.randomBytes(20).toString('hex'); +} + +class ContractStub { + name: string; + cache: Artifact | null; + test: boolean + + constructor(name: string, test: boolean) { + this.name = name; + this.cache = null; + this.test = test; + } + + async deploy(world: World, from: string, args: any[]): Promise> { + const opts = world.web3.currentProvider.opts || {}; + opts.from = from; + + let {networkContracts} = await getNetworkContracts(world); + let networkContract = networkContracts[this.name]; + if (!networkContract) { + throw new Error(`Cannot find contract ${this.name}, found: ${Object.keys(networkContracts)}`) + } + + let invokationOpts = world.getInvokationOpts(opts); + + let contractAbi = JSON.parse(networkContract.abi); + const contract = new world.web3.eth.Contract(contractAbi, null, opts); + const constructorAbi = contractAbi.find((x) => x.type === 'constructor'); + let inputs; + + if (constructorAbi) { + inputs = constructorAbi.inputs; + } else { + inputs = []; + } + + const abi = world.web3.eth.abi.encodeParameters(inputs, args); + + try { + let deployed; + let deployReceipt; + + if (world.dryRun) { + let addr = randomAddress(); + console.log(`Dry run: Deploying ${this.name} at fake address ${addr}`); + deployed = { + ...contract, + _address: addr + }; + deployed.options.address = addr; + deployReceipt = { + blockNumber: -1, + transactionHash: "0x", + events: {} + }; + } else { + deployed = await (contract.deploy({data: '0x' + networkContract.bin, arguments: args}).send(invokationOpts).on('receipt', (receipt) => (deployReceipt = receipt))); + deployed.constructorAbi = abi; + } + + return new Invokation(deployed, deployReceipt, null, null); + } catch (err) { + return new Invokation(null, null, err, null); + } + } + + at(world: World, address: string): T { + let artifact; + + if (!world.artifacts) { + throw new Error(`Cannot deploy contracts with missing artifacts`); + } + + if (this.cache) { + artifact = this.cache; + } else { + artifact = world.artifacts.require(this.name); + this.cache = artifact; + } + + return new world.web3.eth.Contract(artifact._json.abi, address); + } +} + +export function getContract(name: string): ContractStub { + return new ContractStub(name, false); +} + +export function getTestContract(name: string): ContractStub { + return new ContractStub(name, true); +} + +export function setContractName(name: string, contract: Contract): Contract { + contract.name = name; + + return contract; +} + +export async function getPastEvents(world: World, contract: Contract, name: string, event: string, filter: object={}): Promise { + const block = world.getIn(['contractData', 'Blocks', name]); + if (!block) { + throw new Error(`Cannot get events when missing deploy block for ${name}`); + } + + return await contract.getPastEvents(event, { filter: filter, fromBlock: block, toBlock: 'latest' }); +} + +export async function decodeCall(world: World, contract: Contract, input: string): Promise { + if (input.slice(0, 2) === '0x') { + input = input.slice(2); + } + + let functionSignature = input.slice(0, 8); + let argsEncoded = input.slice(8); + + let funsMapped = contract._jsonInterface.reduce((acc, fun) => { + if (fun.type === 'function') { + let functionAbi = `${fun.name}(${fun.inputs.map((i) => i.type).join(',')})`; + let sig = world.web3.utils.sha3(functionAbi).slice(2, 10); + + return { + ...acc, + [sig]: fun + }; + } else { + return acc; + } + }, {}); + + let abi = funsMapped[functionSignature]; + + if (!abi) { + throw new Error(`Cannot find function matching signature ${functionSignature}`); + } + + let decoded = world.web3.eth.abi.decodeParameters(abi.inputs, argsEncoded); + + const args = abi.inputs.map((input) => { + return `${input.name}=${decoded[input.name]}`; + }); + world.printer.printLine(`\n${contract.name}.${abi.name}(\n\t${args.join("\n\t")}\n)`); + + return world; +} + +export async function getNetworkContracts(world: World): Promise<{networkContracts: object, version: string}> { + let fullContracts = await readFile(getNetworkPath(world.basePath, world.network, '-contracts', 'json'), null, JSON.parse); + let version = fullContracts.version; + let networkContracts = Object.entries(fullContracts.contracts).reduce((acc, [k, v]) => { + let [path, contractName] = k.split(':'); + + return { + ...acc, + [contractName]: { + ...v, + path: path + } + }; + }, {}); + + return { + networkContracts, + version + }; +} diff --git a/scenario/src/Contract/CToken.ts b/scenario/src/Contract/CToken.ts new file mode 100644 index 000000000..85c7ce050 --- /dev/null +++ b/scenario/src/Contract/CToken.ts @@ -0,0 +1,57 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; +import {encodedNumber} from '../Encoding'; + +interface CTokenMethods { + balanceOfUnderlying(string): Callable + borrowBalanceCurrent(string): Callable + borrowBalanceStored(string): Callable + totalBorrows(): Callable + totalBorrowsCurrent(): Callable + totalReserves(): Callable + reserveFactorMantissa(): Callable + comptroller(): Callable + exchangeRateStored(): Sendable + exchangeRateCurrent(): Callable + accrueInterest(): Sendable + mint(): Sendable + mint(encodedNumber): Sendable + redeem(encodedNumber): Sendable + redeemUnderlying(encodedNumber): Sendable + borrow(encodedNumber): Sendable + repayBorrow(): Sendable + repayBorrow(encodedNumber): Sendable + repayBorrowBehalf(string): Sendable + repayBorrowBehalf(string, encodedNumber): Sendable + liquidateBorrow(borrower: string, cTokenCollateral: string): Sendable + liquidateBorrow(borrower: string, repayAmount: encodedNumber, cTokenCollateral: string): Sendable + seize(liquidator: string, borrower: string, seizeTokens: encodedNumber): Sendable + evilSeize(treasure: string, liquidator: string, borrower: string, seizeTokens: encodedNumber): Sendable + _reduceReserves(encodedNumber): Sendable + _setReserveFactor(encodedNumber): Sendable + _setInterestRateModel(string): Sendable + _setComptroller(string): Sendable + underlying(): Callable + interestRateModel(): Callable + borrowRatePerBlock(): Callable + donate(): Sendable + admin(): Callable + pendingAdmin(): Callable + _setPendingAdmin(string): Sendable + _acceptAdmin(): Sendable +} + +interface CTokenScenarioMethods extends CTokenMethods { + setTotalBorrows(encodedNumber): Sendable + setTotalReserves(encodedNumber): Sendable +} + +export interface CToken extends Contract { + methods: CTokenMethods + name: string +} + +export interface CTokenScenario extends Contract { + methods: CTokenScenarioMethods + name: string +} diff --git a/scenario/src/Contract/Comptroller.ts b/scenario/src/Contract/Comptroller.ts new file mode 100644 index 000000000..8b650dcdd --- /dev/null +++ b/scenario/src/Contract/Comptroller.ts @@ -0,0 +1,40 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; +import {encodedNumber} from '../Encoding'; + +interface ComptrollerMethods { + getAccountLiquidity(string): Callable<{0: number, 1: number, 2: number}> + getHypotheticalAccountLiquidity(account: string, asset: string, redeemTokens: encodedNumber, borrowAmount: encodedNumber): Callable<{0: number, 1: number, 2: number}> + membershipLength(string): Callable + checkMembership(user: string, cToken: string): Callable + getAssetsIn(string): Callable + admin(): Callable + oracle(): Callable + maxAssets(): Callable + liquidationIncentiveMantissa(): Callable + closeFactorMantissa(): Callable + blockNumber(): Callable + collateralFactor(string): Callable + markets(string): Callable<{0: boolean, 1: number}> + _setMintPaused(bool): Sendable + _setMaxAssets(encodedNumber): Sendable + _setLiquidationIncentive(encodedNumber): Sendable + _supportMarket(string): Sendable + _setPriceOracle(string): Sendable + _setCollateralFactor(string, encodedNumber): Sendable + _setCloseFactor(encodedNumber): Sendable + enterMarkets(markets: string[]): Sendable + exitMarket(market: string): Sendable + fastForward(encodedNumber): Sendable + _setPendingImplementation(string): Sendable + comptrollerImplementation(): Callable + unlist(string): Sendable + admin(): Callable + pendingAdmin(): Callable + _setPendingAdmin(string): Sendable + _acceptAdmin(): Sendable +} + +export interface Comptroller extends Contract { + methods: ComptrollerMethods +} diff --git a/scenario/src/Contract/ComptrollerImpl.ts b/scenario/src/Contract/ComptrollerImpl.ts new file mode 100644 index 000000000..75570535e --- /dev/null +++ b/scenario/src/Contract/ComptrollerImpl.ts @@ -0,0 +1,11 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; +import {encodedNumber} from '../Encoding'; + +interface ComptrollerImplMethods { + _become(comptroller: string, priceOracle: string, maxAssets: encodedNumber, closeFactor: encodedNumber, reinitializing: boolean): Sendable +} + +export interface ComptrollerImpl extends Contract { + methods: ComptrollerImplMethods +} diff --git a/scenario/src/Contract/Erc20.ts b/scenario/src/Contract/Erc20.ts new file mode 100644 index 000000000..31ff9d39c --- /dev/null +++ b/scenario/src/Contract/Erc20.ts @@ -0,0 +1,24 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; +import {encodedNumber} from '../Encoding'; + +interface Erc20Methods { + name(): Callable + symbol(): Callable + decimals(): Callable + totalSupply(): Callable + balanceOf(string): Callable + allowance(owner: string, spender: string): Callable + approve(address: string, amount: encodedNumber): Sendable + allocateTo(address: string, amount: encodedNumber): Sendable + transfer(address: string, amount: encodedNumber): Sendable + transferFrom(owner: string, spender: string, amount: encodedNumber): Sendable + setFail(fail: boolean): Sendable + pause(): Sendable + unpause(): Sendable +} + +export interface Erc20 extends Contract { + methods: Erc20Methods + name: string +} diff --git a/scenario/src/Contract/InterestRateModel.ts b/scenario/src/Contract/InterestRateModel.ts new file mode 100644 index 000000000..dd49ead05 --- /dev/null +++ b/scenario/src/Contract/InterestRateModel.ts @@ -0,0 +1,12 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; +import {encodedNumber} from '../Encoding'; + +interface InterestRateModelMethods { + getBorrowRate(cash: encodedNumber, borrows: encodedNumber, reserves: encodedNumber): Callable<{0: number, 1: number}> +} + +export interface InterestRateModel extends Contract { + methods: InterestRateModelMethods + name: string +} diff --git a/scenario/src/Contract/Maximillion.ts b/scenario/src/Contract/Maximillion.ts new file mode 100644 index 000000000..02b955278 --- /dev/null +++ b/scenario/src/Contract/Maximillion.ts @@ -0,0 +1,11 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; + +interface MaximillionMethods { + cEther(): Callable + repayBehalf(string): Sendable +} + +export interface Maximillion extends Contract { + methods: MaximillionMethods +} diff --git a/scenario/src/Contract/PriceOracle.ts b/scenario/src/Contract/PriceOracle.ts new file mode 100644 index 000000000..4ea9f8d58 --- /dev/null +++ b/scenario/src/Contract/PriceOracle.ts @@ -0,0 +1,29 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; +import {encodedNumber} from '../Encoding'; + +interface PriceOracleMethods { + assetPrices(asset: string): Callable + setUnderlyingPrice(cToken: string, amount: encodedNumber): Sendable + + // Anchor Price Oracle + getPrice(asset: string): Callable + readers(asset: string): Callable + anchorAdmin(): Callable + pendingAnchorAdmin(): Callable + poster(): Callable + maxSwing(): Callable + anchors(asset: string): Callable<{0: number, 1: number}> + pendingAnchors(asset: string): Callable + _setPendingAnchor(asset: string, price: encodedNumber): Sendable + _setPaused(paused: boolean): Sendable + _setPendingAnchorAdmin(string): Sendable + _acceptAnchorAdmin(): Sendable + setPrice(asset: string, price: encodedNumber): Sendable + setPrices(assets: string[], prices: encodedNumber[]): Sendable +} + +export interface PriceOracle extends Contract { + methods: PriceOracleMethods + name: string +} diff --git a/scenario/src/Contract/PriceOracleProxy.ts b/scenario/src/Contract/PriceOracleProxy.ts new file mode 100644 index 000000000..155c06a60 --- /dev/null +++ b/scenario/src/Contract/PriceOracleProxy.ts @@ -0,0 +1,10 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; + +interface PriceOracleProxyMethods { + getUnderlyingPrice(asset: string): Callable +} + +export interface PriceOracleProxy extends Contract { + methods: PriceOracleProxyMethods +} diff --git a/scenario/src/Contract/Unitroller.ts b/scenario/src/Contract/Unitroller.ts new file mode 100644 index 000000000..89704d6d2 --- /dev/null +++ b/scenario/src/Contract/Unitroller.ts @@ -0,0 +1,12 @@ +import {Contract} from '../Contract'; +import {Callable, Sendable} from '../Invokation'; + +interface UnitrollerMethods { + admin(): Callable + _setPendingImplementation(string): Sendable + comptrollerImplementation(): Callable +} + +export interface Unitroller extends Contract { + methods: UnitrollerMethods +} diff --git a/scenario/src/ContractLookup.ts b/scenario/src/ContractLookup.ts new file mode 100644 index 000000000..9682e5e11 --- /dev/null +++ b/scenario/src/ContractLookup.ts @@ -0,0 +1,158 @@ +import {Event} from './Event'; +import {World} from './World'; +import {accountMap} from './Accounts'; +import {Contract} from './Contract'; +import {mustString} from './Utils'; + +import {Comptroller} from './Contract/Comptroller'; +import {ComptrollerImpl} from './Contract/ComptrollerImpl'; +import {CToken} from './Contract/CToken'; +import {Erc20} from './Contract/Erc20'; +import {InterestRateModel} from './Contract/InterestRateModel'; +import {PriceOracle} from './Contract/PriceOracle'; +import {Map} from 'immutable'; + +type ContractDataEl = string | Map | null; + +function getContractData(world: World, indices: string[][]): ContractDataEl { + return indices.reduce((value: ContractDataEl, index) => { + if (value) { + return value; + } else { + return index.reduce((data: ContractDataEl, el) => { + let lowerEl = el.toLowerCase(); + + if (!data) { + return null; + } else if (typeof(data) === "string") { + return data; + } else { + return ( + Map(data).find( + (_v, key) => key.toLowerCase().trim() === lowerEl.trim())); + } + }, world.contractData); + } + }, null); +} + +function getContractDataString(world: World, indices: string[][]): string { + const value: ContractDataEl = getContractData(world, indices); + + if (!value || typeof(value) !== "string") { + throw new Error(`Failed to find string value by index (got ${value}): ${JSON.stringify(indices)}, index contains: ${JSON.stringify(world.contractData.toJSON())}`); + } + + return value; +} + +export function getWorldContract(world: World, indices: string[][]): T { + const address = getContractDataString(world, indices); + + return getWorldContractByAddress(world, address); +} + +export function getWorldContractByAddress(world: World, address: string): T { + const contract = world.contractIndex[address.toLowerCase()]; + + if (!contract) { + throw new Error(`Failed to find world contract by address: ${address}, index contains: ${JSON.stringify(Object.keys(world.contractIndex))}`); + } + + return contract; +} + +export async function getUnitroller(world: World): Promise { + return getWorldContract(world, [['Contracts', 'Unitroller']]); +} + +export async function getMaximillion(world: World): Promise { + return getWorldContract(world, [['Contracts', 'Maximillion']]); +} + +export async function getComptroller(world: World): Promise { + return getWorldContract(world, [['Contracts', 'Comptroller']]); +} + +export async function getComptrollerImpl(world: World, comptrollerImplArg: Event): Promise { + return getWorldContract(world, [['Comptroller', mustString(comptrollerImplArg), 'address']]); +} + +export function getCTokenAddress(world: World, cTokenArg: string): string { + return getContractDataString(world, [['cTokens', cTokenArg, 'address']]); +} + +export function getErc20Address(world: World, erc20Arg: string): string { + return getContractDataString(world, [['Tokens', erc20Arg, 'address']]); +} + +export async function getPriceOracleProxy(world: World): Promise { + return getWorldContract(world, [['Contracts', 'PriceOracleProxy']]); +} + +export async function getPriceOracle(world: World): Promise { + return getWorldContract(world, [['Contracts', 'PriceOracle']]); +} + +export async function getInterestRateModel(world: World, interestRateModelArg: Event): Promise { + return getWorldContract(world, [['InterestRateModel', mustString(interestRateModelArg), 'address']]); +} + +export async function getInterestRateModelData(world: World, interestRateModelArg: string): Promise<[InterestRateModel, string, Map]> { + let contract = await getInterestRateModel(world, interestRateModelArg); + let data = getContractData(world, [['InterestRateModel', interestRateModelArg]]); + + return [contract, interestRateModelArg, >data]; +} + +export async function getErc20Data(world: World, erc20Arg: string): Promise<[Erc20, string, Map]> { + let contract = getWorldContract(world, [['Tokens', erc20Arg, 'address']]); + let data = getContractData(world, [['Tokens', erc20Arg]]); + + return [contract, erc20Arg, >data]; +} + +export async function getCTokenData(world: World, cTokenArg: string): Promise<[CToken, string, Map]> { + let contract = getWorldContract(world, [['cTokens', cTokenArg, 'address']]); + let data = getContractData(world, [['CTokens', cTokenArg]]); + + return [contract, cTokenArg, >data]; +} + +export async function getComptrollerImplData(world: World, comptrollerImplArg: string): Promise<[ComptrollerImpl, string, Map]> { + let contract = await getComptrollerImpl(world, comptrollerImplArg); + let data = getContractData(world, [['Comptroller', comptrollerImplArg]]); + + return [contract, comptrollerImplArg, >data]; +} + +export function getAddress(world: World, addressArg: string): string { + if (addressArg.toLowerCase() === "zero") { + return "0x0000000000000000000000000000000000000000"; + } + + if (addressArg.startsWith("0x")) { + return addressArg; + } + + let alias = Object.entries(world.settings.aliases).find(([alias, addr]) => alias.toLowerCase() === addressArg.toLowerCase()); + if (alias) { + return alias[1]; + } + + let account = world.accounts.find((account) => account.name.toLowerCase() === addressArg.toLowerCase()); + if (account) { + return account.address; + } + + return getContractDataString(world, [ + ['Contracts', addressArg], + ['cTokens', addressArg, 'address'], + ['Tokens', addressArg, 'address'], + ['Comptroller', addressArg, 'address'] + ]); +} + +export function getContractByName(world: World, name: string): Contract { + return getWorldContract(world, [['Contracts', name]]); +} diff --git a/scenario/src/CoreEvent.ts b/scenario/src/CoreEvent.ts new file mode 100644 index 000000000..cc524130a --- /dev/null +++ b/scenario/src/CoreEvent.ts @@ -0,0 +1,565 @@ +import { + addAction, + checkExpectations, + checkInvariants, + clearInvariants, + describeUser, + holdInvariants, + setEvent, + World +} from './World'; +import {Event} from './Event'; +import { + getAddressV, + getEventV, + getNumberV, + getStringV +} from './CoreValue'; +import { + AddressV, + EventV, + NothingV, + NumberV, + StringV, + Value +} from './Value'; +import {Arg, Command, processCommandEvent, View} from './Command'; +import {assertionCommands, processAssertionEvent} from './Event/AssertionEvent'; +import {comptrollerCommands, processComptrollerEvent} from './Event/ComptrollerEvent'; +import {processUnitrollerEvent, unitrollerCommands} from './Event/UnitrollerEvent'; +import {comptrollerImplCommands, processComptrollerImplEvent} from './Event/ComptrollerImplEvent'; +import {cTokenCommands, processCTokenEvent} from './Event/CTokenEvent'; +import {erc20Commands, processErc20Event} from './Event/Erc20Event'; +import {interestRateModelCommands, processInterestRateModelEvent} from './Event/InterestRateModelEvent'; +import {priceOracleCommands, processPriceOracleEvent} from './Event/PriceOracleEvent'; +import {priceOracleProxyCommands, processPriceOracleProxyEvent} from './Event/PriceOracleProxyEvent'; +import {maximillionCommands, processMaximillionEvent} from './Event/MaximillionEvent'; +import {invariantCommands, processInvariantEvent} from './Event/InvariantEvent'; +import {expectationCommands, processExpectationEvent} from './Event/ExpectationEvent'; +import {processTrxEvent, trxCommands} from './Event/TrxEvent'; +import {fetchers, getCoreValue} from './CoreValue'; +import {formatEvent} from './Formatter'; +import {fallback} from './Invokation'; +import {sleep} from './Utils'; +import {Map} from 'immutable'; +import {encodedNumber} from './Encoding'; +import {printHelp} from './Help'; + +export class EventProcessingError extends Error { + error: Error + event: Event + + constructor(error: Error, event: Event) { + super(error.message); + + this.error = error; + this.event = event; + this.message = `Error: \`${this.error.toString()}\` when processing \`${formatEvent(this.event)}\``; + } +} + +export async function processEvents(originalWorld: World, events: Event[]): Promise { + return events.reduce(async (pWorld: Promise, event: Event): Promise => { + let world = await pWorld; + + try { + world = await processCoreEvent(setEvent(world, event), event, world.defaultFrom()); + } catch (err) { + if (world.verbose) { + console.error(err); + } + throw new EventProcessingError(err, event); + }; + + // Next, check any unchecked invariants + world = await checkInvariants(world); + + // Check any expectations + world = await checkExpectations(world); + + // Also clear trx related fields + world = world.set('trxInvokationOpts', Map({})); + world = world.set('newInvokation', false); + + if (!world) { + throw new Error(`Encountered null world result when processing event ${event[0]}: ${world}`); + } else if (!(world instanceof World)) { + throw new Error(`Encountered world result which was not isWorld when processing event ${event[0]}: ${world}`); + } + + return world; + }, Promise.resolve(originalWorld)); +} + +async function print(world: World, message: string): Promise { + world.printer.printLine(message); + + return world; +} + +async function inspect(world: World, string: string | null): Promise { + if (string !== null) { + console.log(["Inspect", string, world.toJS()]); + } else { + console.log(["Inspect", world.toJS()]); + } + + return world; +} + +async function sendEther(world: World, from: string, to: string, amount: encodedNumber): Promise { + let invokation = await fallback(world, from, to, amount); + + world = addAction( + world, + `Send ${amount} from ${from} to ${to}`, + invokation + ); + + return world; +} + +export const commands = [ + new View<{n: NumberV}>(` + #### History + + * "History n:=5" - Prints history of actions + * E.g. "History" + * E.g. "History 10" + `, + "History", + [ + new Arg("n", getNumberV, {default: new NumberV(5)}) + ], + async (world, {n}) => { + world.actions.slice(0, Number(n.val)).forEach((action) => { + world.printer.printLine(action.toString()); + }); + + return world; + } + ), + new View<{ms: NumberV}>(` + #### Sleep + + * "Sleep ms:" - Sleeps for given amount of time. + * E.g. "Sleep 1000" - Sleeps for one second + `, + "Sleep", + [ + new Arg("ms", getNumberV) + ], + async (world, {ms}) => { + await sleep(ms.toNumber()); + return world; + } + ), + new View<{errMsg: StringV}>(` + #### Throw + + * "Throw errMsg:" - Throws given error + * E.g. "Throw \"my error message\"" + `, + "Throw", + [ + new Arg("errMsg", getStringV) + ], + async (world, {errMsg}) => { + throw new Error(errMsg.val); + + return world; + } + ), + new View<{res: Value}>(` + #### Read + + * "Read ..." - Reads given value and prints result + * E.g. "Read CToken cBAT ExchangeRateStored" - Returns exchange rate of cBAT + `, + "Read", + [ + new Arg("res", getCoreValue, {variadic: true}) + ], + async (world, {res}) => { + world.printer.printValue(res); + + return world; + }, + { subExpressions: fetchers } + ), + new View<{message: StringV}>(` + #### Print + + * "Print ..." - Prints given string + * E.g. "Print \"Hello there\"" + `, + "Print", + [ + new Arg("message", getStringV) + ], + async (world, {message}) => print(world, message.val) + ), + new View<{address: AddressV}>(` + #### MyAddress + + * "MyAddress address:" - Sets default from address (same as "Alias Me ") + * E.g. "MyAddress \"0x9C1856636d78C051deAd6CAB9c5699e4E25549e9\"" + `, + "MyAddress", + [ + new Arg("address", getAddressV) + ], + async (world, {address}) => { + return await world.updateSettings(async (settings) => { + settings.aliases["Me"] = address.val; + + return settings; + }); + } + ), + new View<{name: StringV, address: AddressV}>(` + #### Alias + + * "Alias name: address:" - Stores an alias between name and address + * E.g. "Alias Me \"0x9C1856636d78C051deAd6CAB9c5699e4E25549e9\"" + `, + "Alias", + [ + new Arg("name", getStringV), + new Arg("address", getAddressV) + ], + async (world, {name, address}) => { + return await world.updateSettings(async (settings) => { + settings.aliases[name.val] = address.val; + + return settings; + }); + } + ), + new View<{name: StringV, address: AddressV}>(` + #### Aliases + + * "Aliases - Prints all aliases + `, + "Aliases", + [], + async (world, {name, address}) => { + world.printer.printLine("Aliases:"); + Object.entries(world.settings.aliases).forEach(([name, address]) => { + world.printer.printLine(`\t${name}: ${address}`); + }); + + return world; + } + ), + new View<{}>(` + #### Inspect + + * "Inspect" - Prints debugging information about the world + `, + "Inspect", + [], + async (world, {}) => inspect(world, null) + ), + new View<{message: StringV}>(` + #### Debug + + * "Debug message:" - Same as inspect but prepends with a string + `, + "Debug", + [ + new Arg("message", getStringV) + ], + async (world, {message}) => inspect(world, message.val) + ), + new View<{account: AddressV, event: EventV}>(` + #### From + + * "From " - Runs event as the given user + * E.g. "From Geoff (CToken cZRX Mint 5e18)" + `, + "From", + [ + new Arg("account", getAddressV), + new Arg("event", getEventV) + ], + async (world, {account, event}) => processCoreEvent(world, event.val, account.val) + ), + new Command<{event: EventV}>(` + #### Trx + + * "Trx ...trxEvent" - Handles event to set details of next transaction + * E.g. "Trx Value 1.0e18 (CToken cEth Mint 1.0e18)" + `, + "Trx", + [ + new Arg("event", getEventV, {variadic: true}) + ], + async (world, from, {event}) => processTrxEvent(world, event.val, from), + { subExpressions: trxCommands() } + ), + new Command<{event: EventV}>(` + #### Invariant + + * "Invariant ...invariant" - Adds a new invariant to the world which is checked after each transaction + * E.g. "Invariant Static (CToken cZRX TotalSupply)" + `, + "Invariant", + [ + new Arg("event", getEventV, {variadic: true}) + ], + async (world, from, {event}) => processInvariantEvent(world, event.val, from), + { subExpressions: invariantCommands() } + ), + new Command<{event: EventV}>(` + #### Expect + + * "Expect ...expectation" - Adds an expectation to hold after the next transaction + * E.g. "Expect Changes (CToken cZRX TotalSupply) +10.0e18" + `, + "Expect", + [ + new Arg("event", getEventV, {variadic: true}) + ], + async (world, from, {event}) => processExpectationEvent(world, event.val, from), + { subExpressions: expectationCommands() } + ), + new View<{type: StringV}>(` + #### HoldInvariants + + * "HoldInvariants type:" - Skips checking invariants on next command. + * E.g. "HoldInvariants" - Skips all invariants + * E.g. "HoldInvariants All" - Skips all invariants + * E.g. "HoldInvariants Success" - Skips "success" invariants + * E.g. "HoldInvariants Remains" - Skips "remains" invariants + * E.g. "HoldInvariants Static" - Skips "static" invariants + `, + "HoldInvariants", + [ + new Arg("type", getStringV, {default: new StringV("All")}) + ], + async (world, {type}) => holdInvariants(world, type.val) + ), + new View<{type: StringV}>(` + #### ClearInvariants + + * "ClearInvariants type:" - Removes all invariants. + * E.g. "ClearInvariants" - Removes all invariants + * E.g. "ClearInvariants All" - Removes all invariants + * E.g. "ClearInvariants Success" - Removes "success" invariants + * E.g. "ClearInvariants Remains" - Removes "remains" invariants + * E.g. "ClearInvariants Static" - Removes "static" invariants + `, + "ClearInvariants", + [ + new Arg("type", getStringV, {default: new StringV("All")}) + ], + async (world, {type}) => clearInvariants(world, type.val) + ), + new Command<{event: EventV}>(` + #### Assert + + * "Assert ...event" - Validates given assertion, raising an exception if assertion fails + * E.g. "Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 5.0)" + `, + "Assert", + [ + new Arg("event", getEventV, {variadic: true}) + ], + async (world, from, {event}) => processAssertionEvent(world, event.val, from), + { subExpressions: assertionCommands() } + ), + new Command<{gate: Value, event: EventV}>(` + #### Gate + + * "Gate value event" - Runs event only if value is falsey. Thus, gate can be used to build idempotency. + * E.g. "Gate (Erc20 ZRX Address) (Erc20 Deploy BAT)" + `, + "Gate", + [ + new Arg("gate", getCoreValue, {rescue: new NothingV()}), + new Arg("event", getEventV) + ], + async (world, from, {gate, event}) => { + if (gate.truthy()) { + return world; + } else { + return processCoreEvent(world, event.val, from); + } + } + ), + new Command<{given: Value, event: EventV}>(` + #### Given + + * "Given value event" - Runs event only if value is truthy. Thus, given can be used to build existence checks. + * E.g. "Given ($var) (PriceOracle SetPrice cBAT $var)" + `, + "Given", + [ + new Arg("given", getCoreValue, {rescue: new NothingV()}), + new Arg("event", getEventV) + ], + async (world, from, {given, event}) => { + if (given.truthy()) { + return processCoreEvent(world, event.val, from); + } else { + return world; + } + } + ), + new Command<{address: AddressV, amount: NumberV}>(` + #### Send + + * "Send
" - Sends a given amount of eth to given address + * E.g. "Send cETH 0.5e18" + `, + "Send", + [ + new Arg("address", getAddressV), + new Arg("amount", getNumberV) + ], + (world, from, {address, amount}) => sendEther(world, from, address.val, amount.encode()) + ), + new Command<{event: EventV}>(` + #### Unitroller + + * "Unitroller ...event" - Runs given Unitroller event + * E.g. "Unitroller SetPendingImpl MyComptrollerImpl" + `, + "Unitroller", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processUnitrollerEvent(world, event.val, from), + { subExpressions: unitrollerCommands() } + ), + new Command<{event: EventV}>(` + #### Comptroller + + * "Comptroller ...event" - Runs given Comptroller event + * E.g. "Comptroller _setReserveFactor 0.5" + `, + "Comptroller", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processComptrollerEvent(world, event.val, from), + { subExpressions: comptrollerCommands() } + ), + new Command<{event: EventV}>(` + #### ComptrollerImpl + + * "ComptrollerImpl ...event" - Runs given ComptrollerImpl event + * E.g. "ComptrollerImpl MyImpl Become" + `, + "ComptrollerImpl", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processComptrollerImplEvent(world, event.val, from), + { subExpressions: comptrollerImplCommands() } + ), + new Command<{event: EventV}>(` + #### CToken + + * "CToken ...event" - Runs given CToken event + * E.g. "CToken cZRX Mint 5e18" + `, + "CToken", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processCTokenEvent(world, event.val, from), + { subExpressions: cTokenCommands() } + ), + new Command<{event: EventV}>(` + #### Erc20 + + * "Erc20 ...event" - Runs given Erc20 event + * E.g. "Erc20 ZRX Facuet Geoff 5e18" + `, + "Erc20", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processErc20Event(world, event.val, from), + { subExpressions: erc20Commands() } + ), + new Command<{event: EventV}>(` + #### InterestRateModel + + * "InterestRateModel ...event" - Runs given interest rate model event + * E.g. "InterestRateModel Deploy Fixed StdRate 0.5" + `, + "InterestRateModel", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processInterestRateModelEvent(world, event.val, from), + { subExpressions: interestRateModelCommands() } + ), + new Command<{event: EventV}>(` + #### PriceOracle + + * "PriceOracle ...event" - Runs given Price Oracle event + * E.g. "PriceOracle SetPrice cZRX 1.5" + `, + "PriceOracle", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => processPriceOracleEvent(world, event.val, from), + { subExpressions: priceOracleCommands() } + ), + new Command<{event: EventV}>(` + #### PriceOracleProxy + + * "PriceOracleProxy ...event" - Runs given Price Oracle event + * E.g. "PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (CToken cETH Address)" + `, + "PriceOracleProxy", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => { + return processPriceOracleProxyEvent(world, event.val, from) + }, + { subExpressions: priceOracleProxyCommands() } + ), + new Command<{event: EventV}>(` + #### Maximillion + + * "Maximillion ...event" - Runs given Maximillion event + * E.g. "Maximillion Deploy (CToken cETH Address)" + `, + "Maximillion", + [ + new Arg("event", getEventV, {variadic: true}) + ], + (world, from, {event}) => { + return processMaximillionEvent(world, event.val, from) + }, + { subExpressions: maximillionCommands() } + ), + new View<{event: EventV}>(` + #### Help + + * "Help ...event" - Prints help for given command + * E.g. "Help From" + `, + "Help", + [ + new Arg("event", getEventV, {variadic: true}) + ], + async (world, {event}) => { + world.printer.printLine(""); + printHelp(world.printer, event.val, commands); + + return world; + } + ) +]; + +export async function processCoreEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Core", commands, world, event, from); +} diff --git a/scenario/src/CoreValue.ts b/scenario/src/CoreValue.ts new file mode 100644 index 000000000..825fff3d4 --- /dev/null +++ b/scenario/src/CoreValue.ts @@ -0,0 +1,547 @@ +import {Event} from './Event'; +import {World} from './World'; +import { + AddressV, + AnythingV, + BoolV, + EventV, + ExpNumberV, + ListV, + MapV, + NothingV, + NumberV, + PercentV, + PreciseV, + StringV, + Value +} from './Value'; +import {Arg, Fetcher, getFetcherValue} from './Command'; +import {getUserValue, userFetchers} from './Value/UserValue'; +import {comptrollerFetchers, getComptrollerValue} from './Value/ComptrollerValue'; +import {comptrollerImplFetchers, getComptrollerImplValue} from './Value/ComptrollerImplValue'; +import {getUnitrollerValue, unitrollerFetchers} from './Value/UnitrollerValue'; +import {cTokenFetchers, getCTokenValue} from './Value/CTokenValue'; +import {erc20Fetchers, getErc20Value} from './Value/Erc20Value'; +import {getInterestRateModelValue, interestRateModelFetchers} from './Value/InterestRateModelValue'; +import {getPriceOracleValue, priceOracleFetchers} from './Value/PriceOracleValue'; +import {getPriceOracleProxyValue, priceOracleProxyFetchers} from './Value/PriceOracleProxyValue'; +import {getMaximillionValue, maximillionFetchers} from './Value/MaximillionValue'; +import {getAddress} from './ContractLookup'; +import {mustArray} from './Utils'; +import {toEncodableNum} from './Encoding'; +import {BigNumber} from 'bignumber.js'; + +const expMantissa = new BigNumber('1000000000000000000'); + +function getSigFigs(value) { + let str = value.toString(); + + str = str.replace(/e\d+/, ''); // Remove e01 + str = str.replace(/\./, ''); // Remove decimal point + + return str.length; +} + +export async function getEventV(world: World, event: Event): Promise { + return new EventV(event); +} + +// TODO: We may want to handle simple values -> complex values at the parser level +// This is currently trying to parse simple values as simple or complex values, +// and this is because items like `Some` could work either way. +export async function mapValue(world: World, event: Event, simple: (string) => T, complex: (World, Event) => Promise, type: any): Promise { + let simpleErr; + let val; + + if (typeof(event) === "string") { + try { + return simple(event); + } catch (err) { + // Collect the error, but fallback to a complex expression + simpleErr = err; + } + } + + try { + val = await complex(world, event); + } catch (complexErr) { + // If we had an error before and this was the fallback, now throw that one + if (simpleErr) { + throw simpleErr; + } else { + throw complexErr; + } + } + + if (!(val instanceof type)) { + throw new Error(`Expected ${type.name} from ${event.toString()}, got: ${val.toString()}`); + } + + // We just did a typecheck above... + return val; +} + +export async function getBoolV(world: World, event: Event): Promise { + return mapValue( + world, + event, + (str) => { + const lower = str.trim().toLowerCase(); + + if (lower == 'true' || lower == 't' || lower == '1') { + return new BoolV(true); + } else { + return new BoolV(false); + } + }, + getCoreValue, + BoolV + ); +} + +export async function getAddressV(world: World, event: Event): Promise { + return mapValue( + world, + event, + (str) => new AddressV(getAddress(world, str)), + async (currWorld, val) => { + const coreVal = await getCoreValue(currWorld, val); + + if (coreVal instanceof StringV) { + return new AddressV(coreVal.val); + } else { + return coreVal; + } + }, + AddressV + ); +} + +function strToNumberV(str: string): NumberV { + if (isNaN(Number(str))) { + throw "not a number"; + } + + return new NumberV(str); +} + +function strToExpNumberV(str: string): NumberV { + const r = new BigNumber(str); + + return new NumberV(r.multipliedBy(expMantissa).toFixed()); +} + +export async function getNumberV(world: World, event: Event): Promise { + return mapValue( + world, + event, + strToNumberV, + getCoreValue, + NumberV + ); +} + +export async function getExpNumberV(world: World, event: Event): Promise { + let res = await mapValue( + world, + event, + strToNumberV, + getCoreValue, + NumberV + ); + + const r = new BigNumber(res.val); + + return new ExpNumberV(r.multipliedBy(expMantissa).toFixed()); +} + +export async function getPercentV(world: World, event: Event): Promise { + let res = await getExpNumberV(world, event); + + return new PercentV(res.val); +} + +// Note: MapV does not currently parse its contents +export async function getMapV(world: World, event: Event): Promise { + const res: object = {}; + + await Promise.all(mustArray(event).map(async (e) => { + if (Array.isArray(e) && e.length === 2 && typeof e[0] === "string") { + const [key, valueEvent] = e; + let value; + if (typeof valueEvent === "string") { + value = new StringV(valueEvent); + } else { + value = await getCoreValue(world, valueEvent); + } + + res[key] = value; + } else { + throw new Error(`Expected all string pairs for MapV from ${event.toString()}, got: ${e.toString()}`); + } + })); + + return new MapV(res); +} + +export async function getStringV(world: World, event: Event): Promise { + return mapValue( + world, + event, + (str) => new StringV(str), + getCoreValue, + StringV + ); +} + +async function getEtherBalance(world: World, address: string): Promise { + let balance = await world.web3.eth.getBalance(address); + + return new NumberV(balance); +} + +export const fetchers = [ + new Fetcher<{}, BoolV>(` + #### True + + * "True" - Returns true + `, + "True", + [], + async (world, {}) => new BoolV(true) + ), + new Fetcher<{}, BoolV>(` + #### False + + * "False" - Returns false + `, + "False", + [], + async (world, {}) => new BoolV(false) + ), + new Fetcher<{}, NumberV>(` + #### Zero + + * "Zero" - Returns 0 + `, + "Zero", + [], + async (world, {}) => strToNumberV("0") + ), + new Fetcher<{}, NumberV>(` + #### Max + + * "Max" - Returns 2^256 - 1 + `, + "Max", + [], + async (world, {}) => new NumberV("115792089237316195423570985008687907853269984665640564039457584007913129639935") + ), + new Fetcher<{}, NumberV>(` + #### Some + + * "Some" - Returns 100e18 + `, + "Some", + [], + async (world, {}) => strToNumberV("100e18") + ), + new Fetcher<{}, NumberV>(` + #### Little + + * "Little" - Returns 100e10 + `, + "Little", + [], + async (world, {}) => strToNumberV("100e10") + ), + new Fetcher<{amt: EventV}, NumberV>(` + #### Exactly + + * "Exactly " - Returns a strict numerical value + * E.g. "Exactly 5.0" + `, + "Exactly", + [new Arg("amt", getEventV)], + async (world, {amt}) => getNumberV(world, amt.val) + ), + new Fetcher<{hexVal: EventV}, StringV>(` + #### Hex + + * "Hex " - Returns a byte string with given hex value + * E.g. "Hex \"0xffff\"" + `, + "Hex", + [new Arg("hexVal", getEventV)], + async (world, {hexVal}) => getStringV(world, hexVal.val) + ), + new Fetcher<{str: EventV}, StringV>(` + #### String + + * "String " - Returns a string literal + * E.g. "String MyString" + `, + "String", + [new Arg("str", getEventV)], + async (world, {str}) => getStringV(world, str.val) + ), + new Fetcher<{amt: EventV}, NumberV>(` + #### Exp + + * "Exp " - Returns the mantissa for a given exp + * E.g. "Exp 5.5" + `, + "Exp", + [new Arg("amt", getEventV)], + async (world, {amt}) => getExpNumberV(world, amt.val) + ), + new Fetcher<{amt: StringV}, PreciseV>(` + #### Precisely + + * "Precisely " - Matches a number to given number of significant figures + * E.g. "Exactly 5.1000" - Matches to 5 sig figs + `, + "Precisely", + [ + new Arg("amt", getStringV) + ], + async (world, {amt}) => new PreciseV(toEncodableNum(amt.val), getSigFigs(amt.val)) + ), + new Fetcher<{}, AnythingV>(` + #### Anything + + * "Anything" - Matches any value for assertions + `, + "Anything", + [], + async (world, {}) => new AnythingV() + ), + new Fetcher<{}, NothingV>(` + #### Nothing + + * "Nothing" - Matches no values and is nothing. + `, + "Nothing", + [], + async (world, {}) => new NothingV() + ), + new Fetcher<{addr: AddressV}, AddressV>(` + #### Address + + * "Address arg:
" - Returns an address + `, + "Address", + [ + new Arg("addr", getAddressV) + ], + async (world, {addr}) => addr + ), + new Fetcher<{}, AddressV>(` + #### LastContract + + * "LastContract" - The address of last constructed contract + `, + "LastContract", + [], + async (world, {}) => new AddressV(world.get('lastContract')) + ), + new Fetcher<{}, NumberV>(` + #### LastGas + + * "LastGas" - The gas consumed by the last transaction + `, + "LastGas", + [], + async (world, {}) => { + let invokation = world.get('lastInvokation'); + if (!invokation) { + throw new Error(`Expected last invokation for "lastGas" but none found.`); + } + + if (!invokation.receipt) { + throw new Error(`Expected last invokation to have receipt for "lastGas" but none found.`); + } + + return new NumberV(invokation.receipt.gasUsed); + } + ), + new Fetcher<{els: Value[]}, AnythingV>(` + #### List + + * "List ..." - Returns a list of given elements + `, + "List", + [ + new Arg("els", getCoreValue, {variadic: true, mapped: true}) + ], + async (world, {els}) => new ListV(els) + ), + new Fetcher<{val: Value, def: EventV}, Value>(` + #### Default + + * "Default val: def:" - Returns value if truthy, otherwise default. Note: this **does** short circuit. + `, + "Default", + [ + new Arg("val", getCoreValue), + new Arg("def", getEventV) + ], + async (world, {val, def}) => { + if (val.truthy()) { + return val; + } else { + return await getCoreValue(world, def.val); + } + } + ), + new Fetcher<{res: Value}, Value>(` + #### User + + * "User ...userArgs" - Returns user value + `, + "User", + [ + new Arg("res", getUserValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: userFetchers() } + ), + new Fetcher<{address: AddressV}, Value>(` + #### EtherBalance + + * "EtherBalance
" - Returns given address' ether balance. + `, + "EtherBalance", + [ + new Arg("address", getAddressV) + ], + (world, {address}) => getEtherBalance(world, address.val) + ), + new Fetcher<{given: Value, expected: Value}, BoolV>(` + #### Equal + + * "Equal given: expected:" - Returns true if given values are equal + * E.g. "Equal (Exactly 0) Zero" + * E.g. "Equal (CToken cZRX TotalSupply) (Exactly 55)" + * E.g. "Equal (CToken cZRX Comptroller) (Comptroller Address)" + `, + "Equal", + [ + new Arg("given", getCoreValue), + new Arg("expected", getCoreValue) + ], + async (world, {given, expected}) => new BoolV(expected.compareTo(world, given)) + ), + new Fetcher<{res: Value}, Value>(` + #### Unitroller + + * "Unitroller ...unitrollerArgs" - Returns unitroller value + `, + "Unitroller", + [ + new Arg("res", getUnitrollerValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: unitrollerFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### Comptroller + + * "Comptroller ...comptrollerArgs" - Returns comptroller value + `, + "Comptroller", + [ + new Arg("res", getComptrollerValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: comptrollerFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### ComptrollerImpl + + * "ComptrollerImpl ...comptrollerImplArgs" - Returns comptroller implementation value + `, + "ComptrollerImpl", + [ + new Arg("res", getComptrollerImplValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: comptrollerImplFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### CToken + + * "CToken ...cTokenArgs" - Returns cToken value + `, + "CToken", + [ + new Arg("res", getCTokenValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: cTokenFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### Erc20 + + * "Erc20 ...erc20Args" - Returns Erc20 value + `, + "Erc20", + [ + new Arg("res", getErc20Value, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: erc20Fetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### InterestRateModel + + * "InterestRateModel ...interestRateModelArgs" - Returns InterestRateModel value + `, + "InterestRateModel", + [ + new Arg("res", getInterestRateModelValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: interestRateModelFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### PriceOracle + + * "PriceOracle ...priceOracleArgs" - Returns PriceOracle value + `, + "PriceOracle", + [ + new Arg("res", getPriceOracleValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: priceOracleFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### PriceOracleProxy + + * "PriceOracleProxy ...priceOracleProxyArgs" - Returns PriceOracleProxy value + `, + "PriceOracleProxy", + [ + new Arg("res", getPriceOracleProxyValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: priceOracleProxyFetchers() } + ), + new Fetcher<{res: Value}, Value>(` + #### Maximillion + + * "Maximillion ...maximillionArgs" - Returns Maximillion value + `, + "Maximillion", + [ + new Arg("res", getMaximillionValue, {variadic: true}) + ], + async (world, {res}) => res, + { subExpressions: maximillionFetchers() } + ) +]; + +export async function getCoreValue(world: World, event: Event): Promise { + return await getFetcherValue("Core", fetchers, world, event); +} diff --git a/scenario/src/Encoding.ts b/scenario/src/Encoding.ts new file mode 100644 index 000000000..5d9d278df --- /dev/null +++ b/scenario/src/Encoding.ts @@ -0,0 +1,37 @@ +import BigNumber from 'bignumber.js'; +import { utils, ethers } from 'ethers'; + +const smallEnoughNumber = new BigNumber('100000000'); + +export type encodedNumber = number | utils.BigNumber; + +// Returns the mantissa of an Exp with given floating value +export function getExpMantissa(float: number): encodedNumber { + // Workaround from https://github.com/ethereum/web3.js/issues/1920 + const str = Math.floor(float * 1.0e18).toString(); + + return toEncodableNum(str); +} + +export function toEncodableNum(amountArgRaw: string | encodedNumber): encodedNumber { + let bigNumber; + if (amountArgRaw instanceof BigNumber) { + bigNumber = amountArgRaw; + } else { + bigNumber = new BigNumber(amountArgRaw.toString()); + } + + if (bigNumber.lt(smallEnoughNumber)) { + // The Ethers abi encoder can handle regular numbers (including with fractional part) + // and its own internal big number class which is different from BigNumber.js published on npm (and can't accept + // fractional parts.) + // If the input is not huge, we just use a number, otherwise we try to use the Ethers class. + + return Number(amountArgRaw); + } else { + // bigNumberify (and the result class) only accept integers as digits, so we do .toFixed() to convert, for example, 1e4 to 10000. + // Rather than doing toFixed(0) and silently truncating a fractional part, we'll let it through and get an error. + // that case + return utils.bigNumberify(bigNumber.toFixed()); + } +} diff --git a/scenario/src/ErrorReporter.ts b/scenario/src/ErrorReporter.ts new file mode 100644 index 000000000..820b30aa1 --- /dev/null +++ b/scenario/src/ErrorReporter.ts @@ -0,0 +1,98 @@ +import {ComptrollerErr, TokenErr} from './ErrorReporterConstants'; + +export interface ErrorReporter { + getError(error: any): string | null + getInfo(info: any): string | null + getDetail(error: any, detail: number): string +} + +class NoErrorReporterType implements ErrorReporter { + getError(error: any): string | null { + return null; + } + + getInfo(info: any): string | null { + return null; + } + + getDetail(error: any, detail: number): string { + return detail.toString(); + } +} + +class CTokenErrorReporterType implements ErrorReporter { + getError(error: any): string | null { + if (error === null) { + return null; + } else { + return TokenErr.ErrorInv[Number(error)]; + } + } + + getInfo(info: any): string | null { + if (info === null) { + return null; + } else { + return TokenErr.FailureInfoInv[Number(info)]; + } + } + + getDetail(error: any, detail: number): string { + // Little hack to let us use proper names for cross-contract errors + if (this.getError(error) === "COMPTROLLER_REJECTION") { + let comptrollerError = ComptrollerErrorReporter.getError(detail); + + if (comptrollerError) { + return comptrollerError; + } + } + + return detail.toString(); + } +} + +class ComptrollerErrorReporterType implements ErrorReporter { + getError(error: any): string | null { + if (error === null) { + return null; + } else { + // TODO: This probably isn't right... + return ComptrollerErr.ErrorInv[Number(error)]; + } + } + + getInfo(info: any): string | null { + if (info === null) { + return null; + } else { + // TODO: This probably isn't right... + return ComptrollerErr.FailureInfoInv[Number(info)]; + } + } + + getDetail(error: any, detail: number): string { + if (this.getError(error) === "REJECTION") { + let comptrollerError = ComptrollerErrorReporter.getError(detail); + + if (comptrollerError) { + return comptrollerError; + } + } + + return detail.toString(); + } +} + +export function formatResult(errorReporter: ErrorReporter, result: any): string { + const errorStr = errorReporter.getError(result); + if (errorStr !== null) { + return `Error=${errorStr}` + } else { + return `Result=${result}`; + } +} + +// Singleton instances +export const NoErrorReporter = new NoErrorReporterType(); +export const CTokenErrorReporter = new CTokenErrorReporterType(); +export const ComptrollerErrorReporter = new ComptrollerErrorReporterType(); diff --git a/scenario/src/ErrorReporterConstants.ts b/scenario/src/ErrorReporterConstants.ts new file mode 100644 index 000000000..159180659 --- /dev/null +++ b/scenario/src/ErrorReporterConstants.ts @@ -0,0 +1,183 @@ + +interface ErrorReporterEnum { + Error: string[] + FailureInfo: string[] +} + +interface ErrorTypes { + Error: {[name: string]: number} + FailureInfo: {[name: string]: number} + ErrorInv: {[code: number]: string} + FailureInfoInv: {[code: number]: string} +} + +const ComptrollerErrorReporter = { + Error: [ + 'NO_ERROR', + 'UNAUTHORIZED', + 'COMPTROLLER_MISMATCH', + 'INSUFFICIENT_SHORTFALL', + 'INSUFFICIENT_LIQUIDITY', + 'INVALID_CLOSE_FACTOR', + 'INVALID_COLLATERAL_FACTOR', + 'INVALID_LIQUIDATION_INCENTIVE', + 'MARKET_NOT_ENTERED', + 'MARKET_NOT_LISTED', + 'MARKET_ALREADY_LISTED', + 'MATH_ERROR', + 'NONZERO_BORROW_BALANCE', + 'PRICE_ERROR', + 'REJECTION', + 'SNAPSHOT_ERROR', + 'TOO_MANY_ASSETS', + 'TOO_MUCH_REPAY' + ], + + FailureInfo: [ + 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK', + 'ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK', + 'EXIT_MARKET_BALANCE_OWED', + 'EXIT_MARKET_REJECTION', + 'SET_CLOSE_FACTOR_OWNER_CHECK', + 'SET_CLOSE_FACTOR_VALIDATION', + 'SET_COLLATERAL_FACTOR_OWNER_CHECK', + 'SET_COLLATERAL_FACTOR_NO_EXISTS', + 'SET_COLLATERAL_FACTOR_VALIDATION', + 'SET_COLLATERAL_FACTOR_WITHOUT_PRICE', + 'SET_IMPLEMENTATION_OWNER_CHECK', + 'SET_LIQUIDATION_INCENTIVE_OWNER_CHECK', + 'SET_LIQUIDATION_INCENTIVE_VALIDATION', + 'SET_MAX_ASSETS_OWNER_CHECK', + 'SET_PENDING_ADMIN_OWNER_CHECK', + 'SET_PENDING_IMPLEMENTATION_OWNER_CHECK', + 'SET_PRICE_ORACLE_OWNER_CHECK', + 'SUPPORT_MARKET_EXISTS', + 'SUPPORT_MARKET_OWNER_CHECK', + 'ZUNUSED' + ] +}; + +const TokenErrorReporter = { + Error: [ + 'NO_ERROR', + 'UNAUTHORIZED', + 'BAD_INPUT', + 'COMPTROLLER_REJECTION', + 'COMPTROLLER_CALCULATION_ERROR', + 'INTEREST_RATE_MODEL_ERROR', + 'INVALID_ACCOUNT_PAIR', + 'INVALID_CLOSE_AMOUNT_REQUESTED', + 'INVALID_COLLATERAL_FACTOR', + 'MATH_ERROR', + 'MARKET_NOT_FRESH', + 'MARKET_NOT_LISTED', + 'TOKEN_INSUFFICIENT_ALLOWANCE', + 'TOKEN_INSUFFICIENT_BALANCE', + 'TOKEN_INSUFFICIENT_CASH', + 'TOKEN_TRANSFER_IN_FAILED', + 'TOKEN_TRANSFER_OUT_FAILED' + ], + + FailureInfo: [ + 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK', + 'ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED', + 'ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED', + 'ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED', + 'ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED', + 'ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED', + 'ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED', + 'BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED', + 'BORROW_ACCRUE_INTEREST_FAILED', + 'BORROW_CASH_NOT_AVAILABLE', + 'BORROW_FRESHNESS_CHECK', + 'BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', + 'BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED', + 'BORROW_MARKET_NOT_LISTED', + 'BORROW_COMPTROLLER_REJECTION', + 'LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED', + 'LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED', + 'LIQUIDATE_COLLATERAL_FRESHNESS_CHECK', + 'LIQUIDATE_COMPTROLLER_REJECTION', + 'LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED', + 'LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX', + 'LIQUIDATE_CLOSE_AMOUNT_IS_ZERO', + 'LIQUIDATE_FRESHNESS_CHECK', + 'LIQUIDATE_LIQUIDATOR_IS_BORROWER', + 'LIQUIDATE_REPAY_BORROW_FRESH_FAILED', + 'LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED', + 'LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED', + 'LIQUIDATE_SEIZE_COMPTROLLER_REJECTION', + 'LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER', + 'LIQUIDATE_SEIZE_TOO_MUCH', + 'MINT_ACCRUE_INTEREST_FAILED', + 'MINT_COMPTROLLER_REJECTION', + 'MINT_EXCHANGE_CALCULATION_FAILED', + 'MINT_EXCHANGE_RATE_READ_FAILED', + 'MINT_FRESHNESS_CHECK', + 'MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED', + 'MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED', + 'MINT_TRANSFER_IN_FAILED', + 'MINT_TRANSFER_IN_NOT_POSSIBLE', + 'REDEEM_ACCRUE_INTEREST_FAILED', + 'REDEEM_COMPTROLLER_REJECTION', + 'REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED', + 'REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED', + 'REDEEM_EXCHANGE_RATE_READ_FAILED', + 'REDEEM_FRESHNESS_CHECK', + 'REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED', + 'REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED', + 'REDEEM_TRANSFER_OUT_NOT_POSSIBLE', + 'REDUCE_RESERVES_ACCRUE_INTEREST_FAILED', + 'REDUCE_RESERVES_ADMIN_CHECK', + 'REDUCE_RESERVES_CASH_NOT_AVAILABLE', + 'REDUCE_RESERVES_FRESH_CHECK', + 'REDUCE_RESERVES_VALIDATION', + 'REPAY_BEHALF_ACCRUE_INTEREST_FAILED', + 'REPAY_BORROW_ACCRUE_INTEREST_FAILED', + 'REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED', + 'REPAY_BORROW_COMPTROLLER_REJECTION', + 'REPAY_BORROW_FRESHNESS_CHECK', + 'REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED', + 'REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', + 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE', + 'SET_COLLATERAL_FACTOR_OWNER_CHECK', + 'SET_COLLATERAL_FACTOR_VALIDATION', + 'SET_COMPTROLLER_OWNER_CHECK', + 'SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED', + 'SET_INTEREST_RATE_MODEL_FRESH_CHECK', + 'SET_INTEREST_RATE_MODEL_OWNER_CHECK', + 'SET_MAX_ASSETS_OWNER_CHECK', + 'SET_ORACLE_MARKET_NOT_LISTED', + 'SET_PENDING_ADMIN_OWNER_CHECK', + 'SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED', + 'SET_RESERVE_FACTOR_ADMIN_CHECK', + 'SET_RESERVE_FACTOR_FRESH_CHECK', + 'SET_RESERVE_FACTOR_BOUNDS_CHECK', + 'TRANSFER_COMPTROLLER_REJECTION', + 'TRANSFER_NOT_ALLOWED', + 'TRANSFER_NOT_ENOUGH', + 'TRANSFER_TOO_MUCH' + ] +}; + +function parseEnum(reporterEnum: ErrorReporterEnum): ErrorTypes { + const Error: {[name: string]: number} = {}; + const ErrorInv: {[code: number]: string} = {}; + const FailureInfo: {[name: string]: number} = {}; + const FailureInfoInv: {[code: number]: string} = {}; + + reporterEnum.Error.forEach((entry, i) => { + Error[entry] = i; + ErrorInv[i] = entry; + }); + + reporterEnum.FailureInfo.forEach((entry, i) => { + FailureInfo[entry] = i; + FailureInfoInv[i] = entry; + }); + + return {Error, ErrorInv, FailureInfo, FailureInfoInv}; +} + +export const ComptrollerErr = parseEnum(ComptrollerErrorReporter); +export const TokenErr = parseEnum(TokenErrorReporter); diff --git a/scenario/src/Event.ts b/scenario/src/Event.ts new file mode 100644 index 000000000..b5eb6e373 --- /dev/null +++ b/scenario/src/Event.ts @@ -0,0 +1,7 @@ + +type ScalarEvent = string; +interface EventArray extends Array { + [index: number]: ScalarEvent | EventArray; +} + +export type Event = EventArray; diff --git a/scenario/src/Event/AssertionEvent.ts b/scenario/src/Event/AssertionEvent.ts new file mode 100644 index 000000000..0fa52505f --- /dev/null +++ b/scenario/src/Event/AssertionEvent.ts @@ -0,0 +1,345 @@ +import {Event} from '../Event'; +import {fail, World} from '../World'; +import {mustArray} from '../Utils'; +import {getCoreValue} from '../CoreValue'; +import {formatError} from '../Formatter'; +import {Failure, Invokation, InvokationRevertFailure} from '../Invokation'; +import {formatEvent} from '../Formatter'; +import { + getAddressV, + getBoolV, + getEventV, + getMapV, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + BoolV, + EventV, + MapV, + NumberV, + Order, + StringV, + Value +} from '../Value'; +import {Arg, View, processCommandEvent} from '../Command'; + +async function assertEqual(world: World, given: Value, expected: Value): Promise { + if (!expected.compareTo(world, given)) { + return fail(world, `Expected ${given.toString()} to equal ${expected.toString()}`); + } + + return world; +} + +async function assertLessThan(world: World, given: Value, expected: Value): Promise { + if (given.compareOrder(world, expected) !== Order.LESS_THAN) { + return fail(world, `Expected ${given.toString()} to be less than ${expected.toString()}`); + } + + return world; +} + +async function assertFailure(world: World, failure: Failure): Promise { + if (!world.lastInvokation) { + return fail(world, `Expected ${failure.toString()}, but missing any invokations.`); + } + + if (world.lastInvokation.success()) { + return fail(world, `Expected ${failure.toString()}, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); + } + + if (world.lastInvokation.error) { + return fail(world, `Expected ${failure.toString()}, but last invokation threw error ${world.lastInvokation.error}.`); + } + + if (world.lastInvokation.failures.length === 0) { + throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); + } + + if (world.lastInvokation.failures.find((f) => f.equals(failure)) === undefined) { + return fail(world, `Expected ${failure.toString()}, but got ${world.lastInvokation.failures.toString()}.`); + } + + return world; +} + +async function assertRevertFailure(world: World, err: string, message: string): Promise { + if (!world.lastInvokation) { + return fail(world, `Expected revert failure, but missing any invokations.`); + } + + if (world.lastInvokation.success()) { + return fail(world, `Expected revert failure, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); + } + + if (world.lastInvokation.failures.length > 0) { + return fail(world, `Expected revert failure, but got ${world.lastInvokation.failures.toString()}.`); + } + + if (!world.lastInvokation.error) { + throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); + } + + if (!(world.lastInvokation.error instanceof InvokationRevertFailure)) { + throw new Error(`Invokation error mismatch, expected revert failure: "${err}, ${message}", got: "${world.lastInvokation.error.toString()}"`); + } + + const expectedMessage = `Returned error: VM Exception while processing transaction: ${message}`; + + if (world.lastInvokation.error.error !== err || world.lastInvokation.error.errMessage !== expectedMessage) { + throw new Error(`Invokation error mismatch, expected revert failure: err=${err}, message="${expectedMessage}", got: "${world.lastInvokation.error.toString()}"`); + } + + return world; +} + +async function assertError(world: World, message: string): Promise { + if (!world.lastInvokation) { + return fail(world, `Expected revert, but missing any invokations.`); + } + + if (world.lastInvokation.success()) { + return fail(world, `Expected revert, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); + } + + if (world.lastInvokation.failures.length > 0) { + return fail(world, `Expected revert, but got ${world.lastInvokation.failures.toString()}.`); + } + + if (!world.lastInvokation.error) { + throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); + } + + if (!world.lastInvokation.error.message.startsWith(message)) { + throw new Error(`Invokation error mismatch, expected: "${message}", got: "${world.lastInvokation.error.message}"`); + } + + return world; +} + +function buildRevertMessage(world: World, message: string): string { + return `Returned error: VM Exception while processing transaction: ${message}` +} + +async function assertRevert(world: World, message: string): Promise { + return await assertError(world, buildRevertMessage(world, message)); +} + +async function assertSuccess(world: World): Promise { + if (!world.lastInvokation || world.lastInvokation.success()) { + return world; + } else { + return fail(world, `Expected success, but got ${world.lastInvokation.toString()}.`); + } +} + +async function assertReadError(world: World, event: Event, message: string, isRevert: boolean): Promise { + try { + let value = await getCoreValue(world, event); + + throw new Error(`Expected read revert, instead got value \`${value}\``); + } catch (err) { + let expectedMessage; + if (isRevert) { + expectedMessage = buildRevertMessage(world, message); + } else { + expectedMessage = message; + } + + world.assert.equal(expectedMessage, err.message, "expected read revert"); + } + + return world; +} + +async function assertLog(world: World, event: string, keyValues: MapV): Promise { + if (!world.lastInvokation) { + return fail(world, `Expected log message "${event}" from contract execution, but world missing any invokations.`); + } else if (!world.lastInvokation.receipt) { + return fail(world, `Expected log message "${event}" from contract execution, but world invokation transaction.`); + } else { + const log = world.lastInvokation.receipt.events[event]; + + if (!log) { + const events = Object.keys(world.lastInvokation.receipt.events).join(', '); + + fail(world, `Expected log with event \`${event}\`, found logs with events: [${events}]`); + } + + Object.entries(keyValues.val).forEach(([key, value]) => { + if (log.returnValues[key] === undefined) { + fail(world, `Expected log to have param for \`${key}\``); + } else { + let logValue = new StringV(log.returnValues[key]); + + if (!value.compareTo(world, logValue)) { + fail(world, `Expected log to have param \`${key}\` to match ${value.toString()}, but got ${logValue.toString()}`); + } + } + }); + + return world; + } +} + +export function assertionCommands() { + return [ + new View<{given: Value, expected: Value}>(` + #### Equal + + * "Equal given: expected:" - Asserts that given matches expected. + * E.g. "Assert Equal (Exactly 0) Zero" + * E.g. "Assert Equal (CToken cZRX TotalSupply) (Exactly 55)" + * E.g. "Assert Equal (CToken cZRX Comptroller) (Comptroller Address)" + `, + "Equal", + [ + new Arg("given", getCoreValue), + new Arg("expected", getCoreValue) + ], + (world, {given, expected}) => assertEqual(world, given, expected) + ), + new View<{given: Value, expected: Value}>(` + #### LessThan + + * "given: LastThan expected:" - Asserts that given matches expected. + * E.g. "Assert (Exactly 0) LessThan (Exactly 1)" + `, + "LessThan", + [ + new Arg("given", getCoreValue), + new Arg("expected", getCoreValue) + ], + (world, {given, expected}) => assertLessThan(world, given, expected), + {namePos: 1} + ), + new View<{given: Value}>(` + #### True + + * "True given:" - Asserts that given is true. + * E.g. "Assert True (Comptroller CheckMembership Geoff cETH)" + `, + "True", + [ + new Arg("given", getCoreValue) + ], + (world, {given}) => assertEqual(world, given, new BoolV(true)) + ), + new View<{given: Value}>(` + #### False + + * "False given:" - Asserts that given is false. + * E.g. "Assert False (Comptroller CheckMembership Geoff cETH)" + `, + "False", + [ + new Arg("given", getCoreValue) + ], + (world, {given}) => assertEqual(world, given, new BoolV(false)) + ), + new View<{event: EventV, message: StringV}>(` + #### ReadRevert + + * "ReadRevert event: message:" - Asserts that reading the given value reverts with given message. + * E.g. "Assert ReadRevert (Comptroller CheckMembership Geoff cETH) \"revert\"" + `, + "ReadRevert", + [ + new Arg("event", getEventV), + new Arg("message", getStringV) + ], + (world, {event, message}) => assertReadError(world, event.val, message.val, true) + ), + new View<{event: EventV, message: StringV}>(` + #### ReadError + + * "ReadError event: message:" - Asserts that reading the given value throws given error + * E.g. "Assert ReadError (Comptroller Bad Address) \"cannot find comptroller\"" + `, + "ReadError", + [ + new Arg("event", getEventV), + new Arg("message", getStringV) + ], + (world, {event, message}) => assertReadError(world, event.val, message.val, false) + ), + new View<{error: StringV, info: StringV, detail: StringV}>(` + #### Failure + + * "Failure error: info: detail:" - Asserts that last transaction had a graceful failure with given error, info and detail. + * E.g. "Assert Failure UNAUTHORIZED SUPPORT_MARKET_OWNER_CHECK" + * E.g. "Assert Failure MATH_ERROR MINT_CALCULATE_BALANCE 5" + `, + "Failure", + [ + new Arg("error", getStringV), + new Arg("info", getStringV), + new Arg("detail", getStringV, {default: new StringV("0")}), + ], + (world, {error, info, detail}) => assertFailure(world, new Failure(error.val, info.val, detail.val)) + ), + new View<{error: StringV, message: StringV}>(` + #### RevertFailure + + * "RevertFailure error: message:" - Assert last transaction reverted with a message beginning with an error code + * E.g. "Assert RevertFailure UNAUTHORIZED \"set reserves failed\"" + `, + "RevertFailure", + [ + new Arg("error", getStringV), + new Arg("message", getStringV), + ], + (world, {error, message}) => assertRevertFailure(world, error.val, message.val) + ), + new View<{message: StringV}>(` + #### Revert + + * "Revert message:" - Asserts that the last transaction reverted. + `, + "Revert", + [ + new Arg("message", getStringV, {default: new StringV("revert")}), + ], + (world, {message}) => assertRevert(world, message.val) + ), + new View<{message: StringV}>(` + #### Error + + * "Error message:" - Asserts that the last transaction had the given error. + `, + "Error", + [ + new Arg("message", getStringV), + ], + (world, {message}) => assertError(world, message.val) + ), + new View<{given: Value}>(` + #### Success + + * "Success" - Asserts that the last transaction completed successfully (that is, did not revert nor emit graceful failure). + `, + "Success", + [], + (world, {given}) => assertSuccess(world) + ), + new View<{name: StringV, params: MapV}>(` + #### Log + + * "Log name: (key: value:) ..." - Asserts that last transaction emitted log with given name and key-value pairs. + * E.g. "Assert Log Minted ("account" (User Geoff address)) ("amount" (Exactly 55))" + `, + "Log", + [ + new Arg("name", getStringV), + new Arg("params", getMapV, {variadic: true}), + ], + (world, {name, params}) => assertLog(world, name.val, params) + ) + ]; +} + +export async function processAssertionEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Assertion", assertionCommands(), world, event, from); +} diff --git a/scenario/src/Event/CTokenEvent.ts b/scenario/src/Event/CTokenEvent.ts new file mode 100644 index 000000000..119ddcfcb --- /dev/null +++ b/scenario/src/Event/CTokenEvent.ts @@ -0,0 +1,717 @@ +import {Event} from '../Event'; +import {addAction, describeUser, World} from '../World'; +import {decodeCall, getPastEvents} from '../Contract'; +import {CToken, CTokenScenario} from '../Contract/CToken'; +import {invoke, Sendable} from '../Invokation'; +import { + getAddressV, + getEventV, + getExpNumberV, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + EventV, + NothingV, + NumberV, + StringV} from '../Value'; +import {Arg, Command, View, processCommandEvent} from '../Command'; +import {CTokenErrorReporter} from '../ErrorReporter'; +import {getComptroller, getCTokenData} from '../ContractLookup'; +import {getExpMantissa} from '../Encoding'; +import {buildCToken} from '../Builder/CTokenBuilder'; +import {verify} from '../Verify'; +import {getLiquidity} from '../Value/ComptrollerValue'; +import {encodedNumber} from '../Encoding'; +import {getCTokenV} from '../Value/CTokenValue'; + +function showTrxValue(world: World): string { + return new NumberV(world.trxInvokationOpts.get('value')).show(); +} + +async function genCToken(world: World, from: string, event: Event): Promise { + let {world: nextWorld, cToken, tokenData} = await buildCToken(world, from, event); + world = nextWorld; + + world = addAction( + world, + `Added cToken ${tokenData.name} (${tokenData.contract}) at address ${cToken._address}`, + tokenData.invokation + ); + + return world; +} + +async function accrueInterest(world: World, from: string, cToken: CToken): Promise { + let invokation = await invoke(world, cToken.methods.accrueInterest(), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: Interest accrued`, + invokation + ); + + return world; +} + +async function mint(world: World, from: string, cToken: CToken, amount: NumberV | NothingV): Promise { + let invokation; + let showAmount; + + if (amount instanceof NumberV) { + showAmount = amount.show(); + invokation = await invoke(world, cToken.methods.mint(amount.encode()), from, CTokenErrorReporter); + } else { + showAmount = showTrxValue(world); + invokation = await invoke(world, cToken.methods.mint(), from, CTokenErrorReporter); + } + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} mints ${showAmount}`, + invokation + ); + + return world; +} + +async function redeem(world: World, from: string, cToken: CToken, tokens: NumberV): Promise { + let invokation = await invoke(world, cToken.methods.redeem(tokens.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} redeems ${tokens.show()} tokens`, + invokation + ); + + return world; +} + +async function redeemUnderlying(world: World, from: string, cToken: CToken, amount: NumberV): Promise { + let invokation = await invoke(world, cToken.methods.redeemUnderlying(amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} redeems ${amount.show()} underlying`, + invokation + ); + + return world; +} + +async function borrow(world: World, from: string, cToken: CToken, amount: NumberV): Promise { + let invokation = await invoke(world, cToken.methods.borrow(amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} borrows ${amount.show()}`, + invokation + ); + + return world; +} + +async function repayBorrow(world: World, from: string, cToken: CToken, amount: NumberV | NothingV): Promise { + let invokation; + let showAmount; + + if (amount instanceof NumberV) { + showAmount = amount.show(); + invokation = await invoke(world, cToken.methods.repayBorrow(amount.encode()), from, CTokenErrorReporter); + } else { + showAmount = showTrxValue(world); + invokation = await invoke(world, cToken.methods.repayBorrow(), from, CTokenErrorReporter); + } + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} repays ${showAmount} of borrow`, + invokation + ); + + return world; +} + +async function repayBorrowBehalf(world: World, from: string, behalf: string, cToken: CToken, amount: NumberV | NothingV): Promise { + let invokation; + let showAmount; + + if (amount instanceof NumberV) { + showAmount = amount.show(); + invokation = await invoke(world, cToken.methods.repayBorrowBehalf(behalf, amount.encode()), from, CTokenErrorReporter); + } else { + showAmount = showTrxValue(world); + invokation = await invoke(world, cToken.methods.repayBorrowBehalf(behalf), from, CTokenErrorReporter); + } + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} repays ${showAmount} of borrow on behalf of ${describeUser(world, behalf)}`, + invokation + ); + + return world; +} + +async function liquidateBorrow(world: World, from: string, cToken: CToken, borrower: string, collateral: CToken, repayAmount: NumberV | NothingV): Promise { + let invokation; + let showAmount; + + if (repayAmount instanceof NumberV) { + showAmount = repayAmount.show(); + invokation = await invoke(world, cToken.methods.liquidateBorrow(borrower, repayAmount.encode(), collateral._address), from, CTokenErrorReporter); + } else { + showAmount = showTrxValue(world); + invokation = await invoke(world, cToken.methods.liquidateBorrow(borrower, collateral._address), from, CTokenErrorReporter); + } + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} liquidates ${showAmount} from of ${describeUser(world, borrower)}, seizing ${collateral.name}.`, + invokation + ); + + return world; +} + +async function seize(world: World, from: string, cToken: CToken, liquidator: string, borrower: string, seizeTokens: NumberV): Promise { + let invokation = await invoke(world, cToken.methods.seize(liquidator, borrower, seizeTokens.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} initiates seizing ${seizeTokens.show()} to ${describeUser(world, liquidator)} from ${describeUser(world, borrower)}.`, + invokation + ); + + return world; +} + +async function evilSeize(world: World, from: string, cToken: CToken, treasure: CToken, liquidator: string, borrower: string, seizeTokens: NumberV): Promise { + let invokation = await invoke(world, cToken.methods.evilSeize(treasure._address, liquidator, borrower, seizeTokens.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} initiates illegal seizing ${seizeTokens.show()} to ${describeUser(world, liquidator)} from ${describeUser(world, borrower)}.`, + invokation + ); + + return world; +} + +async function setPendingAdmin(world: World, from: string, cToken: CToken, newPendingAdmin: string): Promise { + let invokation = await invoke(world, cToken.methods._setPendingAdmin(newPendingAdmin), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} sets pending admin to ${newPendingAdmin}`, + invokation + ); + + return world; +} + +async function acceptAdmin(world: World, from: string, cToken: CToken): Promise { + let invokation = await invoke(world, cToken.methods._acceptAdmin(), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} accepts admin`, + invokation + ); + + return world; +} + +async function reduceReserves(world: World, from: string, cToken: CToken, amount: NumberV): Promise { + let invokation = await invoke(world, cToken.methods._reduceReserves(amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} reduces reserves by ${amount.show()}`, + invokation + ); + + return world; +} + +async function setReserveFactor(world: World, from: string, cToken: CToken, reserveFactor: NumberV): Promise { + let invokation = await invoke(world, cToken.methods._setReserveFactor(reserveFactor.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `CToken ${cToken.name}: ${describeUser(world, from)} sets reserve factor to ${reserveFactor.show()}`, + invokation + ); + + return world; +} + +async function setInterestRateModel(world: World, from: string, cToken: CToken, interestRateModel: string): Promise { + let invokation = await invoke(world, cToken.methods._setInterestRateModel(interestRateModel), from, CTokenErrorReporter); + + world = addAction( + world, + `Set interest rate for ${cToken.name} to ${interestRateModel} as ${describeUser(world, from)}`, + invokation + ); + + return world; +} + +async function setComptroller(world: World, from: string, cToken: CToken, comptroller: string): Promise { + let invokation = await invoke(world, cToken.methods._setComptroller(comptroller), from, CTokenErrorReporter); + + world = addAction( + world, + `Set comptroller for ${cToken.name} to ${comptroller} as ${describeUser(world, from)}`, + invokation + ); + + return world; +} + +async function donate(world: World, from: string, cToken: CToken): Promise { + let invokation = await invoke(world, cToken.methods.donate(), from, CTokenErrorReporter); + + world = addAction( + world, + `Donate for ${cToken.name} as ${describeUser(world, from)} with value ${showTrxValue(world)}`, + invokation + ); + + return world; +} + +async function setCTokenMock(world: World, from: string, cToken: CTokenScenario, mock: string, value: NumberV): Promise { + let mockMethod: (number) => Sendable; + + switch (mock.toLowerCase()) { + case "totalborrows": + mockMethod = cToken.methods.setTotalBorrows; + break; + case "totalreserves": + mockMethod = cToken.methods.setTotalReserves; + break; + default: + throw new Error(`Mock "${mock}" not defined for cToken`); + } + + let invokation = await invoke(world, mockMethod(value.encode()), from); + + world = addAction( + world, + `Mocked ${mock}=${value.show()} for ${cToken.name}`, + invokation + ); + + return world; +} + +async function verifyCToken(world: World, cToken: CToken, name: string, contract: string, apiKey: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, name, contract, cToken._address); + } + + return world; +} + +async function printMinters(world: World, cToken: CToken): Promise { + let events = await getPastEvents(world, cToken, cToken.name, 'Mint'); + let addresses = events.map((event) => event.returnValues['minter']); + let uniq = [...new Set(addresses)]; + + world.printer.printLine("Minters:") + + uniq.forEach((address) => { + world.printer.printLine(`\t${address}`) + }); + + return world; +} + +async function printBorrowers(world: World, cToken: CToken): Promise { + let events = await getPastEvents(world, cToken, cToken.name, 'Borrow'); + let addresses = events.map((event) => event.returnValues['borrower']); + let uniq = [...new Set(addresses)]; + + world.printer.printLine("Borrowers:") + + uniq.forEach((address) => { + world.printer.printLine(`\t${address}`) + }); + + return world; +} + +async function printLiquidity(world: World, cToken: CToken): Promise { + let mintEvents = await getPastEvents(world, cToken, cToken.name, 'Mint'); + let mintAddresses = mintEvents.map((event) => event.returnValues['minter']); + let borrowEvents = await getPastEvents(world, cToken, cToken.name, 'Borrow'); + let borrowAddresses = borrowEvents.map((event) => event.returnValues['borrower']); + let uniq = [...new Set(mintAddresses.concat(borrowAddresses))]; + let comptroller = await getComptroller(world); + + world.printer.printLine("Liquidity:") + + const liquidityMap = await Promise.all(uniq.map(async (address) => { + let userLiquidity = await getLiquidity(world, comptroller, address); + + return [address, userLiquidity.val]; + })); + + liquidityMap.forEach(([address, liquidity]) => { + world.printer.printLine(`\t${world.settings.lookupAlias(address)}: ${liquidity / 1e18}e18`) + }); + + return world; +} + +export function cTokenCommands() { + return [ + new Command<{cTokenParams: EventV}>(` + #### Deploy + + * "CToken Deploy ...cTokenParams" - Generates a new CToken + * E.g. "CToken cZRX Deploy" + `, + "Deploy", + [new Arg("cTokenParams", getEventV, {variadic: true})], + (world, from, {cTokenParams}) => genCToken(world, from, cTokenParams.val) + ), + new View<{cTokenArg: StringV, apiKey: StringV}>(` + #### Verify + + * "CToken Verify apiKey:" - Verifies CToken in Etherscan + * E.g. "CToken cZRX Verify "myApiKey" + `, + "Verify", + [ + new Arg("cTokenArg", getStringV), + new Arg("apiKey", getStringV) + ], + async (world, {cTokenArg, apiKey}) => { + let [cToken, name, data] = await getCTokenData(world, cTokenArg.val); + + return await verifyCToken(world, cToken, name, data.get('contract')!, apiKey.val); + }, + {namePos: 1} + ), + new Command<{cToken: CToken}>(` + #### AccrueInterest + + * "CToken AccrueInterest" - Accrues interest for given token + * E.g. "CToken cZRX AccrueInterest" + `, + "AccrueInterest", + [ + new Arg("cToken", getCTokenV) + ], + (world, from, {cToken}) => accrueInterest(world, from, cToken), + {namePos: 1} + ), + new Command<{cToken: CToken, amount: NumberV | NothingV}>(` + #### Mint + + * "CToken Mint amount:" - Mints the given amount of cToken as specified user + * E.g. "CToken cZRX Mint 1.0e18" + `, + "Mint", + [ + new Arg("cToken", getCTokenV), + new Arg("amount", getNumberV, {nullable: true}) + ], + (world, from, {cToken, amount}) => mint(world, from, cToken, amount), + {namePos: 1} + ), + new Command<{cToken: CToken, tokens: NumberV}>(` + #### Redeem + + * "CToken Redeem tokens:" - Redeems the given amount of cTokens as specified user + * E.g. "CToken cZRX Redeem 1.0e9" + `, + "Redeem", + [ + new Arg("cToken", getCTokenV), + new Arg("tokens", getNumberV) + ], + (world, from, {cToken, tokens}) => redeem(world, from, cToken, tokens), + {namePos: 1} + ), + new Command<{cToken: CToken, amount: NumberV}>(` + #### RedeemUnderlying + + * "CToken RedeemUnderlying amount:" - Redeems the given amount of underlying as specified user + * E.g. "CToken cZRX RedeemUnderlying 1.0e18" + `, + "RedeemUnderlying", + [ + new Arg("cToken", getCTokenV), + new Arg("amount", getNumberV) + ], + (world, from, {cToken, amount}) => redeemUnderlying(world, from, cToken, amount), + {namePos: 1} + ), + new Command<{cToken: CToken, amount: NumberV}>(` + #### Borrow + + * "CToken Borrow amount:" - Borrows the given amount of this cToken as specified user + * E.g. "CToken cZRX Borrow 1.0e18" + `, + "Borrow", + [ + new Arg("cToken", getCTokenV), + new Arg("amount", getNumberV) + ], + // Note: we override from + (world, from, {cToken, amount}) => borrow(world, from, cToken, amount), + {namePos: 1} + ), + new Command<{cToken: CToken, amount: NumberV | NothingV}>(` + #### RepayBorrow + + * "CToken RepayBorrow underlyingAmount:" - Repays borrow in the given underlying amount as specified user + * E.g. "CToken cZRX RepayBorrow 1.0e18" + `, + "RepayBorrow", + [ + new Arg("cToken", getCTokenV), + new Arg("amount", getNumberV, {nullable: true}) + ], + (world, from, {cToken, amount}) => repayBorrow(world, from, cToken, amount), + {namePos: 1} + ), + new Command<{cToken: CToken, behalf: AddressV, amount: NumberV | NothingV}>(` + #### RepayBorrowBehalf + + * "CToken RepayBorrowBehalf behalf: underlyingAmount:" - Repays borrow in the given underlying amount on behalf of another user + * E.g. "CToken cZRX RepayBorrowBehalf Geoff 1.0e18" + `, + "RepayBorrowBehalf", + [ + new Arg("cToken", getCTokenV), + new Arg("behalf", getAddressV), + new Arg("amount", getNumberV, {nullable: true}) + ], + (world, from, {cToken, behalf, amount}) => repayBorrowBehalf(world, from, behalf.val, cToken, amount), + {namePos: 1} + ), + new Command<{borrower: AddressV, cToken: CToken, collateral: CToken, repayAmount: NumberV | NothingV}>(` + #### Liquidate + + * "CToken Liquidate borrower: cTokenCollateral:
repayAmount:" - Liquidates repayAmount of given token seizing collateral token + * E.g. "CToken cZRX Liquidate Geoff cBAT 1.0e18" + `, + "Liquidate", + [ + new Arg("cToken", getCTokenV), + new Arg("borrower", getAddressV), + new Arg("collateral", getCTokenV), + new Arg("repayAmount", getNumberV, {nullable: true}) + ], + (world, from, {borrower, cToken, collateral, repayAmount}) => liquidateBorrow(world, from, cToken, borrower.val, collateral, repayAmount), + {namePos: 1} + ), + new Command<{cToken: CToken, liquidator: AddressV, borrower: AddressV, seizeTokens: NumberV}>(` + #### Seize + + * "CToken Seize liquidator: borrower: seizeTokens:" - Seizes a given number of tokens from a user (to be called from other CToken) + * E.g. "CToken cZRX Seize Geoff Torrey 1.0e18" + `, + "Seize", + [ + new Arg("cToken", getCTokenV), + new Arg("liquidator", getAddressV), + new Arg("borrower", getAddressV), + new Arg("seizeTokens", getNumberV) + ], + (world, from, {cToken, liquidator, borrower, seizeTokens}) => seize(world, from, cToken, liquidator.val, borrower.val, seizeTokens), + {namePos: 1} + ), + new Command<{cToken: CToken, treasure: CToken, liquidator: AddressV, borrower: AddressV, seizeTokens: NumberV}>(` + #### EvilSeize + + * "CToken EvilSeize treasure: liquidator: borrower: seizeTokens:" - Improperly seizes a given number of tokens from a user + * E.g. "CToken cEVL EvilSeize cZRX Geoff Torrey 1.0e18" + `, + "EvilSeize", + [ + new Arg("cToken", getCTokenV), + new Arg("treasure", getCTokenV), + new Arg("liquidator", getAddressV), + new Arg("borrower", getAddressV), + new Arg("seizeTokens", getNumberV) + ], + (world, from, {cToken, treasure, liquidator, borrower, seizeTokens}) => evilSeize(world, from, cToken, treasure, liquidator.val, borrower.val, seizeTokens), + {namePos: 1} + ), + new Command<{cToken: CToken, amount: NumberV}>(` + #### ReduceReserves + + * "CToken ReduceReserves amount:" - Reduces the reserves of the cToken + * E.g. "CToken cZRX ReduceReserves 1.0e18" + `, + "ReduceReserves", + [ + new Arg("cToken", getCTokenV), + new Arg("amount", getNumberV) + ], + (world, from, {cToken, amount}) => reduceReserves(world, from, cToken, amount), + {namePos: 1} + ), + new Command<{cToken: CToken, newPendingAdmin: AddressV}>(` + #### SetPendingAdmin + + * "CToken SetPendingAdmin newPendingAdmin:
" - Sets the pending admin for the cToken + * E.g. "CToken cZRX SetPendingAdmin Geoff" + `, + "SetPendingAdmin", + [ + new Arg("cToken", getCTokenV), + new Arg("newPendingAdmin", getAddressV) + ], + (world, from, {cToken, newPendingAdmin}) => setPendingAdmin(world, from, cToken, newPendingAdmin.val), + {namePos: 1} + ), + new Command<{cToken: CToken}>(` + #### AcceptAdmin + + * "CToken AcceptAdmin" - Accepts admin for the cToken + * E.g. "From Geoff (CToken cZRX AcceptAdmin)" + `, + "AcceptAdmin", + [ + new Arg("cToken", getCTokenV) + ], + (world, from, {cToken}) => acceptAdmin(world, from, cToken), + {namePos: 1} + ), + new Command<{cToken: CToken, reserveFactor: NumberV}>(` + #### SetReserveFactor + + * "CToken SetReserveFactor reserveFactor:" - Sets the reserve factor for the cToken + * E.g. "CToken cZRX SetReserveFactor 0.1" + `, + "SetReserveFactor", + [ + new Arg("cToken", getCTokenV), + new Arg("reserveFactor", getExpNumberV) + ], + (world, from, {cToken, reserveFactor}) => setReserveFactor(world, from, cToken, reserveFactor), + {namePos: 1} + ), + new Command<{cToken: CToken, interestRateModel: AddressV}>(` + #### SetInterestRateModel + + * "CToken SetInterestRateModel interestRateModel:" - Sets the interest rate model for the given cToken + * E.g. "CToken cZRX SetInterestRateModel (FixedRate 1.5)" + `, + "SetInterestRateModel", + [ + new Arg("cToken", getCTokenV), + new Arg("interestRateModel", getAddressV) + ], + (world, from, {cToken, interestRateModel}) => setInterestRateModel(world, from, cToken, interestRateModel.val), + {namePos: 1} + ), + new Command<{cToken: CToken, comptroller: AddressV}>(` + #### SetComptroller + + * "CToken SetComptroller comptroller:" - Sets the comptroller for the given cToken + * E.g. "CToken cZRX SetComptroller Comptroller" + `, + "SetComptroller", + [ + new Arg("cToken", getCTokenV), + new Arg("comptroller", getAddressV) + ], + (world, from, {cToken, comptroller}) => setComptroller(world, from, cToken, comptroller.val), + {namePos: 1} + ), + new Command<{cToken: CToken}>(` + #### Donate + + * "CToken Donate" - Calls the donate (payable no-op) function + * E.g. "(Trx Value 5.0e18 (CToken cETH Donate))" + `, + "Donate", + [ + new Arg("cToken", getCTokenV) + ], + (world, from, {cToken}) => donate(world, from, cToken), + {namePos: 1} + ), + new Command<{cToken: CToken, variable: StringV, value: NumberV}>(` + #### Mock + + * "CToken Mock variable: value:" - Mocks a given value on cToken. Note: value must be a supported mock and this will only work on a "CTokenScenario" contract. + * E.g. "CToken cZRX Mock totalBorrows 5.0e18" + * E.g. "CToken cZRX Mock totalReserves 0.5e18" + `, + "Mock", + [ + new Arg("cToken", getCTokenV), + new Arg("variable", getStringV), + new Arg("value", getNumberV), + ], + (world, from, {cToken, variable, value}) => setCTokenMock(world, from, cToken, variable.val, value), + {namePos: 1} + ), + new View<{cToken: CToken}>(` + #### Minters + + * "CToken Minters" - Print address of all minters + `, + "Minters", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => printMinters(world, cToken), + {namePos: 1} + ), + new View<{cToken: CToken}>(` + #### Borrowers + + * "CToken Borrowers" - Print address of all borrowers + `, + "Borrowers", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => printBorrowers(world, cToken), + {namePos: 1} + ), + new View<{cToken: CToken}>(` + #### Liquidity + + * "CToken Liquidity" - Prints liquidity of all minters or borrowers + `, + "Liquidity", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => printLiquidity(world, cToken), + {namePos: 1} + ), + new View<{cToken: CToken, input: StringV}>(` + #### Decode + + * "Decode input:" - Prints information about a call to a cToken contract + `, + "Decode", + [ + new Arg("cToken", getCTokenV), + new Arg("input", getStringV) + + ], + (world, {cToken, input}) => decodeCall(world, cToken, input.val), + {namePos: 1} + ) + ]; +} + +export async function processCTokenEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("CToken", cTokenCommands(), world, event, from); +} diff --git a/scenario/src/Event/ComptrollerEvent.ts b/scenario/src/Event/ComptrollerEvent.ts new file mode 100644 index 000000000..438bc7be6 --- /dev/null +++ b/scenario/src/Event/ComptrollerEvent.ts @@ -0,0 +1,447 @@ +import {Event} from '../Event'; +import {addAction, describeUser, World} from '../World'; +import {decodeCall, getPastEvents} from '../Contract'; +import {Comptroller} from '../Contract/Comptroller'; +import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; +import {CToken} from '../Contract/CToken'; +import {invoke} from '../Invokation'; +import { + getAddressV, + getBoolV, + getEventV, + getExpNumberV, + getNumberV, + getPercentV, + getStringV +} from '../CoreValue'; +import { + AddressV, + BoolV, + EventV, + NumberV, + StringV +} from '../Value'; +import {Arg, Command, View, processCommandEvent} from '../Command'; +import {buildComptrollerImpl} from '../Builder/ComptrollerImplBuilder'; +import {ComptrollerErrorReporter} from '../ErrorReporter'; +import {getComptroller, getComptrollerImpl} from '../ContractLookup'; +import {getLiquidity} from '../Value/ComptrollerValue'; +import {getCTokenV} from '../Value/CTokenValue'; +import {encodedNumber} from '../Encoding'; + +async function genComptroller(world: World, from: string, params: Event): Promise { + let {world: nextWorld, comptrollerImpl: comptroller, comptrollerImplData: comptrollerData} = await buildComptrollerImpl(world, from, params); + world = nextWorld; + + world = addAction( + world, + `Added Comptroller (${comptrollerData.description}) at address ${comptroller._address}`, + comptrollerData.invokation + ); + + return world; +}; + +async function setPaused(world: World, from: string, comptroller: Comptroller, actionName: string, isPaused: boolean): Promise { + const pauseMap = { + "Mint": comptroller.methods._setMintPaused + }; + + if (!pauseMap[actionName]) { + throw `Cannot find pause function for action "${actionName}"`; + } + + let invokation = await invoke(world, comptroller[actionName]([isPaused]), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Comptroller: set paused for ${actionName} to ${isPaused}`, + invokation + ); + + return world; +} + +async function setMaxAssets(world: World, from: string, comptroller: Comptroller, numberOfAssets: NumberV): Promise { + let invokation = await invoke(world, comptroller.methods._setMaxAssets(numberOfAssets.encode()), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Set max assets to ${numberOfAssets.show()}`, + invokation + ); + + return world; +} + +async function setLiquidationIncentive(world: World, from: string, comptroller: Comptroller, liquidationIncentive: NumberV): Promise { + let invokation = await invoke(world, comptroller.methods._setLiquidationIncentive(liquidationIncentive.encode()), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Set liquidation incentive to ${liquidationIncentive.show()}`, + invokation + ); + + return world; +} + +async function supportMarket(world: World, from: string, comptroller: Comptroller, cToken: CToken): Promise { + if (world.dryRun) { + // Skip this specifically on dry runs since it's likely to crash due to a number of reasons + world.printer.printLine(`Dry run: Supporting market \`${cToken._address}\``); + return world; + } + + let invokation = await invoke(world, comptroller.methods._supportMarket(cToken._address), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Supported market ${cToken.name}`, + invokation + ); + + return world; +} + +async function unlistMarket(world: World, from: string, comptroller: Comptroller, cToken: CToken): Promise { + let invokation = await invoke(world, comptroller.methods.unlist(cToken._address), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Unlisted market ${cToken.name}`, + invokation + ); + + return world; +} + +async function enterMarkets(world: World, from: string, comptroller: Comptroller, assets: string[]): Promise { + let invokation = await invoke(world, comptroller.methods.enterMarkets(assets), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Called enter assets ${assets} as ${describeUser(world, from)}`, + invokation + ); + + return world; +} + +async function exitMarket(world: World, from: string, comptroller: Comptroller, asset: string): Promise { + let invokation = await invoke(world, comptroller.methods.exitMarket(asset), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Called exit market ${asset} as ${describeUser(world, from)}`, + invokation + ); + + return world; +} + +async function setPriceOracle(world: World, from: string, comptroller: Comptroller, priceOracleAddr: string): Promise { + let invokation = await invoke(world, comptroller.methods._setPriceOracle(priceOracleAddr), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Set price oracle for to ${priceOracleAddr} as ${describeUser(world, from)}`, + invokation + ); + + return world; +} + +async function setCollateralFactor(world: World, from: string, comptroller: Comptroller, cToken: CToken, collateralFactor: NumberV): Promise { + let invokation = await invoke(world, comptroller.methods._setCollateralFactor(cToken._address, collateralFactor.encode()), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Set collateral factor for ${cToken.name} to ${collateralFactor.show()}`, + invokation + ); + + return world; +} + +async function setCloseFactor(world: World, from: string, comptroller: Comptroller, closeFactor: NumberV): Promise { + let invokation = await invoke(world, comptroller.methods._setCloseFactor(closeFactor.encode()), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Set close factor to ${closeFactor.show()}`, + invokation + ); + + return world; +} + +async function fastForward(world: World, from: string, comptroller: Comptroller, blocks: NumberV): Promise { + let invokation = await invoke(world, comptroller.methods.fastForward(blocks.encode()), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Fast forward ${blocks.show()} blocks to #${invokation.value}`, + invokation + ); + + return world; +} + +async function printLiquidity(world: World, comptroller: Comptroller): Promise { + let enterEvents = await getPastEvents(world, comptroller, 'StdComptroller', 'MarketEntered'); + let addresses = enterEvents.map((event) => event.returnValues['account']); + let uniq = [...new Set(addresses)]; + + world.printer.printLine("Liquidity:") + + const liquidityMap = await Promise.all(uniq.map(async (address) => { + let userLiquidity = await getLiquidity(world, comptroller, address); + + return [address, userLiquidity.val]; + })); + + liquidityMap.forEach(([address, liquidity]) => { + world.printer.printLine(`\t${world.settings.lookupAlias(address)}: ${liquidity / 1e18}e18`) + }); + + return world; +} + +async function setPendingAdmin(world: World, from: string, comptroller: Comptroller, newPendingAdmin: string): Promise { + let invokation = await invoke(world, comptroller.methods._setPendingAdmin(newPendingAdmin), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Comptroller: ${describeUser(world, from)} sets pending admin to ${newPendingAdmin}`, + invokation + ); + + return world; +} + +async function acceptAdmin(world: World, from: string, comptroller: Comptroller): Promise { + let invokation = await invoke(world, comptroller.methods._acceptAdmin(), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Comptroller: ${describeUser(world, from)} accepts admin`, + invokation + ); + + return world; +} + +export function comptrollerCommands() { + return [ + new Command<{comptrollerParams: EventV}>(` + #### Deploy + + * "Comptroller Deploy ...comptrollerParams" - Generates a new Comptroller (not as Impl) + * E.g. "Comptroller Deploy YesNo" + `, + "Deploy", + [new Arg("comptrollerParams", getEventV, {variadic: true})], + (world, from, {comptrollerParams}) => genComptroller(world, from, comptrollerParams.val) + ), + new Command<{comptroller: Comptroller, action: StringV, isPaused: BoolV}>(` + #### SetPaused + + * "Comptroller SetPaused " - Pauses or unpaused given cToken function + * E.g. "Comptroller SetPaused "Mint" True" + `, + "SetPaused", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("action", getStringV), + new Arg("isPaused", getBoolV) + ], + (world, from, {comptroller, action, isPaused}) => setPaused(world, from, comptroller, action.val, isPaused.val) + ), + new Command<{comptroller: Comptroller, cToken: CToken}>(` + #### SupportMarket + + * "Comptroller SupportMarket " - Adds support in the Comptroller for the given cToken + * E.g. "Comptroller SupportMarket cZRX" + `, + "SupportMarket", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cToken", getCTokenV) + ], + (world, from, {comptroller, cToken}) => supportMarket(world, from, comptroller, cToken) + ), + new Command<{comptroller: Comptroller, cToken: CToken}>(` + #### UnList + + * "Comptroller UnList " - Mock unlists a given market in tests + * E.g. "Comptroller UnList cZRX" + `, + "UnList", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cToken", getCTokenV) + ], + (world, from, {comptroller, cToken}) => unlistMarket(world, from, comptroller, cToken) + ), + new Command<{comptroller: Comptroller, cTokens: CToken[]}>(` + #### EnterMarkets + + * "Comptroller EnterMarkets ( ...)" - User enters the given markets + * E.g. "Comptroller EnterMarkets (cZRX cETH)" + `, + "EnterMarkets", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cTokens", getCTokenV, {mapped: true}) + ], + (world, from, {comptroller, cTokens}) => enterMarkets(world, from, comptroller, cTokens.map((c) => c._address)) + ), + new Command<{comptroller: Comptroller, cToken: CToken}>(` + #### ExitMarket + + * "Comptroller ExitMarket " - User exits the given markets + * E.g. "Comptroller ExitMarket cZRX" + `, + "ExitMarket", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cToken", getCTokenV) + ], + (world, from, {comptroller, cToken}) => exitMarket(world, from, comptroller, cToken._address) + ), + new Command<{comptroller: Comptroller, maxAssets: NumberV}>(` + #### SetMaxAssets + + * "Comptroller SetMaxAssets " - Sets (or resets) the max allowed asset count + * E.g. "Comptroller SetMaxAssets 4" + `, + "SetMaxAssets", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("maxAssets", getNumberV) + ], + (world, from, {comptroller, maxAssets}) => setMaxAssets(world, from, comptroller, maxAssets) + ), + new Command<{comptroller: Comptroller, liquidationIncentive: NumberV}>(` + #### LiquidationIncentive + + * "Comptroller LiquidationIncentive " - Sets the liquidation incentive + * E.g. "Comptroller LiquidationIncentive 1.1" + `, + "LiquidationIncentive", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("liquidationIncentive", getExpNumberV) + ], + (world, from, {comptroller, liquidationIncentive}) => setLiquidationIncentive(world, from, comptroller, liquidationIncentive) + ), + new Command<{comptroller: Comptroller, priceOracle: AddressV}>(` + #### SetPriceOracle + + * "Comptroller SetPriceOracle oracle:
" - Sets the price oracle address + * E.g. "Comptroller SetPriceOracle 0x..." + `, + "SetPriceOracle", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("priceOracle", getAddressV) + ], + (world, from, {comptroller, priceOracle}) => setPriceOracle(world, from, comptroller, priceOracle.val) + ), + new Command<{comptroller: Comptroller, cToken: CToken, collateralFactor: NumberV}>(` + #### SetCollateralFactor + + * "Comptroller SetCollateralFactor " - Sets the collateral factor for given cToken to number + * E.g. "Comptroller SetCollateralFactor cZRX 0.1" + `, + "SetCollateralFactor", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cToken", getCTokenV), + new Arg("collateralFactor", getExpNumberV) + ], + (world, from, {comptroller, cToken, collateralFactor}) => setCollateralFactor(world, from, comptroller, cToken, collateralFactor) + ), + new Command<{comptroller: Comptroller, closeFactor: NumberV}>(` + #### SetCloseFactor + + * "Comptroller SetCloseFactor " - Sets the close factor to given percentage + * E.g. "Comptroller SetCloseFactor 0.2" + `, + "SetCloseFactor", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("closeFactor", getPercentV) + ], + (world, from, {comptroller, closeFactor}) => setCloseFactor(world, from, comptroller, closeFactor) + ), + new Command<{comptroller: Comptroller, newPendingAdmin: AddressV}>(` + #### SetPendingAdmin + + * "Comptroller SetPendingAdmin newPendingAdmin:
" - Sets the pending admin for the Comptroller + * E.g. "Comptroller SetPendingAdmin Geoff" + `, + "SetPendingAdmin", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("newPendingAdmin", getAddressV) + ], + (world, from, {comptroller, newPendingAdmin}) => setPendingAdmin(world, from, comptroller, newPendingAdmin.val) + ), + new Command<{comptroller: Comptroller}>(` + #### AcceptAdmin + + * "Comptroller AcceptAdmin" - Accepts admin for the Comptroller + * E.g. "From Geoff (Comptroller AcceptAdmin)" + `, + "AcceptAdmin", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + ], + (world, from, {comptroller}) => acceptAdmin(world, from, comptroller) + ), + new Command<{comptroller: Comptroller, blocks: NumberV, _keyword: StringV}>(` + #### FastForward + + * "FastForward n: Blocks" - Moves the block number forward "n" blocks. Note: in "CTokenScenario" and "ComptrollerScenario" the current block number is mocked (starting at 100000). This is the only way for the protocol to see a higher block number (for accruing interest). + * E.g. "Comptroller FastForward 5 Blocks" - Move block number forward 5 blocks. + `, + "FastForward", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("blocks", getNumberV), + new Arg("_keyword", getStringV) + ], + (world, from, {comptroller, blocks}) => fastForward(world, from, comptroller, blocks) + ), + new View<{comptroller: Comptroller}>(` + #### Liquidity + + * "Comptroller Liquidity" - Prints liquidity of all minters or borrowers + `, + "Liquidity", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + ], + (world, {comptroller}) => printLiquidity(world, comptroller) + ), + new View<{comptroller: Comptroller, input: StringV}>(` + #### Decode + + * "Decode input:" - Prints information about a call to a Comptroller contract + `, + "Decode", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("input", getStringV) + + ], + (world, {comptroller, input}) => decodeCall(world, comptroller, input.val) + ) + ]; +} + +export async function processComptrollerEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Comptroller", comptrollerCommands(), world, event, from); +} diff --git a/scenario/src/Event/ComptrollerImplEvent.ts b/scenario/src/Event/ComptrollerImplEvent.ts new file mode 100644 index 000000000..c7222fd24 --- /dev/null +++ b/scenario/src/Event/ComptrollerImplEvent.ts @@ -0,0 +1,147 @@ +import {Event} from '../Event'; +import {addAction, describeUser, World} from '../World'; +import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; +import {Unitroller} from '../Contract/Unitroller'; +import {invoke} from '../Invokation'; +import { + getAddressV, + getEventV, + getExpNumberV, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + EventV, + NumberV, + StringV +} from '../Value'; +import {Arg, Command, View, processCommandEvent} from '../Command'; +import {buildComptrollerImpl} from '../Builder/ComptrollerImplBuilder'; +import {ComptrollerErrorReporter} from '../ErrorReporter'; +import {getComptrollerImpl, getComptrollerImplData, getUnitroller} from '../ContractLookup'; +import {verify} from '../Verify'; +import {mergeContractABI} from '../Networks'; +import {encodedNumber} from '../Encoding'; + +async function genComptrollerImpl(world: World, from: string, params: Event): Promise { + let {world: nextWorld, comptrollerImpl, comptrollerImplData} = await buildComptrollerImpl(world, from, params); + world = nextWorld; + + world = addAction( + world, + `Added Comptroller Implementation (${comptrollerImplData.description}) at address ${comptrollerImpl._address}`, + comptrollerImplData.invokation + ); + + return world; +}; + +async function become(world: World, from: string, comptrollerImpl: ComptrollerImpl, unitroller: Unitroller, priceOracleAddr: string, closeFactor: encodedNumber, maxAssets: encodedNumber): Promise { + let invokation = await invoke(world, comptrollerImpl.methods._become(unitroller._address, priceOracleAddr, closeFactor, maxAssets, false), from, ComptrollerErrorReporter); + + if (!world.dryRun) { + // Skip this specifically on dry runs since it's likely to crash due to a number of reasons + world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); + } + + world = addAction( + world, + `Become ${unitroller._address}'s Comptroller Impl with priceOracle=${priceOracleAddr},closeFactor=${closeFactor},maxAssets=${maxAssets}`, + invokation + ); + + return world; +} + +async function recome(world: World, from: string, comptrollerImpl: ComptrollerImpl, unitroller: Unitroller): Promise { + let invokation = await invoke(world, comptrollerImpl.methods._become(unitroller._address, "0x0000000000000000000000000000000000000000", 0, 0, true), from, ComptrollerErrorReporter); + + world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); + + world = addAction( + world, + `Recome ${unitroller._address}'s Comptroller Impl`, + invokation + ); + + return world; +} + +async function verifyComptrollerImpl(world: World, comptrollerImpl: ComptrollerImpl, name: string, contract: string, apiKey: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, name, contract, comptrollerImpl._address); + } + + return world; +} + +export function comptrollerImplCommands() { + return [ + new Command<{comptrollerImplParams: EventV}>(` + #### Deploy + + * "ComptrollerImpl Deploy ...comptrollerImplParams" - Generates a new Comptroller Implementation + * E.g. "ComptrollerImpl Deploy MyScen Scenario" + `, + "Deploy", + [new Arg("comptrollerImplParams", getEventV, {variadic: true})], + (world, from, {comptrollerImplParams}) => genComptrollerImpl(world, from, comptrollerImplParams.val) + ), + new View<{comptrollerImplArg: StringV, apiKey: StringV}>(` + #### Verify + + * "ComptrollerImpl Verify apiKey:" - Verifies Comptroller Implemetation in Etherscan + * E.g. "ComptrollerImpl Verify "myApiKey" + `, + "Verify", + [ + new Arg("comptrollerImplArg", getStringV), + new Arg("apiKey", getStringV) + ], + async (world, {comptrollerImplArg, apiKey}) => { + let [comptrollerImpl, name, data] = await getComptrollerImplData(world, comptrollerImplArg.val); + + return await verifyComptrollerImpl(world, comptrollerImpl, name, data.get('contract')!, apiKey.val); + }, + {namePos: 1} + ), + new Command<{unitroller: Unitroller, comptrollerImpl: ComptrollerImpl, priceOracle: AddressV, closeFactor: NumberV, maxAssets: NumberV}>(` + #### Become + + * "ComptrollerImpl Become priceOracle: closeFactor: maxAssets:" - Become the comptroller, if possible. + * E.g. "ComptrollerImpl MyImpl Become + `, + "Become", + [ + new Arg("unitroller", getUnitroller, {implicit: true}), + new Arg("comptrollerImpl", getComptrollerImpl), + new Arg("priceOracle", getAddressV), + new Arg("closeFactor", getExpNumberV), + new Arg("maxAssets", getNumberV) + ], + (world, from, {unitroller, comptrollerImpl, priceOracle, closeFactor, maxAssets}) => become(world, from, comptrollerImpl, unitroller, priceOracle.val, closeFactor.encode(), maxAssets.encode()), + {namePos: 1} + ), + new Command<{unitroller: Unitroller, comptrollerImpl: ComptrollerImpl}>(` + #### Recome + + * "ComptrollerImpl Recome" - Recome the comptroller + * E.g. "ComptrollerImpl MyImpl Recome + `, + "Recome", + [ + new Arg("unitroller", getUnitroller, {implicit: true}), + new Arg("comptrollerImpl", getComptrollerImpl) + ], + (world, from, {unitroller, comptrollerImpl}) => recome(world, from, comptrollerImpl, unitroller), + {namePos: 1} + ) + ]; +} + +export async function processComptrollerImplEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("ComptrollerImpl", comptrollerImplCommands(), world, event, from); +} diff --git a/scenario/src/Event/Erc20Event.ts b/scenario/src/Event/Erc20Event.ts new file mode 100644 index 000000000..0de272c0f --- /dev/null +++ b/scenario/src/Event/Erc20Event.ts @@ -0,0 +1,251 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {Erc20} from '../Contract/Erc20'; +import {invoke} from '../Invokation'; +import {buildErc20} from '../Builder/Erc20Builder'; +import { + getAddressV, + getBoolV, + getEventV, + getNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + BoolV, + EventV, + NumberV, + StringV} from '../Value'; +import {getErc20V} from '../Value/Erc20Value'; +import {verify} from '../Verify'; +import {Arg, Command, View, processCommandEvent} from '../Command'; +import {CTokenErrorReporter} from '../ErrorReporter'; +import {encodedNumber} from '../Encoding'; +import {getErc20Data} from '../ContractLookup'; + +async function genToken(world: World, from: string, params: Event): Promise { + let {world: newWorld, erc20, tokenData} = await buildErc20(world, from, params); + world = newWorld; + + world = addAction( + world, + `Added ERC-20 token ${tokenData.symbol} (${tokenData.description}) at address ${erc20._address}`, + tokenData.invokation + ); + + return world; +} + +async function verifyErc20(world: World, erc20: Erc20, name: string, contract: string, apiKey: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, name, contract, erc20._address); + } + + return world; +} + +async function approve(world: World, from: string, erc20: Erc20, address: string, amount: NumberV): Promise { + let invokation = await invoke(world, erc20.methods.approve(address, amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `Approved ${erc20.name} ERC-20 token for ${from} of ${amount.show()}`, + invokation + ); + + return world; +} + +async function faucet(world: World, from: string, erc20: Erc20, address: string, amount: NumberV): Promise { + let invokation = await invoke(world, erc20.methods.allocateTo(address, amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `Fauceted ${amount.show()} ERC-20 tokens to ${address}`, + invokation + ); + + return world; +} + +async function transfer(world: World, from: string, erc20: Erc20, address: string, amount: NumberV): Promise { + let invokation = await invoke(world, erc20.methods.transfer(address, amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `Transferred ${amount.show()} ERC-20 tokens from ${from} to ${address}`, + invokation + ); + + return world; +} + +async function transferFrom(world: World, from: string, erc20: Erc20, owner: string, spender: string, amount: NumberV): Promise { + let invokation = await invoke(world, erc20.methods.transferFrom(owner, spender, amount.encode()), from, CTokenErrorReporter); + + world = addAction( + world, + `"Transferred from" ${amount.show()} ERC-20 tokens from ${owner} to ${spender}`, + invokation + ); + + return world; +} + +async function setFail(world: World, from: string, erc20: Erc20, fail: boolean): Promise { + let invokation = await invoke(world, erc20.methods.setFail(fail), from, CTokenErrorReporter); + + world = addAction( + world, + `Set fail for ${erc20.name} to ${fail}`, + invokation + ); + + return world; +} + +async function setPaused(world: World, from: string, erc20: Erc20, pause: boolean): Promise { + let method = pause ? erc20.methods.pause() : erc20.methods.unpause(); + let invokation = await invoke(world, method, from); + + world = addAction( + world, + `Set ${erc20.name} ${pause ? 'paused' : 'unpaused'}`, + invokation + ); + + return world; +} + +export function erc20Commands() { + return [ + new Command<{erc20Params: EventV}>(` + #### Deploy + + * "Erc20 Deploy ...erc20Params" - Generates a new ERC-20 token by name + * E.g. "Erc20 ZRX Deploy" + `, + "Deploy", + [new Arg("erc20Params", getEventV, {variadic: true})], + (world, from, {erc20Params}) => genToken(world, from, erc20Params.val) + ), + new View<{erc20Arg: StringV, apiKey: StringV}>(` + #### Verify + + * "Erc20 Verify apiKey:" - Verifies Erc20 in Etherscan + * E.g. "Erc20 ZRX Verify "myApiKey" + `, + "Verify", + [ + new Arg("erc20Arg", getStringV), + new Arg("apiKey", getStringV) + ], + async (world, {erc20Arg, apiKey}) => { + console.log([erc20Arg, apiKey]); + let [erc20, name, data] = await getErc20Data(world, erc20Arg.val); + console.log([erc20, name, data.toJS()]); + + return await verifyErc20(world, erc20, name, data.get('contract')!, apiKey.val); + }, + {namePos: 1} + ), + new Command<{erc20: Erc20, spender: AddressV, amount: NumberV}>(` + #### Approve + + * "Erc20 Approve spender:
" - Adds an allowance between user and address + * E.g. "Erc20 ZRX Approve cZRX 1.0e18" + `, + "Approve", + [ + new Arg("erc20", getErc20V), + new Arg("spender", getAddressV), + new Arg("amount", getNumberV) + ], + (world, from, {erc20, spender, amount}) => approve(world, from, erc20, spender.val, amount), + {namePos: 1} + ), + new Command<{erc20: Erc20, recipient: AddressV, amount: NumberV}>(` + #### Faucet + + * "Erc20 Faucet recipient: " - Adds an arbitrary balance to given user + * E.g. "Erc20 ZRX Faucet Geoff 1.0e18" + `, + "Faucet", + [ + new Arg("erc20", getErc20V), + new Arg("recipient", getAddressV), + new Arg("amount", getNumberV) + ], + (world, from, {erc20, recipient, amount}) => { + return faucet(world, from, erc20, recipient.val, amount) + }, + {namePos: 1} + ), + new Command<{erc20: Erc20, recipient: AddressV, amount: NumberV}>(` + #### Transfer + + * "Erc20 Transfer recipient: " - Transfers a number of tokens via "transfer" as given user to recipient (this does not depend on allowance) + * E.g. "Erc20 ZRX Transfer Torrey 1.0e18" + `, + "Transfer", + [ + new Arg("erc20", getErc20V), + new Arg("recipient", getAddressV), + new Arg("amount", getNumberV) + ], + (world, from, {erc20, recipient, amount}) => transfer(world, from, erc20, recipient.val, amount), + {namePos: 1} + ), + new Command<{erc20: Erc20, owner: AddressV, spender: AddressV, amount: NumberV}>(` + #### TransferFrom + + * "Erc20 TransferFrom owner: spender: " - Transfers a number of tokens via "transfeFrom" to recipient (this depends on allowances) + * E.g. "Erc20 ZRX TransferFrom Geoff Torrey 1.0e18" + `, + "TransferFrom", + [ + new Arg("erc20", getErc20V), + new Arg("owner", getAddressV), + new Arg("spender", getAddressV), + new Arg("amount", getNumberV) + ], + (world, from, {erc20, owner, spender, amount}) => transferFrom(world, from, erc20, owner.val, spender.val, amount), + {namePos: 1} + ), + new Command<{erc20: Erc20, fail: BoolV}>(` + #### SetFail + + * "Erc20 SetFail fail:" - Sets failure on or off for an EvilToken + * E.g. "Erc20 EVL SetFail False" + `, + "SetFail", + [ + new Arg("erc20", getErc20V), + new Arg("fail", getBoolV) + ], + (world, from, {erc20, fail}) => setFail(world, from, erc20, fail.val), + {namePos: 1} + ), + new Command<{erc20: Erc20, paused: BoolV}>(` + #### Pause + + * "Erc20 Pause paused:" - Sets paused on or off for WBTC + * E.g. "Erc20 WBTC Pause" + * E.g. "Erc20 WBTC Pause False" + `, + "Pause", + [ + new Arg("erc20", getErc20V), + new Arg("paused", getBoolV, {default: new BoolV(true)}) + ], + (world, from, {erc20, paused}) => setPaused(world, from, erc20, paused.val), + {namePos: 1} + ) + ]; +} + +export async function processErc20Event(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Erc20", erc20Commands(), world, event, from); +} diff --git a/scenario/src/Event/ExpectationEvent.ts b/scenario/src/Event/ExpectationEvent.ts new file mode 100644 index 000000000..0ee787a5a --- /dev/null +++ b/scenario/src/Event/ExpectationEvent.ts @@ -0,0 +1,68 @@ +import {Event} from '../Event'; +import {addExpectation, World} from '../World'; +import { + EventV, + NumberV, + Value +} from '../Value'; +import { + getCoreValue, + getEventV, + getNumberV +} from '../CoreValue'; +import {Invariant} from '../Invariant'; +import {ChangesExpectation} from '../Expectation/ChangesExpectation'; +import {RemainsExpectation} from '../Expectation/RemainsExpectation'; +import {formatEvent} from '../Formatter'; +import {Arg, View, processCommandEvent} from '../Command'; + +async function changesExpectation(world: World, condition: Event, delta: Value): Promise { + const value = await getCoreValue(world, condition); + const expectation = new ChangesExpectation(condition, value, delta); + + return addExpectation(world, expectation); +} + +async function remainsExpectation(world: World, condition: Event, value: Value): Promise { + const expectation = new RemainsExpectation(condition, value); + + // Immediately check value matches + await expectation.checker(world, true); + + return addExpectation(world, expectation); +} + +export function expectationCommands() { + return [ + new View<{condition: EventV, delta: NumberV}>(` + #### Changes + + * "Changes amount:" - Expects that given value changes by amount + * E.g ."Expect Changes (CToken cZRX UnderlyingBalance Geoff) +10e18" + `, + "Changes", + [ + new Arg("condition", getEventV), + new Arg("delta", getNumberV) + ], + (world, {condition, delta}) => changesExpectation(world, condition.val, delta) + ), + new View<{condition: EventV, value: Value}>(` + #### Remains + + * "Expect Remains " - Ensures that the given condition starts at and remains a given value + * E.g ."Expect Remains (CToken cZRX UnderlyingBalance Geoff) (Exactly 0)" + `, + "Remains", + [ + new Arg("condition", getEventV), + new Arg("value", getCoreValue) + ], + (world, {condition, value}) => remainsExpectation(world, condition.val, value) + ) + ]; +} + +export async function processExpectationEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Expectation", expectationCommands(), world, event, from); +} diff --git a/scenario/src/Event/InterestRateModelEvent.ts b/scenario/src/Event/InterestRateModelEvent.ts new file mode 100644 index 000000000..7276c06f5 --- /dev/null +++ b/scenario/src/Event/InterestRateModelEvent.ts @@ -0,0 +1,84 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {InterestRateModel} from '../Contract/InterestRateModel'; +import {buildInterestRateModel} from '../Builder/InterestRateModelBuilder'; +import {invoke} from '../Invokation'; +import { + getAddressV, + getEventV, + getNumberV, + getStringV, +} from '../CoreValue'; +import { + AddressV, + EventV, + NumberV, + StringV +} from '../Value'; +import {Arg, Command, processCommandEvent, View} from '../Command'; +import {getInterestRateModelData} from '../ContractLookup'; +import {verify} from '../Verify'; + +async function genInterestRateModel(world: World, from: string, params: Event): Promise { + let {world: nextWorld, interestRateModel, interestRateModelData} = await buildInterestRateModel(world, from, params); + world = nextWorld; + + world = addAction( + world, + `Deployed interest rate model (${interestRateModelData.description}) to address ${interestRateModel._address}`, + interestRateModelData.invokation + ); + + return world; +} + +async function verifyInterestRateModel(world: World, interestRateModel: InterestRateModel, apiKey: string, modelName: string, contractName: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, modelName, contractName, interestRateModel._address); + } + + return world; +} + +export function interestRateModelCommands() { + return [ + new Command<{params: EventV}>(` + #### Deploy + + * "Deploy ...params" - Generates a new interest rate model + * E.g. "InterestRateModel Deploy Fixed MyInterestRateModel 0.5" + * E.g. "InterestRateModel Deploy Whitepaper MyInterestRateModel 0.05 0.45" + * E.g. "InterestRateModel Deploy Standard MyInterestRateModel" + `, + "Deploy", + [ + new Arg("params", getEventV, {variadic: true}) + ], + (world, from, {params}) => genInterestRateModel(world, from, params.val) + ), + new View<{interestRateModelArg: StringV, apiKey: StringV}>(` + #### Verify + + * " Verify apiKey:" - Verifies InterestRateModel in Etherscan + * E.g. "InterestRateModel MyInterestRateModel Verify "myApiKey" + `, + "Verify", + [ + new Arg("interestRateModelArg", getStringV), + new Arg("apiKey", getStringV) + ], + async (world, {interestRateModelArg, apiKey}) => { + let [interestRateModel, name, data] = await getInterestRateModelData(world, interestRateModelArg.val); + + return await verifyInterestRateModel(world, interestRateModel, apiKey.val, name, data.get('contract')!) + }, + {namePos: 1} + ) + ]; +} + +export async function processInterestRateModelEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("InterestRateModel", interestRateModelCommands(), world, event, from); +} diff --git a/scenario/src/Event/InvariantEvent.ts b/scenario/src/Event/InvariantEvent.ts new file mode 100644 index 000000000..9a94b9c8c --- /dev/null +++ b/scenario/src/Event/InvariantEvent.ts @@ -0,0 +1,83 @@ +import {Event} from '../Event'; +import {addInvariant, World} from '../World'; +import { + EventV, + Value +} from '../Value'; +import { + getCoreValue, + getEventV, +} from '../CoreValue'; +import {Invariant} from '../Invariant'; +import {StaticInvariant} from '../Invariant/StaticInvariant'; +import {RemainsInvariant} from '../Invariant/RemainsInvariant'; +import {SuccessInvariant} from '../Invariant/SuccessInvariant'; +import {formatEvent} from '../Formatter'; +import {Arg, View, processCommandEvent} from '../Command'; + + +async function staticInvariant(world: World, condition): Promise { + const currentValue = await getCoreValue(world, condition); + const invariant = new StaticInvariant(condition, currentValue); + + return addInvariant(world, invariant); +} + +async function remainsInvariant(world: World, condition: Event, value: Value): Promise { + const invariant = new RemainsInvariant(condition, value); + + // Immediately check value matches + await invariant.checker(world, true); + + return addInvariant(world, invariant); +} + +async function successInvariant(world: World): Promise { + const invariant = new SuccessInvariant(); + + return addInvariant(world, invariant); +} + +export function invariantCommands() { + return [ + new View<{condition: EventV}>(` + #### Static + + * "Static " - Ensures that the given condition retains a consistent value + * E.g ."Invariant Static (CToken cZRX UnderlyingBalance Geoff)" + `, + "Static", + [ + new Arg("condition", getEventV) + ], + (world, {condition}) => staticInvariant(world, condition.val) + ), + new View<{condition: EventV, value: Value}>(` + #### Remains + + * "Invariant Remains " - Ensures that the given condition starts at and remains a given value + * E.g ."Invariant Remains (CToken cZRX UnderlyingBalance Geoff) (Exactly 0)" + `, + "Remains", + [ + new Arg("condition", getEventV), + new Arg("value", getCoreValue) + ], + (world, {condition, value}) => remainsInvariant(world, condition.val, value) + ), + new View<{}>(` + #### Success + + * "Invariant Success" - Ensures that each transaction completes successfully + * E.g ."Invariant Success" + `, + "Success", + [], + (world, {}) => successInvariant(world) + ) + ]; +} + +export async function processInvariantEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Invariant", invariantCommands(), world, event, from); +} diff --git a/scenario/src/Event/MaximillionEvent.ts b/scenario/src/Event/MaximillionEvent.ts new file mode 100644 index 000000000..d8bd318d2 --- /dev/null +++ b/scenario/src/Event/MaximillionEvent.ts @@ -0,0 +1,104 @@ +import {Event} from '../Event'; +import {addAction, describeUser, World} from '../World'; +import {Maximillion} from '../Contract/Maximillion'; +import {invoke} from '../Invokation'; +import { + getAddressV, + getEventV, + getStringV +} from '../CoreValue'; +import { + AddressV, + EventV, + NumberV, + StringV +} from '../Value'; +import {Arg, Command, View, processCommandEvent} from '../Command'; +import {buildMaximillion} from '../Builder/MaximillionBuilder'; +import {getMaximillion} from '../ContractLookup'; +import {verify} from '../Verify'; + +function showTrxValue(world: World): string { + return new NumberV(world.trxInvokationOpts.get('value')).show(); +} + +async function genMaximillion(world: World, from: string, params: Event): Promise { + let {world: nextWorld, maximillion, maximillionData} = await buildMaximillion(world, from, params); + world = nextWorld; + + world = addAction( + world, + `Added Maximillion (${maximillionData.description}) at address ${maximillion._address}`, + maximillionData.invokation + ); + + return world; +} + +async function verifyMaximillion(world: World, maximillion: Maximillion, apiKey: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, "Maximillion", "Maximillion", maximillion._address); + } + + return world; +} + +async function repayBehalf(world: World, from: string, maximillion: Maximillion, behalf: string): Promise { + let showAmount = showTrxValue(world); + let invokation = await invoke(world, maximillion.methods.repayBehalf(behalf), from); + + world = addAction( + world, + `Maximillion: ${describeUser(world, from)} repays ${showAmount} of borrow on behalf of ${describeUser(world, behalf)}`, + invokation + ); + + return world; +} + +export function maximillionCommands() { + return [ + new Command<{maximillionParams: EventV}>(` + #### Deploy + + * "Maximillion Deploy ...maximillionParams" - Generates a new Maximillion + * E.g. "Maximillion Deploy" + `, + "Deploy", + [new Arg("maximillionParams", getEventV, {variadic: true})], + (world, from, {maximillionParams}) => genMaximillion(world, from, maximillionParams.val) + ), + new View<{maximillion: Maximillion, apiKey: StringV}>(` + #### Verify + + * "Maximillion Verify apiKey:" - Verifies Maximillion in Etherscan + * E.g. "Maximillion Verify "myApiKey" + `, + "Verify", + [ + new Arg("maximillion", getMaximillion, {implicit: true}), + new Arg("apiKey", getStringV) + ], + (world, {maximillion, apiKey}) => verifyMaximillion(world, maximillion, apiKey.val) + ), + new Command<{maximillion: Maximillion, behalf: AddressV}>(` + #### RepayBehalf + + * "RepayBehalf behalf:" - Repays up to given value of given user's borrow + * E.g. "(Trx Value 1.0e18 (Maximillion RepayBehalf Geoff))" + `, + "RepayBehalf", + [ + new Arg("maximillion", getMaximillion, {implicit: true}), + new Arg("behalf", getAddressV) + ], + (world, from, {maximillion, behalf}) => repayBehalf(world, from, maximillion, behalf.val) + ) + ]; +} + +export async function processMaximillionEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Maximillion", maximillionCommands(), world, event, from); +} diff --git a/scenario/src/Event/PriceOracleEvent.ts b/scenario/src/Event/PriceOracleEvent.ts new file mode 100644 index 000000000..252d83517 --- /dev/null +++ b/scenario/src/Event/PriceOracleEvent.ts @@ -0,0 +1,120 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {PriceOracle} from '../Contract/PriceOracle'; +import {buildPriceOracle, setPriceOracle} from '../Builder/PriceOracleBuilder'; +import {invoke} from '../Invokation'; +import { + getAddressV, + getEventV, + getExpNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + EventV, + NumberV, + StringV +} from '../Value'; +import {Arg, Command, processCommandEvent, View} from '../Command'; +import {getPriceOracle} from '../ContractLookup'; +import {verify} from '../Verify'; +import {encodedNumber} from '../Encoding'; + +async function genPriceOracle(world: World, from: string, params: Event): Promise { + let {world: nextWorld, priceOracle, priceOracleData} = await buildPriceOracle(world, from, params); + world = nextWorld; + + world = addAction( + world, + `Deployed PriceOracle (${priceOracleData.description}) to address ${priceOracle._address}`, + priceOracleData.invokation! + ); + + return world; +} + +async function setPriceOracleFn(world: World, params: Event): Promise { + let {world: nextWorld, priceOracle, priceOracleData} = await setPriceOracle(world, params); + + return nextWorld; +} + +async function setPrice(world: World, from: string, priceOracle: PriceOracle, cToken: string, amount: NumberV): Promise { + return addAction( + world, + `Set price oracle price for ${cToken} to ${amount.show()}`, + await invoke(world, priceOracle.methods.setUnderlyingPrice(cToken, amount.encode()), from) + ); +} + +async function verifyPriceOracle(world: World, priceOracle: PriceOracle, apiKey: string, contractName: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, "PriceOracle", contractName, priceOracle._address); + } + + return world; +} + +export function priceOracleCommands() { + return [ + new Command<{params: EventV}>(` + #### Deploy + + * "Deploy ...params" - Generates a new price oracle + * E.g. "PriceOracle Deploy Fixed 1.0" + * E.g. "PriceOracle Deploy Simple" + * E.g. "PriceOracle Deploy NotPriceOracle" + `, + "Deploy", + [ + new Arg("params", getEventV, {variadic: true}) + ], + (world, from, {params}) => genPriceOracle(world, from, params.val) + ), + new Command<{params: EventV}>(` + #### Set + + * "Set ...params" - Sets the price oracle to given deployed contract + * E.g. "PriceOracle Set Standard \"0x...\" \"My Already Deployed Oracle\"" + `, + "Set", + [ + new Arg("params", getEventV, {variadic: true}) + ], + (world, from, {params}) => setPriceOracleFn(world, params.val) + ),new Command<{priceOracle: PriceOracle, cToken: AddressV, amount: NumberV}>(` + #### SetPrice + + * "SetPrice " - Sets the per-ether price for the given cToken + * E.g. "PriceOracle SetPrice cZRX 1.0" + `, + "SetPrice", + [ + new Arg("priceOracle", getPriceOracle, {implicit: true}), + new Arg("cToken", getAddressV), + new Arg("amount", getExpNumberV) + ], + (world, from, {priceOracle, cToken, amount}) => setPrice(world, from, priceOracle, cToken.val, amount) + ), + new View<{priceOracle: PriceOracle, apiKey: StringV, contractName: StringV}>(` + #### Verify + + * "Verify apiKey: contractName:=PriceOracle" - Verifies PriceOracle in Etherscan + * E.g. "PriceOracle Verify "myApiKey" + `, + "Verify", + [ + new Arg("priceOracle", getPriceOracle, {implicit: true}), + new Arg("apiKey", getStringV), + new Arg("contractName", getStringV, {default: new StringV("PriceOracle")}) + ], + (world, {priceOracle, apiKey, contractName}) => verifyPriceOracle(world, priceOracle, apiKey.val, contractName.val) + ) + ]; +} + +export async function processPriceOracleEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("PriceOracle", priceOracleCommands(), world, event, from); +} diff --git a/scenario/src/Event/PriceOracleProxyEvent.ts b/scenario/src/Event/PriceOracleProxyEvent.ts new file mode 100644 index 000000000..57a8e3e9d --- /dev/null +++ b/scenario/src/Event/PriceOracleProxyEvent.ts @@ -0,0 +1,81 @@ +import {Event} from '../Event'; +import {addAction, World} from '../World'; +import {PriceOracleProxy} from '../Contract/PriceOracleProxy'; +import {buildPriceOracleProxy} from '../Builder/PriceOracleProxyBuilder'; +import {invoke} from '../Invokation'; +import { + getAddressV, + getEventV, + getExpNumberV, + getStringV +} from '../CoreValue'; +import { + AddressV, + EventV, + NumberV, + StringV +} from '../Value'; +import {Arg, Command, processCommandEvent, View} from '../Command'; +import {getPriceOracleProxy} from '../ContractLookup'; +import {verify} from '../Verify'; +import {encodedNumber} from '../Encoding'; + +async function genPriceOracleProxy(world: World, from: string, params: Event): Promise { + let priceOracleProxy; + let invokation; + + ({world, priceOracleProxy, invokation} = await buildPriceOracleProxy(world, from, params)); + + world = addAction( + world, + `Deployed PriceOracleProxy to address ${priceOracleProxy._address}`, + invokation + ); + + return world; +} + +async function verifyPriceOracleProxy(world: World, priceOracleProxy: PriceOracleProxy, apiKey: string, contractName: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, "PriceOracleProxy", contractName, priceOracleProxy._address); + } + + return world; +} + +export function priceOracleProxyCommands() { + return [ + new Command<{params: EventV}>(` + #### Deploy + + * "Deploy ...params" - Generates a new price oracle proxy + * E.g. "PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (cEther Address)" + `, + "Deploy", + [ + new Arg("params", getEventV, {variadic: true}) + ], + (world, from, {params}) => genPriceOracleProxy(world, from, params.val) + ), + new View<{priceOracleProxy: PriceOracleProxy, apiKey: StringV, contractName: StringV}>(` + #### Verify + + * "Verify apiKey: contractName:=PriceOracleProxy" - Verifies PriceOracleProxy in Etherscan + * E.g. "PriceOracleProxy Verify "myApiKey" + `, + "Verify", + [ + new Arg("priceOracleProxy", getPriceOracleProxy, {implicit: true}), + new Arg("apiKey", getStringV), + new Arg("contractName", getStringV, {default: new StringV("PriceOracleProxy")}) + ], + (world, {priceOracleProxy, apiKey, contractName}) => verifyPriceOracleProxy(world, priceOracleProxy, apiKey.val, contractName.val) + ) + ]; +} + +export async function processPriceOracleProxyEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("PriceOracleProxy", priceOracleProxyCommands(), world, event, from); +} diff --git a/scenario/src/Event/TrxEvent.ts b/scenario/src/Event/TrxEvent.ts new file mode 100644 index 000000000..b559129b9 --- /dev/null +++ b/scenario/src/Event/TrxEvent.ts @@ -0,0 +1,56 @@ +import {World} from '../World'; +import {Event} from '../Event'; +import {processCoreEvent} from '../CoreEvent'; +import { + EventV, + NumberV +} from '../Value'; +import { + getEventV, + getNumberV +} from '../CoreValue'; +import {Arg, Command, processCommandEvent} from '../Command'; +import {encodedNumber} from '../Encoding'; + +async function setTrxValue(world: World, value: encodedNumber): Promise { + return world.update('trxInvokationOpts', (t) => t.set('value', value)); +} + +async function setTrxGasPrice(world: World, gasPrice: encodedNumber): Promise { + return world.update('trxInvokationOpts', (t) => t.set('gasPrice', gasPrice.toString())); +} + +export function trxCommands() { + return [ + new Command<{amount: NumberV, event: EventV}>(` + #### Value + + * "Value " - Runs event with a set amount for any transactions + * E.g. "Value 1.0e18 (CToken cEth Mint 1.0e18)" + `, + "Value", + [ + new Arg("amount", getNumberV), + new Arg("event", getEventV) + ], + async (world, from, {amount, event}) => processCoreEvent(await setTrxValue(world, amount.encode()), event.val, from) + ), + new Command<{gasPrice: NumberV, event: EventV}>(` + #### GasPrice + + * "GasPrice " - Runs event with a given gas price + * E.g. "GasPrice 0 (CToken cEth Mint 1.0e18)" + `, + "GasPrice", + [ + new Arg("gasPrice", getNumberV), + new Arg("event", getEventV) + ], + async (world, from, {gasPrice, event}) => processCoreEvent(await setTrxGasPrice(world, gasPrice.encode()), event.val, from) + ) + ]; +} + +export async function processTrxEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Trx", trxCommands(), world, event, from); +} diff --git a/scenario/src/Event/UnitrollerEvent.ts b/scenario/src/Event/UnitrollerEvent.ts new file mode 100644 index 000000000..ed963832f --- /dev/null +++ b/scenario/src/Event/UnitrollerEvent.ts @@ -0,0 +1,98 @@ +import {Event} from '../Event'; +import {addAction, describeUser, World} from '../World'; +import {Unitroller} from '../Contract/Unitroller'; +import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; +import {invoke} from '../Invokation'; +import { + getEventV, + getStringV +} from '../CoreValue'; +import { + EventV, + StringV +} from '../Value'; +import {Arg, Command, View, processCommandEvent} from '../Command'; +import {ComptrollerErrorReporter} from '../ErrorReporter'; +import {buildUnitroller} from '../Builder/UnitrollerBuilder'; +import {getComptrollerImpl, getUnitroller} from '../ContractLookup'; +import {verify} from '../Verify'; + +async function genUnitroller(world: World, from: string, params: Event): Promise { + let {world: nextWorld, unitroller, unitrollerData} = await buildUnitroller(world, from, params); + world = nextWorld; + + world = addAction( + world, + `Added Unitroller (${unitrollerData.description}) at address ${unitroller._address}`, + unitrollerData.invokation + ); + + return world; +} + +async function verifyUnitroller(world: World, unitroller: Unitroller, apiKey: string): Promise { + if (world.isLocalNetwork()) { + world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); + } else { + await verify(world, apiKey, "Unitroller", "Unitroller", unitroller._address); + } + + return world; +} + +async function setPendingImpl(world: World, from: string, unitroller: Unitroller, comptrollerImpl: ComptrollerImpl): Promise { + let invokation = await invoke(world, unitroller.methods._setPendingImplementation(comptrollerImpl._address), from, ComptrollerErrorReporter); + + world = addAction( + world, + `Set pending comptroller impl to ${comptrollerImpl.name}`, + invokation + ); + + return world; +} + +export function unitrollerCommands() { + return [ + new Command<{unitrollerParams: EventV}>(` + #### Deploy + + * "Unitroller Deploy ...unitrollerParams" - Generates a new Unitroller + * E.g. "Unitroller Deploy" + `, + "Deploy", + [new Arg("unitrollerParams", getEventV, {variadic: true})], + (world, from, {unitrollerParams}) => genUnitroller(world, from, unitrollerParams.val) + ), + new View<{unitroller: Unitroller, apiKey: StringV}>(` + #### Verify + + * "Unitroller Verify apiKey:" - Verifies Unitroller in Etherscan + * E.g. "Unitroller Verify "myApiKey" + `, + "Verify", + [ + new Arg("unitroller", getUnitroller, {implicit: true}), + new Arg("apiKey", getStringV) + ], + (world, {unitroller, apiKey}) => verifyUnitroller(world, unitroller, apiKey.val) + ), + new Command<{unitroller: Unitroller, comptrollerImpl: ComptrollerImpl}>(` + #### SetPendingImpl + + * "SetPendingImpl impl:" - Sets the pending comptroller implementation for this unitroller + * E.g. "Unitroller SetPendingImpl MyScenImpl" - Sets the current comptroller implementation to MyScenImpl + `, + "SetPendingImpl", + [ + new Arg("unitroller", getUnitroller, {implicit: true}), + new Arg("comptrollerImpl", getComptrollerImpl) + ], + (world, from, {unitroller, comptrollerImpl}) => setPendingImpl(world, from, unitroller, comptrollerImpl) + ) + ]; +} + +export async function processUnitrollerEvent(world: World, event: Event, from: string | null): Promise { + return await processCommandEvent("Unitroller", unitrollerCommands(), world, event, from); +} diff --git a/scenario/src/Expectation.ts b/scenario/src/Expectation.ts new file mode 100644 index 000000000..7823f87fd --- /dev/null +++ b/scenario/src/Expectation.ts @@ -0,0 +1,4 @@ + +export interface Expectation { + checker: (world: any) => Promise; +} diff --git a/scenario/src/Expectation/ChangesExpectation.ts b/scenario/src/Expectation/ChangesExpectation.ts new file mode 100644 index 000000000..3cc182c47 --- /dev/null +++ b/scenario/src/Expectation/ChangesExpectation.ts @@ -0,0 +1,47 @@ +import {Expectation} from '../Expectation'; +import {fail, World} from '../World'; +import {getCoreValue} from '../CoreValue'; +import {Value, NumberV} from '../Value'; +import {Event} from '../Event'; +import {formatEvent} from '../Formatter'; +import {BigNumber} from 'bignumber.js'; + +function asNumberV(v: Value): NumberV { + if (v instanceof NumberV) { + return v; + } else { + throw new Error(`Expected NumberV for ChangesExpectation, got ${v.toString()}`); + } +} + +export class ChangesExpectation implements Expectation { + condition: Event; + originalValue: NumberV; + delta: NumberV; + expected: NumberV; + + constructor(condition: Event, originalValue: Value, delta: Value) { + this.condition = condition; + this.originalValue = asNumberV(originalValue); + this.delta = asNumberV(delta); + this.expected = this.originalValue.add(this.delta); + } + + async getCurrentValue(world: World): Promise { + return await getCoreValue(world, this.condition); + }; + + async checker(world: World, initialCheck: boolean=false): Promise { + const currentValue = asNumberV(await this.getCurrentValue(world)); + + if (!currentValue.compareTo(world, this.expected)) { + const trueDelta = currentValue.sub(this.originalValue); + + fail(world, `${this.toString()} instead had value \`${currentValue.toString()}\` (true delta: ${trueDelta.toString()})`); + } + } + + toString() { + return `ChangesExpectation: condition=${formatEvent(this.condition)}, originalValue=${this.originalValue.toString()}, delta=${this.delta.toString()}, expected=${this.expected.toString()}`; + } +} diff --git a/scenario/src/Expectation/RemainsExpectation.ts b/scenario/src/Expectation/RemainsExpectation.ts new file mode 100644 index 000000000..9506cc473 --- /dev/null +++ b/scenario/src/Expectation/RemainsExpectation.ts @@ -0,0 +1,32 @@ +import {Expectation} from '../Expectation'; +import {fail, World} from '../World'; +import {getCoreValue} from '../CoreValue'; +import {Value} from '../Value'; +import {Event} from '../Event'; +import {formatEvent} from '../Formatter'; + +export class RemainsExpectation implements Expectation { + condition: Event; + value: Value; + + constructor(condition: Event, value: Value) { + this.condition = condition; + this.value = value; + } + + async getCurrentValue(world: World): Promise { + return await getCoreValue(world, this.condition); + }; + + async checker(world: World, initialCheck: boolean=false): Promise { + const currentValue = await this.getCurrentValue(world); + + if (!this.value.compareTo(world, currentValue)) { + fail(world, `${this.toString()} failed as value ${initialCheck ? 'started as' : 'became'} \`${currentValue.toString()}\``); + } + } + + toString() { + return `RemainsExpectation: condition=${formatEvent(this.condition)}, value=${this.value.toString()}`; + } +} diff --git a/scenario/src/File.ts b/scenario/src/File.ts new file mode 100644 index 000000000..84df15318 --- /dev/null +++ b/scenario/src/File.ts @@ -0,0 +1,32 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export function getNetworkPath(basePath: string | null, network: string, name: string, extension: string | null='json'): string { + if (!basePath) { + throw new Error(`Cannot read file when missing base path`); + } + + return path.join(basePath, 'networks', `${network}${name}${extension ? `.${extension}` : ''}`); +} + +export async function readFile(file: string, def: T, fn: (data: string) => T): Promise { + return new Promise((resolve, reject) => { + fs.access(file, fs.constants.F_OK, (err) => { + if (err) { + resolve(def); + } else { + fs.readFile(file, 'utf8', (err, data) => { + return err ? reject(err) : resolve(fn(data)); + }); + } + }); + }); +} + +export async function writeFile(file: string, data: string): Promise { + return new Promise((resolve, reject) => { + fs.writeFile(file, data, (err) => { + return err ? reject(err) : resolve(); + }); + }); +} diff --git a/scenario/src/Formatter.ts b/scenario/src/Formatter.ts new file mode 100644 index 000000000..55e2d4806 --- /dev/null +++ b/scenario/src/Formatter.ts @@ -0,0 +1,25 @@ +import {Event} from './Event'; + +// Effectively the opposite of parse +export function formatEvent(event: Event, outter=true): string { + if (Array.isArray(event)) { + if (event.length === 2 && typeof event[0] === "string" && (event[0]).toLowerCase() === "exactly") { + return event[1].toString(); + } + + let mapped = event.map(e => formatEvent(e, false)); + let joined = mapped.join(' '); + + if (outter) { + return joined; + } else { + return `(${joined})`; + } + } else { + return event; + } +} + +export function formatError(err: any) { + return JSON.stringify(err); // yeah... for now +} diff --git a/scenario/src/Help.ts b/scenario/src/Help.ts new file mode 100644 index 000000000..c67d53170 --- /dev/null +++ b/scenario/src/Help.ts @@ -0,0 +1,64 @@ +import {Event} from './Event'; +import {Expression} from './Command'; +import {mustString} from './Utils'; +import {Printer} from './Printer'; + +export function printHelp(printer: Printer, event: Event, expressions: Expression[], path: string[]=[]) { + if (event.length === 0) { + let banner; + + if (path.length === 0) { + banner = ( +` +## Compound Command Runner + +The Compound Command Runner makes it easy to interact with Compound. You can input simple commands +and it will construct Web3 calls to pull data or generate transactions. A list of available commands +is included below. To dig further into a command run \`Help \`, such as \`Help From\` or for +sub-commands run \`Help CToken\` or \`Help CToken Mint\`. +`).trim(); + } else { + if (expressions.length > 0) { + banner = `### ${path.join(" ")} Sub-Commands`; + } + } + + if (!!banner) { + printer.printMarkdown(banner); + } + + expressions.forEach((expression) => { + printer.printMarkdown(`\n${expression.doc}`); + if (expression.subExpressions.length > 0) { + printer.printMarkdown(`For more information, run: \`Help ${path} ${expression.name}\``); + } + }); + } else { + const [first, ...rest] = event; + const expressionName = mustString(first); + + let expression = expressions.find((expression) => expression.name.toLowerCase() === expressionName.toLowerCase()); + + if (expression) { + if (rest.length === 0) { + printer.printMarkdown(`${expression.doc}`); + } + + printHelp(printer, rest, expression.subExpressions, path.concat(expression.name)); + } else { + let matchingExpressions = expressions.filter((expression) => expression.name.toLowerCase().startsWith(expressionName.toLowerCase())); + + if (matchingExpressions.length === 0) { + printer.printLine(`\nError: cannot find help docs for ${path.concat(first).join(" ")}`); + } else { + if (rest.length === 0) { + matchingExpressions.forEach((expression) => { + printer.printMarkdown(`${expression.doc}`); + }); + } else { + printer.printLine(`\nError: cannot find help docs for ${path.concat(event).join(" ")}`); + } + } + } + } +} diff --git a/scenario/src/HistoricReadline.ts b/scenario/src/HistoricReadline.ts new file mode 100644 index 000000000..ef9bd3dd7 --- /dev/null +++ b/scenario/src/HistoricReadline.ts @@ -0,0 +1,35 @@ +import * as readline from 'readline'; +import * as fs from 'fs'; +import {readFile} from './File'; + +let readlineAny = readline; + +export async function createInterface(options): Promise { + let history: string[] = await readFile(options['path'], [], (x) => x.split("\n")); + let cleanHistory = history.filter((x) => !!x).reverse(); + + readlineAny.kHistorySize = Math.max(readlineAny.kHistorySize, options['maxLength']); + + let rl = readline.createInterface(options); + let rlAny = rl; + + let oldAddHistory = rlAny._addHistory; + + rlAny._addHistory = function() { + let last = rlAny.history[0]; + let line = oldAddHistory.call(rl); + + // TODO: Should this be sync? + if (line.length > 0 && line != last) { + fs.appendFileSync(options['path'], `${line}\n`); + } + + // TODO: Truncate file? + + return line; + } + + rlAny.history.push.apply(rlAny.history, cleanHistory); + + return rl; +} diff --git a/scenario/src/Invariant.ts b/scenario/src/Invariant.ts new file mode 100644 index 000000000..fc5211c0a --- /dev/null +++ b/scenario/src/Invariant.ts @@ -0,0 +1,5 @@ + +export interface Invariant { + held: boolean + checker: (world: any) => Promise; +} diff --git a/scenario/src/Invariant/RemainsInvariant.ts b/scenario/src/Invariant/RemainsInvariant.ts new file mode 100644 index 000000000..b98a4c635 --- /dev/null +++ b/scenario/src/Invariant/RemainsInvariant.ts @@ -0,0 +1,33 @@ +import {Invariant} from '../Invariant'; +import {fail, World} from '../World'; +import {getCoreValue} from '../CoreValue'; +import {Value} from '../Value'; +import {Event} from '../Event'; +import {formatEvent} from '../Formatter'; + +export class RemainsInvariant implements Invariant { + condition: Event; + value: Value; + held = false; + + constructor(condition: Event, value: Value) { + this.condition = condition; + this.value = value; + } + + async getCurrentValue(world: World): Promise { + return await getCoreValue(world, this.condition); + }; + + async checker(world: World, initialCheck: boolean=false): Promise { + const currentValue = await this.getCurrentValue(world); + + if (!this.value.compareTo(world, currentValue)) { + fail(world, `Static invariant broken! Expected ${this.toString()} to remain static value \`${this.value}\` but ${initialCheck ? 'started as' : 'became'} \`${currentValue}\``); + } + } + + toString() { + return `RemainsInvariant: condition=${formatEvent(this.condition)}, value=${this.value.toString()}`; + } +} diff --git a/scenario/src/Invariant/StaticInvariant.ts b/scenario/src/Invariant/StaticInvariant.ts new file mode 100644 index 000000000..7a464c310 --- /dev/null +++ b/scenario/src/Invariant/StaticInvariant.ts @@ -0,0 +1,33 @@ +import {Invariant} from '../Invariant'; +import {fail, World} from '../World'; +import {getCoreValue} from '../CoreValue'; +import {Value} from '../Value'; +import {Event} from '../Event'; +import {formatEvent} from '../Formatter'; + +export class StaticInvariant implements Invariant { + condition: Event; + value: Value; + held = false; + + constructor(condition: Event, value: Value) { + this.condition = condition; + this.value = value; + } + + async getCurrentValue(world: World): Promise { + return await getCoreValue(world, this.condition); + }; + + async checker(world: World): Promise { + const currentValue = await this.getCurrentValue(world); + + if (!this.value.compareTo(world, currentValue)) { + fail(world, `Static invariant broken! Expected ${this.toString()} to remain static value \`${this.value}\` but became \`${currentValue}\``); + } + } + + toString() { + return `StaticInvariant: condition=${formatEvent(this.condition)}, value=${this.value.toString()}`; + } +} diff --git a/scenario/src/Invariant/SuccessInvariant.ts b/scenario/src/Invariant/SuccessInvariant.ts new file mode 100644 index 000000000..9abd2b49e --- /dev/null +++ b/scenario/src/Invariant/SuccessInvariant.ts @@ -0,0 +1,21 @@ +import {Invariant} from '../Invariant'; +import {fail, World} from '../World'; +import {getCoreValue} from '../CoreValue'; +import {Value} from '../Value'; +import {Event} from '../Event'; + +export class SuccessInvariant implements Invariant { + held = false; + + constructor() {} + + async checker(world: World): Promise { + if (world.lastInvokation && !world.lastInvokation.success()) { + fail(world, `Success invariant broken! Expected successful execution, but had error ${world.lastInvokation.toString()}`); + } + } + + toString() { + return `SuccessInvariant`; + } +} diff --git a/scenario/src/Invokation.ts b/scenario/src/Invokation.ts new file mode 100644 index 000000000..450e796e2 --- /dev/null +++ b/scenario/src/Invokation.ts @@ -0,0 +1,274 @@ +import {ErrorReporter, NoErrorReporter, ComptrollerErrorReporter} from './ErrorReporter'; +import {mustArray} from './Utils'; +import {World} from './World'; +import {encodedNumber} from './Encoding'; + +const errorRegex = /^(.*) \((\d+)\)$/ + +function getErrorCode(revertMessage: string): [string, number] | null { + let res = errorRegex.exec(revertMessage); + + if (res) { + return [res[1], Number(res[2])]; + } else { + return null; + } +} + +export interface InvokationOpts { + from?: string, + gas?: number, + gasPrice?: number +} + +export class InvokationError extends Error { + err : Error + // function : string + // arguments : {[]} + + constructor(err: Error) { + super(err.message); + this.err = err; + } + + toString() { + return `InvokationError`; + } +} + +export class InvokationRevertFailure extends InvokationError { + errCode: number + error : string | null + errMessage : string + + constructor(err: Error, errMessage: string, errCode: number, error: string | null) { + super(err); + + this.errMessage = errMessage; + this.errCode = errCode; + this.error = error; + } + + toString() { + return `InvokationRevertError`; + } +} + +interface Argument { + name: string + type: string +} + +interface Method { + name: string + inputs: Argument[] +} + +export interface Callable { + estimateGas: (InvokationOpts?) => Promise + call: (InvokationOpts?) => Promise + _method: Method + arguments: any[] +} + +export interface Sendable extends Callable { + send: (InvokationOpts) => Promise +} + +export interface Receipt { + // TODO: Add more transaction details + blockNumber: number + transactionHash: string + gasUsed: number + + events: {[event: string]: {returnValues: {[key: string]: any}}} +} + +export class Failure { + error: string + info: string + detail: string + + constructor(error: string, info: string, detail: string) { + this.error = error; + this.info = info; + this.detail = detail; + } + + toString(): string { + return `Failure`; + } + + equals(other: Failure): boolean { + return ( + this.error === other.error && + this.info === other.info && + this.detail === other.detail + ); + } +} + +export class Invokation { + value: T | null + receipt: Receipt | null + error: Error | null + failures: Failure[] + method: string | null + args: {arg: string, val: any}[] + errorReporter: ErrorReporter + + constructor(value: T | null, receipt: Receipt | null, error: Error | null, fn: Callable | null, errorReporter: ErrorReporter=NoErrorReporter) { + this.value = value; + this.receipt = receipt; + this.error = error; + this.errorReporter = errorReporter; + + if (fn !== null) { + this.method = fn._method.name; + this.args = fn.arguments.map((argument, i) => ({arg: fn._method.inputs[i].name, val: argument})); + } else { + this.method = null; + this.args = []; + } + + if (receipt !== null && receipt.events["Failure"]) { + const failures = mustArray(receipt.events["Failure"]); + + this.failures = failures.map((failure) => { + const {'error': errorVal, 'info': infoVal, 'detail': detailVal} = failure.returnValues; + + return new Failure( + errorReporter.getError(errorVal) || `unknown error=${errorVal}`, + errorReporter.getInfo(infoVal) || `unknown info=${infoVal}`, + errorReporter.getDetail(errorVal, detailVal) + ); + }); + } else { + this.failures = []; + } + } + + success(): boolean { + return ( + this.error === null && this.failures.length === 0 + ); + } + + invokation(): string { + if (this.method) { + let argStr = this.args.map(({arg, val}) => `${arg}=${val.toString()}`).join(','); + return `"${this.method}(${argStr})"`; + } else { + return `unknown method`; + } + } + + toString(): string { + return `Invokation<${this.invokation()}, tx=${this.receipt ? this.receipt.transactionHash : ''}, value=${this.value ? this.value.toString() : ''}, error=${this.error}, failures=${this.failures.toString()}>`; + } +} + +export async function fallback(world: World, from: string, to: string, value: encodedNumber): Promise> { + let trxObj = { + from: from, + to: to, + value: value + }; + + let estimateGas = async (opts: InvokationOpts) => { + let trxObjMerged = { + ...trxObj, + ...opts + }; + + return await world.web3.eth.estimateGas(trxObjMerged); + }; + + let call = async (opts: InvokationOpts) => { + let trxObjMerged = { + ...trxObj, + ...opts + }; + + return await world.web3.eth.call(trxObjMerged); + }; + + let send = async (opts: InvokationOpts) => { + let trxObjMerged = { + ...trxObj, + ...opts + }; + + let receipt = await world.web3.eth.sendTransaction(trxObjMerged); + receipt.events = {}; + + return receipt; + } + + let fn: Sendable = { + estimateGas: estimateGas, + call: call, + send: send, + _method: { + name: "fallback", + inputs: [] + }, + arguments: [] + } + + return invoke(world, fn, from, NoErrorReporter); +} + +export async function invoke(world: World, fn: Sendable, from: string, errorReporter: ErrorReporter=NoErrorReporter): Promise> { + let value: T | null = null; + let result: Receipt | null = null; + let worldInvokationOpts = world.getInvokationOpts({from: from}); + let trxInvokationOpts = world.trxInvokationOpts.toJS(); + + let invokationOpts = { + ...worldInvokationOpts, + ...trxInvokationOpts + }; + + try{ + const gas = await fn.estimateGas({...invokationOpts}); + invokationOpts = { + ...invokationOpts, + gas: gas * 2 + }; + + let error: null | Error = null; + + try { + value = await fn.call({...invokationOpts}); + } catch (err) { + error = new InvokationError(err); + } + + if (world.dryRun) { + world.printer.printLine(`Dry run: invoking \`${fn._method.name}\``); + result = { + blockNumber: -1, + transactionHash: "0x", + gasUsed: 0, + events: {} + }; + } else { + result = await fn.send({...invokationOpts}); + } + + return new Invokation(value, result, null, fn, errorReporter); + } catch (err) { + if (errorReporter) { + let decoded = getErrorCode(err.message); + + if (decoded) { + let [errMessage, errCode] = decoded; + + return new Invokation(value, result, new InvokationRevertFailure(err, errMessage, errCode, errorReporter.getError(errCode)), fn, errorReporter); + } + } + + return new Invokation(value, result, new InvokationError(err), fn, errorReporter); + } +} diff --git a/scenario/src/Macro.ts b/scenario/src/Macro.ts new file mode 100644 index 000000000..a0a686733 --- /dev/null +++ b/scenario/src/Macro.ts @@ -0,0 +1,98 @@ +import {Event} from './Event'; + +interface Arg { + arg: any + def: any + splat: any +} + +interface Macro { + args: Arg[] + steps: Event +} + +type ArgMap = {[arg: string]: Event}; +type NamedArg = { argName: string, argValue: Event }; +type ArgValue = Event | NamedArg; + +export type Macros = {[eventName: string]: Macro}; + +export function expandEvent(macros: Macros, event: Event): Event[] { + const [eventName, ...eventArgs] = event; + + if (macros[eventName]) { + let expanded = expandMacro(macros[eventName], eventArgs); + + // Recursively expand steps + return expanded.map(event => expandEvent(macros, event)).flat(); + } else { + return [event]; + } +} + +function getArgValues(eventArgs: ArgValue[], macroArgs: Arg[]): ArgMap { + const eventArgNameMap: ArgMap = {}; + const eventArgIndexed: Event[] = []; + const argValues: ArgMap = {}; + let usedNamedArg: boolean = false; + let usedSplat: boolean = false; + + eventArgs.forEach((eventArg) => { + if (eventArg.hasOwnProperty('argName')) { + const {argName, argValue} = eventArg; + + eventArgNameMap[argName] = argValue; + usedNamedArg = true; + } else { + if (usedNamedArg) { + throw new Error("Cannot use positional arg after named arg in macro invokation."); + } + + eventArgIndexed.push(eventArg); + } + }); + + macroArgs.forEach(({arg, def, splat}, argIndex) => { + let val; + + if (usedSplat) { + throw new Error("Cannot have arg after splat arg"); + } + + if (eventArgNameMap[arg] !== undefined) { + val = eventArgNameMap[arg]; + } else if (splat) { + val = eventArgIndexed.slice(argIndex); + usedSplat = true; + } else if (eventArgIndexed[argIndex] !== undefined) { + val = eventArgIndexed[argIndex]; + } else if (def !== undefined) { + val = def; + } else { + throw new Error("Macro cannot find arg value for " + arg); + } + argValues[arg] = val; + }); + + return argValues; +} + +export function expandMacro(macro: Macro, event: Event): Event[] { + const argValues = getArgValues(event, macro.args); + + function expandStep(step) { + return step.map((token) => { + if (argValues[token] !== undefined) { + return argValues[token]; + } else { + if (Array.isArray(token)) { + return expandStep(token); + } else { + return token; + } + } + }); + }; + + return macro.steps.map(expandStep); +} diff --git a/scenario/src/Networks.ts b/scenario/src/Networks.ts new file mode 100644 index 000000000..b5456fca6 --- /dev/null +++ b/scenario/src/Networks.ts @@ -0,0 +1,140 @@ +import {fromJS, Map} from 'immutable'; +import {World} from './World'; +import {Invokation} from './Invokation'; +import {ABI, Contract, setContractName} from './Contract'; +import {getNetworkPath, readFile, writeFile} from './File'; + +type Networks = Map; + +interface ExtraData { + index: string[] + data: object | string | number +} + +export function parseNetworkFile(data: string | object): Networks { + return fromJS(typeof data === "string" ? JSON.parse(data) : data); +} + +function serializeNetworkFile(networks: Networks): string { + return JSON.stringify(networks.toJSON(), null, 4); +} + +function readNetworkFile(world: World, isABI: boolean): Promise { + return readFile(getNetworkPath(world.basePath, world.network, isABI ? '-abi' : ''), Map({}), parseNetworkFile); +} + +function writeNetworkFile(world: World, networks: Networks, isABI: boolean): Promise { + return writeFile(getNetworkPath(world.basePath, world.network, isABI ? '-abi' : ''), serializeNetworkFile(networks)); +} + +export function storeContract(world: World, contract: Contract, name: string, extraData: ExtraData[]): World { + contract = setContractName(name, contract); + + world = world.set('lastContract', contract); + world = world.setIn(['contractIndex', contract._address.toLowerCase()], contract); + + world = world.update('contractData', (contractData) => { + return extraData.reduce((acc, {index, data}) => { + if (typeof data !== 'string' && typeof data !== 'number') { + // Store extra data as an immutable + data = Map(data); + } + + return acc.setIn(index, data); + }, contractData); + }); + + return world; +} + +export async function saveContract(world: World, contract: Contract, name: string, extraData: ExtraData[]): Promise { + let networks = await readNetworkFile(world, false); + let networksABI = await readNetworkFile(world, true); + + networks = extraData.reduce((acc, {index, data}) => acc.setIn(index, data), networks); + networksABI = networksABI.set(name, contract._jsonInterface); + + // Don't write during a dry-run + if (!world.dryRun) { + await writeNetworkFile(world, networks, false); + await writeNetworkFile(world, networksABI, true); + } +} + +// Merges a contract into another, which is important for delegation +export async function mergeContractABI(world: World, targetName: string, contractTarget: Contract, a: string, b: string): Promise { + let networks = await readNetworkFile(world, false); + let networksABI = await readNetworkFile(world, true); + let aABI = networksABI.get(a); + let bABI = networksABI.get(b); + + if (!aABI) { + throw new Error(`Missing contract ABI for ${a}`); + } + + if (!bABI) { + throw new Error(`Missing contract ABI for ${b}`); + } + + const fullABI = aABI.toJS().concat(bABI.toJS()); + + // Store Comptroller address + networks = networks.setIn(['Contracts', targetName], contractTarget._address); + world = world.setIn(['contractData', 'Contracts', targetName], contractTarget._address); + + networksABI = networksABI.set(targetName, fullABI); + + let mergedContract = new world.web3.eth.Contract(fullABI, contractTarget._address, {}); + + world = world.setIn(['contractIndex', contractTarget._address.toLowerCase()], setContractName(targetName, mergedContract)); + + // Don't write during a dry-run + if (!world.dryRun) { + await writeNetworkFile(world, networks, false); + await writeNetworkFile(world, networksABI, true); + } + + return world; +} + +export async function loadContracts(world: World): Promise<[World, string[]]> { + let networks = await readNetworkFile(world, false); + let networksABI = await readNetworkFile(world, true); + + return loadContractData(world, networks, networksABI); +} + +export async function loadContractData(world: World, networks: Networks, networksABI: Networks): Promise<[World, string[]]> { + // Pull off contracts value and the rest is "extra" + let contractInfo: string[] = []; + let contracts = networks.get('Contracts') || Map({}); + + world = contracts.reduce((world: World, address: string, name: string) => { + let abi: ABI[] = networksABI.has(name) ? networksABI.get(name).toJS() : []; + let contract = new world.web3.eth.Contract(abi, address, {}); + + contractInfo.push(`${name}: ${address}`); + + // Store the contract + return world.setIn(['contractIndex', contract._address.toLowerCase()], setContractName(name, contract)); + }, world); + + world = world.update('contractData', (contractData) => contractData.mergeDeep(networks)); + + return [world, contractInfo]; +} + +export async function storeAndSaveContract(world: World, contract: Contract, name: string, invokation: Invokation | null, extraData: ExtraData[]): Promise { + extraData.push({index: ['Contracts', name], data: contract._address}); + if (contract.constructorAbi) { + extraData.push({index: ['Constructors', name], data: contract.constructorAbi}); + } + if (invokation && invokation.receipt) { + extraData.push({index: ['Blocks', name], data: invokation.receipt.blockNumber}); + } + + world = storeContract(world, contract, name, extraData); + await saveContract(world, contract, name, extraData); + + return world; +} diff --git a/scenario/src/Parser.ts b/scenario/src/Parser.ts new file mode 100644 index 000000000..928c0c976 --- /dev/null +++ b/scenario/src/Parser.ts @@ -0,0 +1,3210 @@ +// tslint:disable:only-arrow-functions +// tslint:disable:object-literal-shorthand +// tslint:disable:trailing-comma +// tslint:disable:object-literal-sort-keys +// tslint:disable:one-variable-per-declaration +// tslint:disable:max-line-length +// tslint:disable:no-consecutive-blank-lines +// tslint:disable:align + + +// Generated by PEG.js v. 0.10.0 (ts-pegjs plugin v. 0.2.2 ) +// +// https://pegjs.org/ https://github.com/metadevpro/ts-pegjs + +"use strict"; + +export interface IFilePosition { + offset: number; + line: number; + column: number; +} + +export interface IFileRange { + start: IFilePosition; + end: IFilePosition; +} + +export interface ILiteralExpectation { + type: "literal"; + text: string; + ignoreCase: boolean; +} + +export interface IClassParts extends Array {} + +export interface IClassExpectation { + type: "class"; + parts: IClassParts; + inverted: boolean; + ignoreCase: boolean; +} + +export interface IAnyExpectation { + type: "any"; +} + +export interface IEndExpectation { + type: "end"; +} + +export interface IOtherExpectation { + type: "other"; + description: string; +} + +export type Expectation = ILiteralExpectation | IClassExpectation | IAnyExpectation | IEndExpectation | IOtherExpectation; + +export class SyntaxError extends Error { + public static buildMessage(expected: Expectation[], found: string | null) { + function hex(ch: string): string { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s: string): string { + return s + .replace(/\\/g, "\\\\") + .replace(/"/g, "\\\"") + .replace(/\0/g, "\\0") + .replace(/\t/g, "\\t") + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/[\x00-\x0F]/g, (ch) => "\\x0" + hex(ch) ) + .replace(/[\x10-\x1F\x7F-\x9F]/g, (ch) => "\\x" + hex(ch) ); + } + + function classEscape(s: string): string { + return s + .replace(/\\/g, "\\\\") + .replace(/\]/g, "\\]") + .replace(/\^/g, "\\^") + .replace(/-/g, "\\-") + .replace(/\0/g, "\\0") + .replace(/\t/g, "\\t") + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/[\x00-\x0F]/g, (ch) => "\\x0" + hex(ch) ) + .replace(/[\x10-\x1F\x7F-\x9F]/g, (ch) => "\\x" + hex(ch) ); + } + + function describeExpectation(expectation: Expectation) { + switch (expectation.type) { + case "literal": + return "\"" + literalEscape(expectation.text) + "\""; + case "class": + const escapedParts = expectation.parts.map((part) => { + return Array.isArray(part) + ? classEscape(part[0] as string) + "-" + classEscape(part[1] as string) + : classEscape(part); + }); + + return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; + case "any": + return "any character"; + case "end": + return "end of input"; + case "other": + return expectation.description; + } + } + + function describeExpected(expected1: Expectation[]) { + const descriptions = expected1.map(describeExpectation); + let i; + let j; + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found1: string | null) { + return found1 ? "\"" + literalEscape(found1) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; + } + + public message: string; + public expected: Expectation[]; + public found: string | null; + public location: IFileRange; + public name: string; + + constructor(message: string, expected: Expectation[], found: string | null, location: IFileRange) { + super(); + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof (Error as any).captureStackTrace === "function") { + (Error as any).captureStackTrace(this, SyntaxError); + } + } +} + +export interface ICached { + nextPos: number; + result: any; +} + +function peg$parse(input: string, options?: IParseOptions) { + options = options !== undefined ? options : {}; + + const peg$FAILED = {}; + + const peg$startRuleFunctions: {[id: string]: any} = { tests: peg$parsetests, step: peg$parsestep, macros: peg$parsemacros }; + let peg$startRuleFunction: () => any = peg$parsetests; + + const peg$c0 = function(head: any, t: any) { return t; }; + const peg$c1 = function(head: any, tail: any) { return tail.reduce((acc, el) => addTopLevelEl(acc, el), addTopLevelEl({macros: {}, tests: {}}, head)); }; + const peg$c2 = function(values: any) { return values !== null ? values.tests : {}; }; + const peg$c3 = function(values: any) { return values !== null ? values.macros : {}; }; + const peg$c4 = "Test"; + const peg$c5 = peg$literalExpectation("Test", false); + const peg$c6 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: steps}; }; + const peg$c7 = "GasTest"; + const peg$c8 = peg$literalExpectation("GasTest", false); + const peg$c9 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Gas"].concat(steps)}; }; + const peg$c10 = "Pending"; + const peg$c11 = peg$literalExpectation("Pending", false); + const peg$c12 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Pending"].concat(steps)}; }; + const peg$c13 = "Only"; + const peg$c14 = peg$literalExpectation("Only", false); + const peg$c15 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Only"].concat(steps)}; }; + const peg$c16 = "Skip"; + const peg$c17 = peg$literalExpectation("Skip", false); + const peg$c18 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Skip"].concat(steps)}; }; + const peg$c19 = "Macro"; + const peg$c20 = peg$literalExpectation("Macro", false); + const peg$c21 = function(name: any, args: any, steps: any) { return {type: 'macro', name: getString(name), args: args || [], steps: steps}; }; + const peg$c22 = function(head: any, tail: any) { return [head].concat(tail).filter((x) => !!x); }; + const peg$c23 = function(args: any) { return args !== null ? args.flat() : []; }; + const peg$c24 = "..."; + const peg$c25 = peg$literalExpectation("...", false); + const peg$c26 = "="; + const peg$c27 = peg$literalExpectation("=", false); + const peg$c28 = function(splat: any, arg: any, t: any) { return t; }; + const peg$c29 = function(splat: any, arg: any, def: any) { return { arg, def, splat }; }; + const peg$c30 = function(tokens: any) { return tokens !== null ? tokens.flat() : []; }; + const peg$c31 = function(head: any, step: any) { return step; }; + const peg$c32 = function(steps: any) { return steps !== null ? steps : []; }; + const peg$c33 = function(step: any) { return step; }; + const peg$c34 = function() { return null; }; + const peg$c35 = function(val: any) { return val; }; + const peg$c36 = function(head: any, value: any) { return value }; + const peg$c37 = function(head: any, tail: any) { return [head].concat(tail.flat(1)); }; + const peg$c38 = function(inner: any) { return [inner]; }; + const peg$c39 = function(inner: any) { return [["List"].concat((inner || []).flat())] }; + const peg$c40 = "--"; + const peg$c41 = peg$literalExpectation("--", false); + const peg$c42 = /^[^\n]/; + const peg$c43 = peg$classExpectation(["\n"], true, false); + const peg$c44 = "#"; + const peg$c45 = peg$literalExpectation("#", false); + const peg$c46 = ":"; + const peg$c47 = peg$literalExpectation(":", false); + const peg$c48 = function(token1: any, token2: any) { return {argName: token1, argValue: token2} }; + const peg$c49 = /^[A-Za-z0-9_]/; + const peg$c50 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_"], false, false); + const peg$c51 = function(t: any) { return t.join("") }; + const peg$c52 = "0x"; + const peg$c53 = peg$literalExpectation("0x", false); + const peg$c54 = /^[0-9a-fA-F]/; + const peg$c55 = peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false); + const peg$c56 = function(hex: any) { return ["Hex", hex.flat().flat().join("")] }; + const peg$c57 = "-"; + const peg$c58 = peg$literalExpectation("-", false); + const peg$c59 = "+"; + const peg$c60 = peg$literalExpectation("+", false); + const peg$c61 = /^[0-9]/; + const peg$c62 = peg$classExpectation([["0", "9"]], false, false); + const peg$c63 = "."; + const peg$c64 = peg$literalExpectation(".", false); + const peg$c65 = "e"; + const peg$c66 = peg$literalExpectation("e", false); + const peg$c67 = function(n: any) { return ["Exactly", n.flat().flat().join("")] }; + const peg$c68 = function(head: any, tail: any) { return [head].concat(tail.flat()); }; + const peg$c69 = "("; + const peg$c70 = peg$literalExpectation("(", false); + const peg$c71 = ")"; + const peg$c72 = peg$literalExpectation(")", false); + const peg$c73 = "["; + const peg$c74 = peg$literalExpectation("[", false); + const peg$c75 = "]"; + const peg$c76 = peg$literalExpectation("]", false); + const peg$c77 = "\r"; + const peg$c78 = peg$literalExpectation("\r", false); + const peg$c79 = "\n"; + const peg$c80 = peg$literalExpectation("\n", false); + const peg$c81 = "\t"; + const peg$c82 = peg$literalExpectation("\t", false); + const peg$c83 = " "; + const peg$c84 = peg$literalExpectation(" ", false); + const peg$c85 = "\\"; + const peg$c86 = peg$literalExpectation("\\", false); + const peg$c87 = peg$otherExpectation("whitespace"); + const peg$c88 = /^[ \t]/; + const peg$c89 = peg$classExpectation([" ", "\t"], false, false); + const peg$c90 = /^[ \t\r\n]/; + const peg$c91 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); + const peg$c92 = peg$otherExpectation("string"); + const peg$c93 = function(chars: any) { return ["String", chars.join("")]; }; + const peg$c94 = "\""; + const peg$c95 = peg$literalExpectation("\"", false); + const peg$c96 = "/"; + const peg$c97 = peg$literalExpectation("/", false); + const peg$c98 = "b"; + const peg$c99 = peg$literalExpectation("b", false); + const peg$c100 = function() { return "\b"; }; + const peg$c101 = "f"; + const peg$c102 = peg$literalExpectation("f", false); + const peg$c103 = function() { return "\f"; }; + const peg$c104 = "n"; + const peg$c105 = peg$literalExpectation("n", false); + const peg$c106 = function() { return "\n"; }; + const peg$c107 = "r"; + const peg$c108 = peg$literalExpectation("r", false); + const peg$c109 = function() { return "\r"; }; + const peg$c110 = "t"; + const peg$c111 = peg$literalExpectation("t", false); + const peg$c112 = function() { return "\t"; }; + const peg$c113 = "u"; + const peg$c114 = peg$literalExpectation("u", false); + const peg$c115 = function(digits: any) { + return String.fromCharCode(parseInt(digits, 16)); + }; + const peg$c116 = function(sequence: any) { return sequence; }; + const peg$c117 = /^[^\0-\x1F"\\]/; + const peg$c118 = peg$classExpectation([["\0", "\x1F"], "\"", "\\"], true, false); + const peg$c119 = /^[0-9a-f]/i; + const peg$c120 = peg$classExpectation([["0", "9"], ["a", "f"]], false, true); + + let peg$currPos = 0; + let peg$savedPos = 0; + const peg$posDetailsCache = [{ line: 1, column: 1 }]; + let peg$maxFailPos = 0; + let peg$maxFailExpected: any[] = []; + let peg$silentFails = 0; + + const peg$resultsCache: {[id: number]: ICached} = {}; + + let peg$result; + + if (options.startRule !== undefined) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text(): string { + return input.substring(peg$savedPos, peg$currPos); + } + + function location(): IFileRange { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description: string, location1?: IFileRange) { + location1 = location1 !== undefined + ? location1 + : peg$computeLocation(peg$savedPos, peg$currPos); + + throw peg$buildStructuredError( + [peg$otherExpectation(description)], + input.substring(peg$savedPos, peg$currPos), + location1 + ); + } + + function error(message: string, location1?: IFileRange) { + location1 = location1 !== undefined + ? location1 + : peg$computeLocation(peg$savedPos, peg$currPos); + + throw peg$buildSimpleError(message, location1); + } + + function peg$literalExpectation(text1: string, ignoreCase: boolean): ILiteralExpectation { + return { type: "literal", text: text1, ignoreCase: ignoreCase }; + } + + function peg$classExpectation(parts: IClassParts, inverted: boolean, ignoreCase: boolean): IClassExpectation { + return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; + } + + function peg$anyExpectation(): IAnyExpectation { + return { type: "any" }; + } + + function peg$endExpectation(): IEndExpectation { + return { type: "end" }; + } + + function peg$otherExpectation(description: string): IOtherExpectation { + return { type: "other", description: description }; + } + + function peg$computePosDetails(pos: number) { + let details = peg$posDetailsCache[pos]; + let p; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + + return details; + } + } + + function peg$computeLocation(startPos: number, endPos: number): IFileRange { + const startPosDetails = peg$computePosDetails(startPos); + const endPosDetails = peg$computePosDetails(endPos); + + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + function peg$fail(expected1: Expectation) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected1); + } + + function peg$buildSimpleError(message: string, location1: IFileRange) { + return new SyntaxError(message, [], "", location1); + } + + function peg$buildStructuredError(expected1: Expectation[], found: string | null, location1: IFileRange) { + return new SyntaxError( + SyntaxError.buildMessage(expected1, found), + expected1, + found, + location1 + ); + } + + function peg$parsetests(): any { + let s0, s1, s2, s3, s4, s5, s6; + + const key = peg$currPos * 38 + 0; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsetop_level_el(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + s5 = peg$parseline_separator(); + if (s5 !== peg$FAILED) { + s6 = peg$parsetop_level_el(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + s5 = peg$parseline_separator(); + if (s5 !== peg$FAILED) { + s6 = peg$parsetop_level_el(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s1; + s2 = peg$c1(s2, s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsefull_ws(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c2(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsemacros(): any { + let s0, s1, s2, s3, s4, s5, s6; + + const key = peg$currPos * 38 + 1; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsetop_level_el(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + s5 = peg$parseline_separator(); + if (s5 !== peg$FAILED) { + s6 = peg$parsetop_level_el(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + s5 = peg$parseline_separator(); + if (s5 !== peg$FAILED) { + s6 = peg$parsetop_level_el(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s1; + s2 = peg$c1(s2, s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsefull_ws(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c3(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsetop_level_el(): any { + let s0; + + const key = peg$currPos * 38 + 2; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$parsetest(); + if (s0 === peg$FAILED) { + s0 = peg$parsemacro(); + if (s0 === peg$FAILED) { + s0 = peg$parsegastest(); + if (s0 === peg$FAILED) { + s0 = peg$parsepending(); + if (s0 === peg$FAILED) { + s0 = peg$parseonly(); + if (s0 === peg$FAILED) { + s0 = peg$parseskip(); + } + } + } + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsetest(): any { + let s0, s1, s2, s3, s4, s5, s6, s7; + + const key = peg$currPos * 38 + 3; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsefull_ws(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c4) { + s2 = peg$c4; + peg$currPos += 4; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c5); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s4 = peg$parsestring(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseline_separator(); + if (s6 !== peg$FAILED) { + s7 = peg$parsesteps(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c6(s4, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsegastest(): any { + let s0, s1, s2, s3, s4, s5, s6, s7; + + const key = peg$currPos * 38 + 4; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsefull_ws(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 7) === peg$c7) { + s2 = peg$c7; + peg$currPos += 7; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c8); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s4 = peg$parsestring(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseline_separator(); + if (s6 !== peg$FAILED) { + s7 = peg$parsesteps(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c9(s4, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsepending(): any { + let s0, s1, s2, s3, s4, s5, s6, s7; + + const key = peg$currPos * 38 + 5; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsefull_ws(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 7) === peg$c10) { + s2 = peg$c10; + peg$currPos += 7; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c11); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s4 = peg$parsestring(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseline_separator(); + if (s6 !== peg$FAILED) { + s7 = peg$parsesteps(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c12(s4, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseonly(): any { + let s0, s1, s2, s3, s4, s5, s6, s7; + + const key = peg$currPos * 38 + 6; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsefull_ws(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c13) { + s2 = peg$c13; + peg$currPos += 4; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c14); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s4 = peg$parsestring(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseline_separator(); + if (s6 !== peg$FAILED) { + s7 = peg$parsesteps(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(s4, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseskip(): any { + let s0, s1, s2, s3, s4, s5, s6, s7; + + const key = peg$currPos * 38 + 7; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsefull_ws(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c16) { + s2 = peg$c16; + peg$currPos += 4; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c17); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s4 = peg$parsestring(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseline_separator(); + if (s6 !== peg$FAILED) { + s7 = peg$parsesteps(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c18(s4, s7); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsemacro(): any { + let s0, s1, s2, s3, s4, s5, s6, s7, s8; + + const key = peg$currPos * 38 + 8; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsefull_ws(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 5) === peg$c19) { + s2 = peg$c19; + peg$currPos += 5; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c20); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s4 = peg$parsetoken(); + if (s4 !== peg$FAILED) { + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseargs(); + if (s6 === peg$FAILED) { + s6 = null; + } + if (s6 !== peg$FAILED) { + s7 = peg$parseline_separator(); + if (s7 !== peg$FAILED) { + s8 = peg$parsesteps(); + if (s8 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c21(s4, s6, s8); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseargs(): any { + let s0, s1, s2, s3, s4, s5, s6; + + const key = peg$currPos * 38 + 9; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsearg(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseargs(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parseargs(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s1; + s2 = peg$c22(s2, s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c23(s1); + } + s0 = s1; + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsearg(): any { + let s0, s1, s2, s3, s4, s5, s6, s7; + + const key = peg$currPos * 38 + 10; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c24) { + s1 = peg$c24; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c25); } + } + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsetoken(); + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + s4 = peg$parsews(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s5 = peg$c26; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c27); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parsetoken(); + if (s6 !== peg$FAILED) { + s7 = peg$parsews(); + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c28(s1, s2, s6); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c29(s1, s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsetoken_set(): any { + let s0, s1, s2, s3, s4, s5, s6; + + const key = peg$currPos * 38 + 11; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsetoken(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parsetoken_set(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + s5 = peg$parsews(); + if (s5 !== peg$FAILED) { + s6 = peg$parsetoken_set(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c0(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s1; + s2 = peg$c22(s2, s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c30(s1); + } + s0 = s1; + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsesteps(): any { + let s0, s1, s2, s3, s4, s5, s6; + + const key = peg$currPos * 38 + 12; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parsefull_expr(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + s5 = peg$parseline_separator(); + if (s5 !== peg$FAILED) { + s6 = peg$parsefull_expr(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c31(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + s5 = peg$parseline_separator(); + if (s5 !== peg$FAILED) { + s6 = peg$parsefull_expr(); + if (s6 !== peg$FAILED) { + peg$savedPos = s4; + s5 = peg$c31(s2, s6); + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s1; + s2 = peg$c22(s2, s3); + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c32(s1); + } + s0 = s1; + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsefull_expr(): any { + let s0, s1, s2; + + const key = peg$currPos * 38 + 13; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsetab_separator(); + if (s1 !== peg$FAILED) { + s2 = peg$parsestep(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c33(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsecomment(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsetab_separator(); + if (s1 !== peg$FAILED) { + s2 = peg$parsews(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsestep(): any { + let s0, s1, s2; + + const key = peg$currPos * 38 + 14; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parseexpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parsecomment(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c35(s1); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsecomment(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsetab_separator(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parsews(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseexpr(): any { + let s0, s1, s2, s3, s4, s5, s6; + + const key = peg$currPos * 38 + 15; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsetoken(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parsews(); + if (s4 !== peg$FAILED) { + s5 = peg$parsecontinuation(); + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + s6 = peg$parseexpr(); + if (s6 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c36(s1, s6); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parsews(); + if (s4 !== peg$FAILED) { + s5 = peg$parsecontinuation(); + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + s6 = peg$parseexpr(); + if (s6 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c36(s1, s6); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c37(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsebegin_compound(); + if (s1 !== peg$FAILED) { + s2 = peg$parseexpr(); + if (s2 !== peg$FAILED) { + s3 = peg$parseend_compound(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c38(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsebegin_list(); + if (s1 !== peg$FAILED) { + s2 = peg$parselist_inner(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseend_list(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c39(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsecomment(): any { + let s0, s1, s2, s3, s4; + + const key = peg$currPos * 38 + 16; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsews(); + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c40) { + s2 = peg$c40; + peg$currPos += 2; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c41); } + } + if (s2 !== peg$FAILED) { + s3 = []; + if (peg$c42.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + while (s4 !== peg$FAILED) { + s3.push(s4); + if (peg$c42.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsews(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 35) { + s2 = peg$c44; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c45); } + } + if (s2 !== peg$FAILED) { + s3 = []; + if (peg$c42.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + while (s4 !== peg$FAILED) { + s3.push(s4); + if (peg$c42.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c43); } + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsetoken(): any { + let s0, s1, s2, s3; + + const key = peg$currPos * 38 + 17; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsesimple_token(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 58) { + s2 = peg$c46; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c47); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsesimple_token(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c48(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parsesimple_token(); + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsesimple_token(): any { + let s0, s1, s2; + + const key = peg$currPos * 38 + 18; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$parsehex(); + if (s0 === peg$FAILED) { + s0 = peg$parsenumber(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = []; + if (peg$c49.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + if (peg$c49.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c51(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$parsestring(); + } + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsehex(): any { + let s0, s1, s2, s3, s4; + + const key = peg$currPos * 38 + 19; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c52) { + s2 = peg$c52; + peg$currPos += 2; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c53); } + } + if (s2 !== peg$FAILED) { + s3 = []; + if (peg$c54.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c55); } + } + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + if (peg$c54.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c55); } + } + } + } else { + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s2 = [s2, s3]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c56(s1); + } + s0 = s1; + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsenumber(): any { + let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + const key = peg$currPos * 38 + 20; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 45) { + s2 = peg$c57; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c58); } + } + if (s2 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 43) { + s2 = peg$c59; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c60); } + } + } + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + s3 = []; + if (peg$c61.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + if (s4 !== peg$FAILED) { + while (s4 !== peg$FAILED) { + s3.push(s4); + if (peg$c61.test(input.charAt(peg$currPos))) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + } + } else { + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s4 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s5 = peg$c63; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c64); } + } + if (s5 !== peg$FAILED) { + s6 = []; + if (peg$c61.test(input.charAt(peg$currPos))) { + s7 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + if (s7 !== peg$FAILED) { + while (s7 !== peg$FAILED) { + s6.push(s7); + if (peg$c61.test(input.charAt(peg$currPos))) { + s7 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + } + } else { + s6 = peg$FAILED; + } + if (s6 !== peg$FAILED) { + s5 = [s5, s6]; + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 101) { + s6 = peg$c65; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c66); } + } + if (s6 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s7 = peg$c57; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c58); } + } + if (s7 === peg$FAILED) { + s7 = null; + } + if (s7 !== peg$FAILED) { + s8 = []; + if (peg$c61.test(input.charAt(peg$currPos))) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + if (s9 !== peg$FAILED) { + while (s9 !== peg$FAILED) { + s8.push(s9); + if (peg$c61.test(input.charAt(peg$currPos))) { + s9 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + } + } else { + s8 = peg$FAILED; + } + if (s8 !== peg$FAILED) { + s6 = [s6, s7, s8]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 === peg$FAILED) { + s5 = null; + } + if (s5 !== peg$FAILED) { + s2 = [s2, s3, s4, s5]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c67(s1); + } + s0 = s1; + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parselist_inner(): any { + let s0, s1, s2, s3, s4, s5; + + const key = peg$currPos * 38 + 21; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parseexpr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parsews(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + s5 = peg$parselist_inner(); + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c36(s1, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parsews(); + if (s4 === peg$FAILED) { + s4 = null; + } + if (s4 !== peg$FAILED) { + s5 = peg$parselist_inner(); + if (s5 !== peg$FAILED) { + peg$savedPos = s3; + s4 = peg$c36(s1, s5); + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c68(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsebegin_compound(): any { + let s0, s1, s2, s3; + + const key = peg$currPos * 38 + 22; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsews(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 40) { + s2 = peg$c69; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c70); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s1 = [s1, s2, s3]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseend_compound(): any { + let s0, s1, s2, s3; + + const key = peg$currPos * 38 + 23; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsews(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s2 = peg$c71; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c72); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s1 = [s1, s2, s3]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsebegin_list(): any { + let s0, s1, s2, s3; + + const key = peg$currPos * 38 + 24; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsews(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 91) { + s2 = peg$c73; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c74); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s1 = [s1, s2, s3]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseend_list(): any { + let s0, s1, s2, s3; + + const key = peg$currPos * 38 + 25; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsews(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 93) { + s2 = peg$c75; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c76); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + s1 = [s1, s2, s3]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseline_separator(): any { + let s0, s1, s2; + + const key = peg$currPos * 38 + 26; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 13) { + s1 = peg$c77; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 10) { + s2 = peg$c79; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c80); } + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsetab_separator(): any { + let s0; + + const key = peg$currPos * 38 + 27; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + if (input.charCodeAt(peg$currPos) === 9) { + s0 = peg$c81; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c83) { + s0 = peg$c83; + peg$currPos += 4; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c84); } + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsecontinuation(): any { + let s0, s1, s2, s3, s4; + + const key = peg$currPos * 38 + 28; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c85; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c86); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseline_separator(); + if (s2 !== peg$FAILED) { + s3 = peg$parsetab_separator(); + if (s3 !== peg$FAILED) { + s4 = peg$parsetab_separator(); + if (s4 !== peg$FAILED) { + s1 = [s1, s2, s3, s4]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsews(): any { + let s0, s1; + + const key = peg$currPos * 38 + 29; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + peg$silentFails++; + s0 = []; + if (peg$c88.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c89); } + } + while (s1 !== peg$FAILED) { + s0.push(s1); + if (peg$c88.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c89); } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsefull_ws(): any { + let s0, s1, s2; + + const key = peg$currPos * 38 + 30; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$currPos; + s1 = peg$parsecomment(); + if (s1 !== peg$FAILED) { + s2 = peg$parsefull_ws(); + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (peg$c90.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c91); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsefull_ws(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsestring(): any { + let s0, s1, s2, s3; + + const key = peg$currPos * 38 + 31; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsequotation_mark(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsechar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsechar(); + } + if (s2 !== peg$FAILED) { + s3 = peg$parsequotation_mark(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c93(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c92); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsechar(): any { + let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + const key = peg$currPos * 38 + 32; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + s0 = peg$parseunescaped(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseescape(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s2 = peg$c94; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c95); } + } + if (s2 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 92) { + s2 = peg$c85; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c86); } + } + if (s2 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 47) { + s2 = peg$c96; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c97); } + } + if (s2 === peg$FAILED) { + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 98) { + s3 = peg$c98; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c99); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c100(); + } + s2 = s3; + if (s2 === peg$FAILED) { + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 102) { + s3 = peg$c101; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c102); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c103(); + } + s2 = s3; + if (s2 === peg$FAILED) { + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 110) { + s3 = peg$c104; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c105); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c106(); + } + s2 = s3; + if (s2 === peg$FAILED) { + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 114) { + s3 = peg$c107; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c108); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c109(); + } + s2 = s3; + if (s2 === peg$FAILED) { + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 116) { + s3 = peg$c110; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c111); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c112(); + } + s2 = s3; + if (s2 === peg$FAILED) { + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 117) { + s3 = peg$c113; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c114); } + } + if (s3 !== peg$FAILED) { + s4 = peg$currPos; + s5 = peg$currPos; + s6 = peg$parseHEXDIG(); + if (s6 !== peg$FAILED) { + s7 = peg$parseHEXDIG(); + if (s7 !== peg$FAILED) { + s8 = peg$parseHEXDIG(); + if (s8 !== peg$FAILED) { + s9 = peg$parseHEXDIG(); + if (s9 !== peg$FAILED) { + s6 = [s6, s7, s8, s9]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s4 = input.substring(s4, peg$currPos); + } else { + s4 = s5; + } + if (s4 !== peg$FAILED) { + peg$savedPos = s2; + s3 = peg$c115(s4); + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } + } + } + } + } + } + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c116(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseescape(): any { + let s0; + + const key = peg$currPos * 38 + 33; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + if (input.charCodeAt(peg$currPos) === 92) { + s0 = peg$c85; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c86); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parsequotation_mark(): any { + let s0; + + const key = peg$currPos * 38 + 34; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + if (input.charCodeAt(peg$currPos) === 34) { + s0 = peg$c94; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c95); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseunescaped(): any { + let s0; + + const key = peg$currPos * 38 + 35; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + if (peg$c117.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c118); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseDIGIT(): any { + let s0; + + const key = peg$currPos * 38 + 36; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + if (peg$c61.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + function peg$parseHEXDIG(): any { + let s0; + + const key = peg$currPos * 38 + 37; + const cached: ICached = peg$resultsCache[key]; + + if (cached) { + peg$currPos = cached.nextPos; + + return cached.result; + } + + if (peg$c119.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c120); } + } + + peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; + + return s0; + } + + + if (!Array.prototype.flat) { + Object.defineProperty(Array.prototype, 'flat', { + configurable: true, + value: function flat (x) { + var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); + + return depth ? Array.prototype.reduce.call(this, function (acc, cur) { + if (Array.isArray(cur)) { + acc.push.apply(acc, flat.call(cur, depth - 1)); + } else { + acc.push(cur); + } + + return acc; + }, []) : Array.prototype.slice.call(this); + }, + writable: true + }); + } + + function getString(str) { + let val; + if (Array.isArray(str)) { + if (str.length !== 2 || str[0] !== 'String') { + throw new Error(`Expected string, got ${str}`); + } + + val = str[1]; + } else { + val = str; + } + + if (typeof val !== 'string') { + throw new Error(`Expected string, got ${val} (${typeof val})`); + } + + return val; + } + + function expandEvent(macros, step) { + const [eventName, ...eventArgs] = step; + + if (macros[eventName]) { + let expanded = expandMacro(macros[eventName], eventArgs); + + // Recursively expand steps + return expanded.map(event => expandEvent(macros, event)).flat(); + } else { + return [step]; + } + } + + function getArgValues(eventArgs, macroArgs) { + const eventArgNameMap = {}; + const eventArgIndexed = new Array(); + const argValues = {}; + let usedNamedArg = false; + let usedSplat = false; + + eventArgs.forEach((eventArg) => { + if (eventArg.argName) { + const {argName, argValue} = eventArg; + + eventArgNameMap[argName] = argValue; + usedNamedArg = true; + } else { + if (usedNamedArg) { + throw new Error(`Cannot use positional arg after named arg in macro invokation ${JSON.stringify(eventArgs)} looking at ${eventArg.toString()}`); + } + + eventArgIndexed.push(eventArg); + } + }); + + macroArgs.forEach(({arg, def, splat}, argIndex) => { + if (usedSplat) { + throw new Error("Cannot have arg after splat arg"); + } + + let val; + if (eventArgNameMap[arg] !== undefined) { + val = eventArgNameMap[arg]; + } else if (splat) { + val = eventArgIndexed.slice(argIndex); // Clear out any remaining args + usedSplat = true; + } else if (eventArgIndexed[argIndex] !== undefined) { + val = eventArgIndexed[argIndex]; + } else if (def !== undefined) { + val = def; + } else { + throw new Error("Macro cannot find arg value for " + arg); + } + argValues[arg] = val; + }); + + return argValues; + } + + function expandMacro(macro, eventArgs) { + const argValues = getArgValues(eventArgs, macro.args); + + function expandStep(step) { + return step.map((token) => { + if (argValues[token] !== undefined) { + return argValues[token]; + } else { + if (Array.isArray(token)) { + return expandStep(token); + } else { + return token; + } + } + }); + }; + + return macro.steps.map(expandStep); + } + + function addTopLevelEl(state, el) { + const macros = state.macros; + const tests = state.tests; + const pending = state.pending; + + switch (el.type) { + case 'macro': + const macro = {[el.name]: {args: el.args, steps: el.steps}}; + + return { + tests: tests, + macros: ({...macros, ...macro}) + }; + case 'test': + const steps = el.steps; + const expandedSteps = steps.map((step) => { + return expandEvent(macros, step) + }).flat(); + + const test = {[el.test]: expandedSteps}; + + return { + tests: {...tests, ...test}, + macros: macros + } + } + } + + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError( + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } +} + +export interface IParseOptions { + filename?: string; + startRule?: string; + tracer?: any; + [key: string]: any; +} +export type ParseFunction = (input: string, options?: IParseOptions) => any; +export const parse: ParseFunction = peg$parse; + diff --git a/scenario/src/Printer.ts b/scenario/src/Printer.ts new file mode 100644 index 000000000..478bbfc69 --- /dev/null +++ b/scenario/src/Printer.ts @@ -0,0 +1,120 @@ +import {Value} from './Value'; +import {Action} from './Action'; +import {EventProcessingError} from './CoreEvent' +import {formatEvent} from './Formatter'; + +import * as readline from 'readline'; + +export interface Printer { + printLine(str: string): void + printMarkdown(str: string): void + printValue(val: Value): void + printError(err: Error): void + printAction(action: Action): void +} + +export class CallbackPrinter implements Printer { + callback: (message: any, format: object) => void + + constructor(callback: (message: string) => void) { + this.callback = callback; + } + + printLine(str: string): void { + this.callback(str, {}); + } + + printMarkdown(str: string): void { + this.callback(str, {markdown: true}); + } + + printValue(val: Value): void { + this.callback(val.toString(), {value: true}); + } + + printError(err: Error): void { + if (process.env['verbose']) { + this.callback(err, {error: true}); + } + + this.callback(`Error: ${err.toString()}`, {error: true}); + } + + printAction(action: Action): void { + // Do nothing + } +} + +export class ConsolePrinter implements Printer { + verbose: boolean + + constructor(verbose: boolean) { + this.verbose = verbose; + } + + printLine(str: string): void { + console.log(str); + } + + printMarkdown(str: string): void { + console.log(str); + } + + printValue(val: Value): void { + console.log(val.toString()); + } + + printError(err: Error): void { + if (this.verbose) { + console.log(err); + } + + console.log(`Error: ${err.toString()}`); + } + + printAction(action: Action): void { + if (this.verbose) { + console.log(`Action: ${action.log}`); + } + } +} + +export class ReplPrinter implements Printer { + rl : readline.Interface; + verbose : boolean + + constructor(rl: readline.Interface, verbose: boolean) { + this.rl = rl; + this.verbose = verbose; + } + + printLine(str: string): void { + console.log(`${str}`); + } + + printMarkdown(str: string): void { + console.log(`${str}`); + } + + printValue(val: Value): void { + console.log(val.toString()); + } + + printError(err: Error): void { + if (this.verbose) { + console.log(err); + } + + if (err instanceof EventProcessingError) { + console.log(`Event Processing Error:`); + console.log(`\t${err.error.toString()}`); + console.log(`\twhen processing event \`${formatEvent(err.event)}\``); + } else { + console.log(`Error: ${err.toString()}`); + } + } + + printAction(action: Action): void { + console.log(`Action: ${action.log}`); + } +} diff --git a/scenario/src/Repl.d.ts b/scenario/src/Repl.d.ts new file mode 100644 index 000000000..a4a22f456 --- /dev/null +++ b/scenario/src/Repl.d.ts @@ -0,0 +1,9 @@ +import {Artifacts} from './Artifact'; +import {Web3} from './Web3'; + +declare namespace NodeJS { + interface Global { + Web3: Web3 + Artifacts: Artifacts + } +} diff --git a/scenario/src/Repl.ts b/scenario/src/Repl.ts new file mode 100644 index 000000000..3bc297ad6 --- /dev/null +++ b/scenario/src/Repl.ts @@ -0,0 +1,168 @@ +import {ReplPrinter} from './Printer'; +import { + addInvariant, + initWorld, + IWeb3, + loadInvokationOpts, + loadDryRun, + loadSettings, + loadVerbose, + World +} from './World'; +import {Artifacts} from './Artifact'; +import {throwAssert} from './Assert'; +import {Macros} from './Macro'; +import {formatEvent} from './Formatter'; +import {complete} from './Completer'; +import {loadContracts} from './Networks'; +import {accountAliases, loadAccounts} from './Accounts'; +import {getNetworkPath} from './File'; +import {SuccessInvariant} from './Invariant/SuccessInvariant'; +import {createInterface} from './HistoricReadline'; +import {runCommand} from './Runner'; +import {parse} from './Parser'; +import Web3 from 'web3'; + +import * as fs from 'fs'; +import * as path from 'path'; + +const basePath = process.env.proj_root || process.cwd(); +const baseScenarioPath = path.join(basePath, 'spec', 'scenario'); + +declare var web3: IWeb3; +declare var artifacts: Artifacts; + +function questionPromise(rl): Promise { + return new Promise((resolve, reject) => { + rl.question(" > ", (command) => { + resolve(command); + }); + }); +} + +async function loop(world, rl, macros): Promise { + let command = await questionPromise(rl); + + try { + let newWorld = await runCommand(world, command, macros); + + return await loop(newWorld, rl, macros); + } catch (err) { + world.printer.printError(err); + return await loop(world, rl, macros); + } +} + +function loadEnvVars(): object { + return (process.env['env_vars'] || '').split(',').reduce((acc, keyValue) => { + if (keyValue.length === 0) { + return acc; + } else { + const [key, value] = keyValue.split('='); + + return { + ...acc, + [key]: value + }; + } + }, {}); +} + +async function repl(web3: IWeb3, artifacts: Artifacts): Promise { + // Uck, we need to load core macros :( + const coreMacros = fs.readFileSync(path.join(baseScenarioPath, 'CoreMacros'), 'utf8'); + + const macros = parse(coreMacros, {startRule: 'macros'}); + + let script = process.env['script']; + + let accounts: string[]; + + let network = process.env['network']; + + if (!network) { + throw new Error(`Missing required "network" env argument`); + } + + let world; + + let rl = await createInterface({ + input: process.stdin, + output: process.stdout, + completer: (line) => complete(world, macros, line), + path: getNetworkPath(basePath, network, '-history', null) + }); + + const verbose: boolean = !!process.env['verbose']; + let printer = new ReplPrinter(rl, verbose); + + // Uck, we have to load accounts first... + if (web3.currentProvider && web3.currentProvider.addresses && web3.currentProvider.addresses.length > 0) { + // We have a wallet provider + accounts = web3.currentProvider.addresses; + } else { + // Let's see if we have any unlocked accounts + accounts = await (new Web3(web3.currentProvider)).eth.personal.getAccounts(); + } + + let contractInfo: string[]; + world = await initWorld(throwAssert, printer, web3, artifacts, network, accounts, basePath); + [world, contractInfo] = await loadContracts(world); + world = loadInvokationOpts(world); + world = loadVerbose(world); + world = loadDryRun(world); + world = await loadSettings(world); + + printer.printLine(`Network: ${network}`); + + if (accounts.length > 0) { + printer.printLine(`Accounts:`); + accounts.forEach((account, i) => { + let aliases = world.settings.lookupAliases(account); + aliases = aliases.concat(accountAliases(i)); + + printer.printLine(`\t${account} (${aliases.join(',')})`) + }); + } + + if (contractInfo.length > 0) { + world.printer.printLine(`Contracts:`); + contractInfo.forEach((info) => world.printer.printLine(`\t${info}`)); + } + + printer.printLine(`Available macros: ${Object.keys(macros).toString()}`); + printer.printLine(``); + + if (script) { + printer.printLine(`Running script: ${script}...`); + const envVars = loadEnvVars(); + const scriptData: string = fs.readFileSync(script).toString(); + + if (Object.keys(envVars).length > 0) { + printer.printLine(`Env Vars:`); + } + + const replacedScript = Object.entries(envVars).reduce((data, [key, val]) => { + printer.printLine(`\t${key}: ${val}`); + + return data.split(`$${key}`).join(val); + }, scriptData); + + const finalScript = replacedScript.replace(new RegExp(/\$[\w_]+/, 'g'), 'Nothing'); + + return await finalScript.split("\n").reduce(async (acc, command) => { + return await runCommand(await acc, command, macros); + }, Promise.resolve(world)); + printer.printLine(`Script complete.`); + } else { + await loop(world, rl, macros); + } +} + +export = function(callback) { + repl(web3, artifacts).catch((err) => { + console.error("Fatal error"); + console.error(err); + callback(); + }).then(() => callback()); +} diff --git a/scenario/src/Runner.ts b/scenario/src/Runner.ts new file mode 100644 index 000000000..e5aac37e6 --- /dev/null +++ b/scenario/src/Runner.ts @@ -0,0 +1,20 @@ +import {World} from './World'; +import {parse} from './Parser'; +import {expandEvent, Macros} from './Macro'; +import {processEvents} from './CoreEvent' + +export async function runCommand(world: World, command: string, macros: Macros): Promise { + const trimmedCommand = command.trim(); + + const event = parse(trimmedCommand, {startRule: 'step'}); + + if (event === null) { + return world; + } else { + world.printer.printLine(`Command: ${trimmedCommand}`); + + let expanded = expandEvent(macros, event); + + return processEvents(world, expanded); + } +} diff --git a/scenario/src/Settings.ts b/scenario/src/Settings.ts new file mode 100644 index 000000000..ff82224f0 --- /dev/null +++ b/scenario/src/Settings.ts @@ -0,0 +1,75 @@ +import {getNetworkPath, readFile, writeFile} from './File'; + +export class Settings { + basePath: string | null + network: string | null + aliases: {[name: string]: string} + from: string | undefined + + constructor(basePath: string | null, network: string | null, aliases: {[name: string]: string}, from?: string) { + this.basePath = basePath; + this.network = network; + this.aliases = aliases; + this.from = from; + } + + static deserialize(basePath: string, network: string, data: string): Settings { + const {aliases} = JSON.parse(data); + + return new Settings(basePath, network, aliases); + } + + serialize(): string { + return JSON.stringify({ + aliases: this.aliases + }); + } + + static default(basePath: string | null, network: string | null): Settings { + return new Settings(basePath, network, {}); + } + + static getFilePath(basePath: string | null, network: string): string { + return getNetworkPath(basePath, network, '-settings'); + } + + static load(basePath: string, network: string): Promise { + return readFile(Settings.getFilePath(basePath, network), Settings.default(basePath, network), (data) => Settings.deserialize(basePath, network, data)); + } + + async save(): Promise { + if (this.network) { + return await writeFile(Settings.getFilePath(this.basePath, this.network), this.serialize()); + } + } + + lookupAlias(address: string): string { + let entry = Object.entries(this.aliases).find(([key, value]) => { + return value === address; + }); + + if (entry) { + return entry[0]; + } else { + return address; + } + } + + lookupAliases(address: string): string[] { + let entries = Object.entries(this.aliases).filter(([key, value]) => { + return value === address; + }); + + return entries.map(([key, _value]) => key); + } + + findAlias(name: string): string | null { + const alias = Object.entries(this.aliases).find(([alias, addr]) => alias.toLowerCase() === name.toLowerCase()); + + if (alias) { + return alias[1]; + } else { + return null; + } + } +} diff --git a/scenario/src/Utils.ts b/scenario/src/Utils.ts new file mode 100644 index 000000000..fa8c62051 --- /dev/null +++ b/scenario/src/Utils.ts @@ -0,0 +1,62 @@ +import {Event} from './Event'; +import {World} from './World'; + +// Wraps the element in an array, if it was not already an array +// If array is null or undefined, return the empty array +export function mustArray(arg: T[] | T): T[] { + if (Array.isArray(arg)) { + return arg; + } else { + if (arg === null || arg === undefined) { + return []; + } else { + return [arg]; + } + } +} + +// Asserts that the array must be given length and if so returns it, otherwise +// it will raise an error +export function mustLen(arg: any[] | any, len: number, maxLen?: number): any[] { + if (!Array.isArray(arg)) { + throw `Expected array of length ${len}, got ${arg}`; + } else if (maxLen === undefined && arg.length !== len) { + throw `Expected array of length ${len}, got length ${arg.length} (${arg})`; + } else if (maxLen !== undefined && (arg.length < len || arg.length > maxLen)) { + throw `Expected array of length ${len}-${maxLen}, got length ${arg.length} (${arg})`; + } else { + return arg; + } +} + +export function mustString(arg: Event): string { + if (typeof(arg) === "string") { + return arg; + } + + throw new Error(`Expected string argument, got ${arg.toString()}`); +} + +// Web3 doesn't have a function ABI parser.. not sure why.. but we build a simple encoder +// that accepts "fun(uint256,uint256)" and params and returns the encoded value. +export function encodeABI(world: World, fnABI: string, fnParams: string[]): string { + const regex = /(\w+)\(([\w,]+)\)/; + const res = regex.exec(fnABI); + if (!res) { + throw new Error(`Expected ABI signature, got: ${fnABI}`); + } + const [_, fnName, fnInputs] = <[string, string, string]>res; + const jsonInterface = { + name: fnName, + inputs: fnInputs.split(',').map((i) => ({name: '', type: i})) + }; + return world.web3.eth.abi.encodeFunctionCall(jsonInterface, fnParams); +} + +export function sleep(timeout: number): Promise { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(); + }, timeout); + }); +} diff --git a/scenario/src/Value.ts b/scenario/src/Value.ts new file mode 100644 index 000000000..be87535c2 --- /dev/null +++ b/scenario/src/Value.ts @@ -0,0 +1,386 @@ +import {World} from './World'; +import {Event} from './Event'; +import BigNumber from 'bignumber.js'; +import {toEncodableNum} from './Encoding'; +import {formatEvent} from './Formatter'; + +BigNumber.config({ ROUNDING_MODE: 3 }); +const mantissaOne = new BigNumber('1.0e18'); + +export enum Order { + EQUAL, + LESS_THAN, + GREATER_THAN +} + +export interface Value { + compareTo(world: World, given: Value): boolean + compareOrder(world: World, given: Value): Order + toString(): string + truthy(): boolean +} + +function compareInt(a: number, b: number): Order { + if (a === b) { + return Order.EQUAL; + } else if (a > b) { + return Order.GREATER_THAN; + } else { + return Order.LESS_THAN; + } +} + +export class EventV implements Value { + val: Event + + constructor(val) { + this.val = val; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof EventV) { + return JSON.stringify(this.val) === JSON.stringify(given.val); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `EventV`; + } + + truthy() { + // This check applies to strings or arrays :) + return this.val.length > 0; + } +} + +export class AnythingV implements Value { + compareTo(world: World, given: Value): boolean { + // Everything is awesome. + return true; + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `AnythingV<>`; + } + + truthy() { + return true; + } +} + +export class NothingV implements Value { + val: null + + constructor() { + this.val = null; + } + + compareTo(world: World, given: Value): boolean { + // Everything is not awesome. + return false; + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + encode() { + return null; + } + + toString() { + return `NothingV<>`; + } + + truthy() { + return false; + } +} + +export class BoolV implements Value { + val: boolean + + constructor(val) { + this.val = val; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof BoolV) { + return this.val === given.val; + } else if (given instanceof NumberV) { + return this.compareTo(world, given.toBoolV()); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `BoolV`; + } + + truthy() { + return this.val; + } +} + +export class StringV implements Value { + val: string + + constructor(val) { + this.val = val; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof StringV) { + return this.val === given.val; + } else if (given instanceof AddressV) { + return this.val === given.val; + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `StringV`; + } + + truthy() { + return this.val.length > 0; + } +} + +export class MapV implements Value { + val: object + + constructor(val) { + this.val = val; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof MapV) { + return JSON.stringify(this.val) === JSON.stringify(given.val); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `MapV`; + } + + truthy() { + return Object.keys(this.val).length > 0; + } +} + +export class AddressV implements Value { + val: string + + constructor(val) { + this.val = val; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof AddressV) { + return this.val === given.val; + } else if (given instanceof StringV) { + return this.val === given.val; + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `AddressV`; + } + + truthy() { + return this.val !== "0x0000000000000000000000000000000000000000"; + } +} + +export class NumberV implements Value { + val : number | string + + constructor(val: number | string, denom?: number | undefined) { + if (denom) { + this.val = Number(val) / denom; + } else { + this.val = val; + } + } + + toNumber(): number { + return Number(this.val); + } + + encode() { + return toEncodableNum(this.val); + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof NumberV) { + const thisBig = new BigNumber(this.val).toFixed(); + const givenBig = new BigNumber(given.val).toFixed(); + + return thisBig === givenBig; + } else if (given instanceof PreciseV) { + return this.compareTo(world, given.toNumberV()); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + if (given instanceof NumberV) { + const thisBig = new BigNumber(this.val).toNumber(); + const givenBig = new BigNumber(given.val).toNumber(); + + return compareInt(thisBig, givenBig); + } else if (given instanceof PreciseV) { + return this.compareOrder(world, given.toNumberV()); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + toBoolV(): BoolV { + if (this.val === 0) { + return new BoolV(true) + } else if (this.val === 1) { + return new BoolV(false); + } + + throw new Error(`Cannot convert number ${this.val} into bool`) + } + + asExp(denom=undefined): string { + return new BigNumber(this.val).toExponential(); + } + + show(): string { + return new BigNumber(this.val).toExponential(); + } + + toString() { + return `NumberV`; + } + + truthy() { + return this.val != 0; + } + + add(b: NumberV): NumberV { + return new NumberV(new BigNumber(this.val).plus(new BigNumber(b.val)).toFixed()); + } + + sub(b: NumberV): NumberV { + return new NumberV(new BigNumber(this.val).minus(new BigNumber(b.val)).toFixed()); + } +} + +export class ExpNumberV extends NumberV { + show() { + return new BigNumber(this.val).dividedBy(mantissaOne).toNumber().toString(); + } +} + +export class PercentV extends NumberV { + show() { + return new BigNumber(this.val).dividedBy(mantissaOne).multipliedBy(new BigNumber(100)).toNumber().toString() + '%'; + } +} + +export class PreciseV implements Value { + val: number + precision: number + + constructor(val, precision) { + this.val = val; + this.precision = precision; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof NumberV) { + const thisBig = new BigNumber(this.val.toString()).toPrecision(this.precision); + const givenBig = new BigNumber(given.val.toString()).toPrecision(this.precision); + + return thisBig === givenBig; + } else if (given instanceof PreciseV) { + // TODO: Is this okay? + return this.compareTo(world, given.toNumberV()); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toNumberV(): NumberV { + return new NumberV(this.val); + } + + toString() { + return `PreciseV`; + } + + truthy() { + return this.val != 0; + } +} + +export class ListV implements Value { + val: Value[] + + constructor(els) { + this.val = els; + } + + compareTo(world: World, given: Value): boolean { + if (given instanceof ListV) { + return this.val.every((el, i) => el.compareTo(world, given.val[i])); + } else { + throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + } + + compareOrder(world: World, given: Value): Order { + throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); + } + + toString() { + return `ListV el.toString()).join(',')}>`; + } + + truthy() { + return this.val.length > 0; + } +} diff --git a/scenario/src/Value/CTokenValue.ts b/scenario/src/Value/CTokenValue.ts new file mode 100644 index 000000000..19361f15f --- /dev/null +++ b/scenario/src/Value/CTokenValue.ts @@ -0,0 +1,293 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {CToken} from '../Contract/CToken'; +import {Erc20} from '../Contract/Erc20'; +import {InterestRateModel} from '../Contract/InterestRateModel'; +import { + getAddressV, + getCoreValue, + mapValue +} from '../CoreValue'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import { + AddressV, + NumberV, + Value, + StringV +} from '../Value'; +import {getWorldContractByAddress, getCTokenAddress} from '../ContractLookup'; + +export async function getCTokenV(world: World, event: Event): Promise { + const address = await mapValue( + world, + event, + (str) => new AddressV(getCTokenAddress(world, str)), + getCoreValue, + AddressV + ); + + return getWorldContractByAddress(world, address.val); +} + +async function cTokenAddress(world: World, cToken: CToken): Promise { + return new AddressV(cToken._address); +} + +async function getCTokenAdmin(world: World, cToken: CToken): Promise { + return new AddressV(await cToken.methods.admin().call()); +} + +async function getCTokenPendingAdmin(world: World, cToken: CToken): Promise { + return new AddressV(await cToken.methods.pendingAdmin().call()); +} + +async function balanceOfUnderlying(world: World, cToken: CToken, user: string): Promise { + return new NumberV(await cToken.methods.balanceOfUnderlying(user).call()); +} + +async function getBorrowBalance(world: World, cToken: CToken, user): Promise { + return new NumberV(await cToken.methods.borrowBalanceCurrent(user).call()); +} + +async function getBorrowBalanceStored(world: World, cToken: CToken, user): Promise { + return new NumberV(await cToken.methods.borrowBalanceStored(user).call()); +} + +async function getTotalBorrows(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.totalBorrows().call()); +} + +async function getTotalBorrowsCurrent(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.totalBorrowsCurrent().call()); +} + +async function getReserveFactor(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.reserveFactorMantissa().call(), 1.0e18); +} + +async function getTotalReserves(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.totalReserves().call()); +} + +async function getComptroller(world: World, cToken: CToken): Promise { + return new AddressV(await cToken.methods.comptroller().call()); +} + +async function getExchangeRateStored(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.exchangeRateStored().call()); +} + +async function getExchangeRate(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.exchangeRateCurrent().call(), 1e18); +} + +async function getInterestRate(world: World, cToken: CToken): Promise { + return new NumberV(await cToken.methods.borrowRatePerBlock().call(), 1.0e18 / 2102400); +} + +export function cTokenFetchers() { + return [ + new Fetcher<{cToken: CToken}, AddressV>(` + #### Address + + * "CToken Address" - Returns address of CToken contract + * E.g. "CToken cZRX Address" - Returns cZRX's address + `, + "Address", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => cTokenAddress(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, AddressV>(` + #### Admin + + * "CToken Admin" - Returns the admin of CToken contract + * E.g. "CToken cZRX Admin" - Returns cZRX's admin + `, + "Admin", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getCTokenAdmin(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, AddressV>(` + #### PendingAdmin + + * "CToken PendingAdmin" - Returns the pending admin of CToken contract + * E.g. "CToken cZRX PendingAdmin" - Returns cZRX's pending admin + `, + "PendingAdmin", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getCTokenPendingAdmin(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, AddressV>(` + #### Underlying + + * "CToken Underlying" - Returns the underlying asset (if applicable) + * E.g. "CToken cZRX Underlying" + `, + "Underlying", + [ + new Arg("cToken", getCTokenV) + ], + async (world, {cToken}) => new AddressV(await cToken.methods.underlying().call()), + {namePos: 1} + ), + new Fetcher<{cToken: CToken, address: AddressV}, NumberV>(` + #### UnderlyingBalance + + * "CToken UnderlyingBalance " - Returns a user's underlying balance (based on given exchange rate) + * E.g. "CToken cZRX UnderlyingBalance Geoff" + `, + "UnderlyingBalance", + [ + new Arg("cToken", getCTokenV), + new Arg("address", getAddressV) + ], + (world, {cToken, address}) => balanceOfUnderlying(world, cToken, address.val), + {namePos: 1} + ), + new Fetcher<{cToken: CToken, address: AddressV}, NumberV>(` + #### BorrowBalance + + * "CToken BorrowBalance " - Returns a user's borrow balance (including interest) + * E.g. "CToken cZRX BorrowBalance Geoff" + `, + "BorrowBalance", + [ + new Arg("cToken", getCTokenV), + new Arg("address", getAddressV) + ], + (world, {cToken, address}) => getBorrowBalance(world, cToken, address.val), + {namePos: 1} + ), + new Fetcher<{cToken: CToken, address: AddressV}, NumberV>(` + #### BorrowBalanceStored + + * "CToken BorrowBalanceStored " - Returns a user's borrow balance (without specifically re-accruing interest) + * E.g. "CToken cZRX BorrowBalanceStored Geoff" + `, + "BorrowBalanceStored", + [ + new Arg("cToken", getCTokenV), + new Arg("address", getAddressV) + ], + (world, {cToken, address}) => getBorrowBalanceStored(world, cToken, address.val), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### TotalBorrows + + * "CToken TotalBorrows" - Returns the cToken's total borrow balance + * E.g. "CToken cZRX TotalBorrows" + `, + "TotalBorrows", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getTotalBorrows(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### TotalBorrowsCurrent + + * "CToken TotalBorrowsCurrent" - Returns the cToken's total borrow balance with interest + * E.g. "CToken cZRX TotalBorrowsCurrent" + `, + "TotalBorrowsCurrent", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getTotalBorrowsCurrent(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### Reserves + + * "CToken Reserves" - Returns the cToken's total reserves + * E.g. "CToken cZRX Reserves" + `, + "Reserves", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getTotalReserves(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### ReserveFactor + + * "CToken ReserveFactor" - Returns reserve factor of CToken contract + * E.g. "CToken cZRX ReserveFactor" - Returns cZRX's reserve factor + `, + "ReserveFactor", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getReserveFactor(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, AddressV>(` + #### Comptroller + + * "CToken Comptroller" - Returns the cToken's comptroller + * E.g. "CToken cZRX Comptroller" + `, + "Comptroller", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getComptroller(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### ExchangeRateStored + + * "CToken ExchangeRateStored" - Returns the cToken's exchange rate (based on balances stored) + * E.g. "CToken cZRX ExchangeRateStored" + `, + "ExchangeRateStored", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getExchangeRateStored(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### ExchangeRate + + * "CToken ExchangeRate" - Returns the cToken's current exchange rate + * E.g. "CToken cZRX ExchangeRate" + `, + "ExchangeRate", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getExchangeRate(world, cToken), + {namePos: 1} + ), + new Fetcher<{cToken: CToken}, NumberV>(` + #### InterestRate + + * "CToken InterestRate" - Returns the cToken's current interest rate + * E.g. "CToken cZRX InterestRate" + `, + "InterestRate", + [ + new Arg("cToken", getCTokenV) + ], + (world, {cToken}) => getInterestRate(world, cToken), + {namePos: 1} + ) + ]; +} + +export async function getCTokenValue(world: World, event: Event): Promise { + return await getFetcherValue("cToken", cTokenFetchers(), world, event); +} diff --git a/scenario/src/Value/ComptrollerImplValue.ts b/scenario/src/Value/ComptrollerImplValue.ts new file mode 100644 index 000000000..a7678b969 --- /dev/null +++ b/scenario/src/Value/ComptrollerImplValue.ts @@ -0,0 +1,35 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; +import { + getAddressV +} from '../CoreValue'; +import { + AddressV, + Value +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getComptrollerImpl} from '../ContractLookup'; + +export async function getComptrollerImplAddress(world: World, comptrollerImpl: ComptrollerImpl): Promise { + return new AddressV(comptrollerImpl._address); +} + +export function comptrollerImplFetchers() { + return [ + new Fetcher<{comptrollerImpl: ComptrollerImpl}, AddressV>(` + #### Address + + * "ComptrollerImpl Address" - Returns address of comptroller implementation + `, + "Address", + [new Arg("comptrollerImpl", getComptrollerImpl)], + (world, {comptrollerImpl}) => getComptrollerImplAddress(world, comptrollerImpl), + {namePos: 1} + ) + ]; +} + +export async function getComptrollerImplValue(world: World, event: Event): Promise { + return await getFetcherValue("ComptrollerImpl", comptrollerImplFetchers(), world, event); +} diff --git a/scenario/src/Value/ComptrollerValue.ts b/scenario/src/Value/ComptrollerValue.ts new file mode 100644 index 000000000..7b001f527 --- /dev/null +++ b/scenario/src/Value/ComptrollerValue.ts @@ -0,0 +1,313 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {Comptroller} from '../Contract/Comptroller'; +import {CToken} from '../Contract/CToken'; +import { + getAddressV, + getStringV, + getNumberV +} from '../CoreValue'; +import { + AddressV, + BoolV, + ListV, + NumberV, + StringV, + Value +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getComptroller} from '../ContractLookup'; +import {encodedNumber} from '../Encoding'; +import {getCTokenV} from '../Value/CTokenValue'; + +export async function getComptrollerAddress(world: World, comptroller: Comptroller): Promise { + return new AddressV(comptroller._address); +} + +export async function getLiquidity(world: World, comptroller: Comptroller, user: string): Promise { + let {0: error, 1: liquidity, 2: shortfall} = await comptroller.methods.getAccountLiquidity(user).call(); + if (Number(error) != 0) { + throw new Error(`Failed to compute account liquidity: error code = ${error}`); + } + return new NumberV(Number(liquidity) - Number(shortfall)); +} + +export async function getHypotheticalLiquidity(world: World, comptroller: Comptroller, account: string, asset: string, redeemTokens: encodedNumber, borrowAmount: encodedNumber): Promise { + let {0: error, 1: liquidity, 2: shortfall} = await comptroller.methods.getHypotheticalAccountLiquidity(account, asset, redeemTokens, borrowAmount).call(); + if (Number(error) != 0) { + throw new Error(`Failed to compute account hypothetical liquidity: error code = ${error}`); + } + return new NumberV(Number(liquidity) - Number(shortfall)); +} + +async function getPriceOracle(world: World, comptroller: Comptroller): Promise { + return new AddressV(await comptroller.methods.oracle().call()); +} + +async function getCloseFactor(world: World, comptroller: Comptroller): Promise { + return new NumberV(await comptroller.methods.closeFactorMantissa().call(), 1e18); +} + +async function getMaxAssets(world: World, comptroller: Comptroller): Promise { + return new NumberV(await comptroller.methods.maxAssets().call()); +} + +async function getLiquidationIncentive(world: World, comptroller: Comptroller): Promise { + return new NumberV(await comptroller.methods.liquidationIncentiveMantissa().call(), 1e18); +} + +async function getImplementation(world: World, comptroller: Comptroller): Promise { + return new AddressV(await comptroller.methods.comptrollerImplementation().call()); +} + +async function getBlockNumber(world: World, comptroller: Comptroller): Promise { + return new NumberV(await comptroller.methods.blockNumber().call()); +} + +async function getAdmin(world: World, comptroller: Comptroller): Promise { + return new AddressV(await comptroller.methods.admin().call()); +} + +async function getPendingAdmin(world: World, comptroller: Comptroller): Promise { + return new AddressV(await comptroller.methods.pendingAdmin().call()); +} + +async function getCollateralFactor(world: World, comptroller: Comptroller, cToken: CToken): Promise { + let {0: _isListed, 1: collateralFactorMantissa} = await comptroller.methods.markets(cToken._address).call(); + + return new NumberV(collateralFactorMantissa, 1e18); +} + +async function membershipLength(world: World, comptroller: Comptroller, user: string): Promise { + return new NumberV(await comptroller.methods.membershipLength(user).call()); +} + +async function checkMembership(world: World, comptroller: Comptroller, user: string, cToken: CToken): Promise { + return new BoolV(await comptroller.methods.checkMembership(user, cToken._address).call()); +} + +async function getAssetsIn(world: World, comptroller: Comptroller, user: string): Promise { + let assetsList = await comptroller.methods.getAssetsIn(user).call(); + + return new ListV(assetsList.map((a) => new AddressV(a))); +} + +async function checkListed(world: World, comptroller: Comptroller, cToken: CToken): Promise { + let {0: isListed, 1: _collateralFactorMantissa} = await comptroller.methods.markets(cToken._address).call(); + + return new BoolV(isListed); +} + +export function comptrollerFetchers() { + return [ + new Fetcher<{comptroller: Comptroller}, AddressV>(` + #### Address + + * "Comptroller Address" - Returns address of comptroller + `, + "Address", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getComptrollerAddress(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller, account: AddressV}, NumberV>(` + #### Liquidity + + * "Comptroller Liquidity " - Returns a given user's trued up liquidity + * E.g. "Comptroller Liquidity Geoff" + `, + "Liquidity", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("account", getAddressV) + ], + (world, {comptroller, account}) => getLiquidity(world, comptroller, account.val) + ), + new Fetcher<{comptroller: Comptroller, account: AddressV, action: StringV, amount: NumberV, cToken: CToken}, NumberV>(` + #### Hypothetical + + * "Comptroller Hypothetical " - Returns a given user's trued up liquidity given a hypothetical change in asset with redeeming a certain number of tokens and/or borrowing a given amount. + * E.g. "Comptroller Hypothetical Geoff Redeems 6.0 cZRX" + * E.g. "Comptroller Hypothetical Geoff Borrows 5.0 cZRX" + `, + "Hypothetical", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("account", getAddressV), + new Arg("action", getStringV), + new Arg("amount", getNumberV), + new Arg("cToken", getCTokenV) + ], + async (world, {comptroller, account, action, cToken, amount}) => { + let redeemTokens: NumberV; + let borrowAmount: NumberV; + + switch (action.val.toLowerCase()) { + case "borrows": + redeemTokens = new NumberV(0); + borrowAmount = amount; + break; + case "redeems": + redeemTokens = amount; + borrowAmount = new NumberV(0); + break; + default: + throw new Error(`Unknown hypothetical: ${action.val}`); + } + + return await getHypotheticalLiquidity(world, comptroller, account.val, cToken._address, redeemTokens.encode(), borrowAmount.encode()); + } + ), + new Fetcher<{comptroller: Comptroller}, AddressV>(` + #### Admin + + * "Comptroller Admin" - Returns the Comptrollers's admin + * E.g. "Comptroller Admin" + `, + "Admin", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getAdmin(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, AddressV>(` + #### PendingAdmin + + * "Comptroller PendingAdmin" - Returns the pending admin of the Comptroller + * E.g. "Comptroller PendingAdmin" - Returns Comptroller's pending admin + `, + "PendingAdmin", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + ], + (world, {comptroller}) => getPendingAdmin(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, AddressV>(` + #### PriceOracle + + * "Comptroller PriceOracle" - Returns the Comptrollers's price oracle + * E.g. "Comptroller PriceOracle" + `, + "PriceOracle", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getPriceOracle(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, NumberV>(` + #### CloseFactor + + * "Comptroller CloseFactor" - Returns the Comptrollers's price oracle + * E.g. "Comptroller CloseFactor" + `, + "CloseFactor", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getCloseFactor(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, NumberV>(` + #### MaxAssets + + * "Comptroller MaxAssets" - Returns the Comptrollers's price oracle + * E.g. "Comptroller MaxAssets" + `, + "MaxAssets", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getMaxAssets(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, NumberV>(` + #### LiquidationIncentive + + * "Comptroller LiquidationIncentive" - Returns the Comptrollers's liquidation incentive + * E.g. "Comptroller LiquidationIncentive" + `, + "LiquidationIncentive", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getLiquidationIncentive(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, AddressV>(` + #### Implementation + + * "Comptroller Implementation" - Returns the Comptrollers's implementation + * E.g. "Comptroller Implementation" + `, + "Implementation", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getImplementation(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller}, NumberV>(` + #### BlockNumber + + * "Comptroller BlockNumber" - Returns the Comptrollers's mocked block number (for scenario runner) + * E.g. "Comptroller BlockNumber" + `, + "BlockNumber", + [new Arg("comptroller", getComptroller, {implicit: true})], + (world, {comptroller}) => getBlockNumber(world, comptroller) + ), + new Fetcher<{comptroller: Comptroller, cToken: CToken}, NumberV>(` + #### CollateralFactor + + * "Comptroller CollateralFactor " - Returns the collateralFactor associated with a given asset + * E.g. "Comptroller CollateralFactor cZRX" + `, + "CollateralFactor", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cToken", getCTokenV) + ], + (world, {comptroller, cToken}) => getCollateralFactor(world, comptroller, cToken) + ), + new Fetcher<{comptroller: Comptroller, account: AddressV}, NumberV>(` + #### MembershipLength + + * "Comptroller MembershipLength " - Returns a given user's length of membership + * E.g. "Comptroller MembershipLength Geoff" + `, + "MembershipLength", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("account", getAddressV) + ], + (world, {comptroller, account}) => membershipLength(world, comptroller, account.val) + ), + new Fetcher<{comptroller: Comptroller, account: AddressV, cToken: CToken}, BoolV>(` + #### CheckMembership + + * "Comptroller CheckMembership " - Returns one if user is in asset, zero otherwise. + * E.g. "Comptroller CheckMembership Geoff cZRX" + `, + "CheckMembership", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("account", getAddressV), + new Arg("cToken", getCTokenV) + ], + (world, {comptroller, account, cToken}) => checkMembership(world, comptroller, account.val, cToken) + ), + new Fetcher<{comptroller: Comptroller, account: AddressV}, ListV>(` + #### AssetsIn + + * "Comptroller AssetsIn " - Returns the assets a user is in + * E.g. "Comptroller AssetsIn Geoff" + `, + "AssetsIn", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("account", getAddressV) + ], + (world, {comptroller, account}) => getAssetsIn(world, comptroller, account.val) + ), + new Fetcher<{comptroller: Comptroller, cToken: CToken}, BoolV>(` + #### CheckListed + + * "Comptroller CheckListed " - Returns true if market is listed, false otherwise. + * E.g. "Comptroller CheckListed cZRX" + `, + "CheckListed", + [ + new Arg("comptroller", getComptroller, {implicit: true}), + new Arg("cToken", getCTokenV) + ], + (world, {comptroller, cToken}) => checkListed(world, comptroller, cToken) + ) + ]; +} + +export async function getComptrollerValue(world: World, event: Event): Promise { + return await getFetcherValue("Comptroller", comptrollerFetchers(), world, event); +} diff --git a/scenario/src/Value/Erc20Value.ts b/scenario/src/Value/Erc20Value.ts new file mode 100644 index 000000000..8f31716b0 --- /dev/null +++ b/scenario/src/Value/Erc20Value.ts @@ -0,0 +1,160 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {Erc20} from '../Contract/Erc20'; +import {getErc20Address, getWorldContractByAddress} from '../ContractLookup'; +import { + getAddressV, + getCoreValue, + mapValue, +} from '../CoreValue'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import { + AddressV, + NumberV, + Value, + StringV +} from '../Value'; + +export async function getErc20Name(world: World, erc20: Erc20): Promise { + return new StringV(await erc20.methods.name().call()); +} + +export async function getErc20Symbol(world: World, erc20: Erc20): Promise { + return new StringV(await erc20.methods.symbol().call()); +} + +export async function getErc20Decimals(world: World, erc20: Erc20): Promise { + return new NumberV(await erc20.methods.decimals().call()); +} + +async function getTotalSupply(world: World, erc20: Erc20): Promise { + return new NumberV(await erc20.methods.totalSupply().call()); +} + +async function getTokenBalance(world: World, erc20: Erc20, address: string): Promise { + return new NumberV(await erc20.methods.balanceOf(address).call()); +} + +async function getAllowance(world: World, erc20: Erc20, owner: string, spender: string): Promise { + return new NumberV(await erc20.methods.allowance(owner, spender).call()); +} + +export async function getErc20V(world: World, event: Event): Promise { + const address = await mapValue( + world, + event, + (str) => new AddressV(getErc20Address(world, str)), + getCoreValue, + AddressV + ); + + return getWorldContractByAddress(world, address.val); +} + +export function erc20Fetchers() { + return [ + new Fetcher<{erc20: Erc20}, AddressV>(` + #### Address + + * "Erc20 Address" - Returns address of ERC-20 contract + * E.g. "Erc20 ZRX Address" - Returns ZRX's address + `, + "Address", + [ + new Arg("erc20", getErc20V) + ], + async (world, {erc20}) => new AddressV(erc20._address), + {namePos: 1} + ), + new Fetcher<{erc20: Erc20}, StringV>(` + #### Name + + * "Erc20 Name" - Returns name of ERC-20 contract + * E.g. "Erc20 ZRX Name" - Returns ZRX's name + `, + "Name", + [ + new Arg("erc20", getErc20V) + ], + (world, {erc20}) => getErc20Name(world, erc20), + {namePos: 1} + ), + new Fetcher<{erc20: Erc20}, StringV>(` + #### Symbol + + * "Erc20 Symbol" - Returns symbol of ERC-20 contract + * E.g. "Erc20 ZRX Symbol" - Returns ZRX's symbol + `, + "Symbol", + [ + new Arg("erc20", getErc20V) + ], + (world, {erc20}) => getErc20Symbol(world, erc20), + {namePos: 1} + ), + new Fetcher<{erc20: Erc20}, NumberV>(` + #### Decimals + + * "Erc20 Decimals" - Returns number of decimals in ERC-20 contract + * E.g. "Erc20 ZRX Decimals" - Returns ZRX's decimals + `, + "Decimals", + [ + new Arg("erc20", getErc20V) + ], + (world, {erc20}) => getErc20Decimals(world, erc20), + {namePos: 1} + ), + new Fetcher<{erc20: Erc20}, NumberV>(` + #### TotalSupply + + * "Erc20 TotalSupply" - Returns the ERC-20 token's total supply + * E.g. "Erc20 ZRX TotalSupply" + * E.g. "Erc20 cZRX TotalSupply" + `, + "TotalSupply", + [ + new Arg("erc20", getErc20V) + ], + (world, {erc20}) => getTotalSupply(world, erc20), + {namePos: 1} + ), + new Fetcher<{erc20: Erc20, address: AddressV}, NumberV>(` + #### TokenBalance + + * "Erc20 TokenBalance
" - Returns the ERC-20 token balance of a given address + * E.g. "Erc20 ZRX TokenBalance Geoff" - Returns a user's ZRX balance + * E.g. "Erc20 cZRX TokenBalance Geoff" - Returns a user's cZRX balance + * E.g. "Erc20 ZRX TokenBalance cZRX" - Returns cZRX's ZRX balance + `, + "TokenBalance", + [ + new Arg("erc20", getErc20V), + new Arg("address", getAddressV) + ], + (world, {erc20, address}) => getTokenBalance(world, erc20, address.val), + {namePos: 1} + ), + new Fetcher<{erc20: Erc20, owner: AddressV, spender: AddressV}, NumberV>(` + #### Allowance + + * "Erc20 Allowance owner:
spender:
" - Returns the ERC-20 allowance from owner to spender + * E.g. "Erc20 ZRX Allowance Geoff Torrey" - Returns the ZRX allowance of Geoff to Torrey + * E.g. "Erc20 cZRX Allowance Geoff Coburn" - Returns the cZRX allowance of Geoff to Coburn + * E.g. "Erc20 ZRX Allowance Geoff cZRX" - Returns the ZRX allowance of Geoff to the cZRX cToken + `, + "Allowance", + [ + new Arg("erc20", getErc20V), + new Arg("owner", getAddressV), + new Arg("spender", getAddressV) + ], + (world, {erc20, owner, spender}) => getAllowance(world, erc20, owner.val, spender.val), + {namePos: 1} + ) + ]; +} + +export async function getErc20Value(world: World, event: Event): Promise { + return await getFetcherValue("Erc20", erc20Fetchers(), world, event); +} diff --git a/scenario/src/Value/InterestRateModelValue.ts b/scenario/src/Value/InterestRateModelValue.ts new file mode 100644 index 000000000..bbe75e197 --- /dev/null +++ b/scenario/src/Value/InterestRateModelValue.ts @@ -0,0 +1,38 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {InterestRateModel} from '../Contract/InterestRateModel'; +import { + getAddressV +} from '../CoreValue'; +import { + AddressV, + NumberV, + Value} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getInterestRateModel} from '../ContractLookup'; + +export async function getInterestRateModelAddress(world: World, interestRateModel: InterestRateModel): Promise { + return new AddressV(interestRateModel._address); +} + +export function interestRateModelFetchers() { + return [ + new Fetcher<{interestRateModel: InterestRateModel}, AddressV>(` + #### Address + + * " Address" - Gets the address of the global price oracle + * E.g. "InterestRateModel MyInterestRateModel Address" + `, + "Address", + [ + new Arg("interestRateModel", getInterestRateModel) + ], + (world, {interestRateModel}) => getInterestRateModelAddress(world, interestRateModel), + {namePos: 1} + ) + ]; +} + +export async function getInterestRateModelValue(world: World, event: Event): Promise { + return await getFetcherValue("InterestRateModel", interestRateModelFetchers(), world, event); +} diff --git a/scenario/src/Value/MaximillionValue.ts b/scenario/src/Value/MaximillionValue.ts new file mode 100644 index 000000000..eaf701e52 --- /dev/null +++ b/scenario/src/Value/MaximillionValue.ts @@ -0,0 +1,34 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {Maximillion} from '../Contract/Maximillion'; +import { + getAddressV +} from '../CoreValue'; +import { + AddressV, + Value +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getMaximillion} from '../ContractLookup'; + +export async function getMaximillionAddress(world: World, maximillion: Maximillion): Promise { + return new AddressV(maximillion._address); +} + +export function maximillionFetchers() { + return [ + new Fetcher<{maximillion: Maximillion}, AddressV>(` + #### Address + + * "Maximillion Address" - Returns address of maximillion + `, + "Address", + [new Arg("maximillion", getMaximillion, {implicit: true})], + (world, {maximillion}) => getMaximillionAddress(world, maximillion) + ) + ]; +} + +export async function getMaximillionValue(world: World, event: Event): Promise { + return await getFetcherValue("Maximillion", maximillionFetchers(), world, event); +} diff --git a/scenario/src/Value/PriceOracleProxyValue.ts b/scenario/src/Value/PriceOracleProxyValue.ts new file mode 100644 index 000000000..2eabec18e --- /dev/null +++ b/scenario/src/Value/PriceOracleProxyValue.ts @@ -0,0 +1,52 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {PriceOracleProxy} from '../Contract/PriceOracleProxy'; +import { + getAddressV +} from '../CoreValue'; +import { + AddressV, + NumberV, + Value} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getPriceOracleProxy} from '../ContractLookup'; + +export async function getPriceOracleProxyAddress(world: World, priceOracleProxy: PriceOracleProxy): Promise { + return new AddressV(priceOracleProxy._address); +} + +async function getPrice(world: World, priceOracleProxy: PriceOracleProxy, asset: string): Promise { + return new NumberV(await priceOracleProxy.methods.getUnderlyingPrice(asset).call()); +} + +export function priceOracleProxyFetchers() { + return [ + new Fetcher<{priceOracleProxy: PriceOracleProxy}, AddressV>(` + #### Address + + * "Address" - Gets the address of the global price oracle + `, + "Address", + [ + new Arg("priceOracleProxy", getPriceOracleProxy, {implicit: true}) + ], + (world, {priceOracleProxy}) => getPriceOracleProxyAddress(world, priceOracleProxy) + ), + new Fetcher<{priceOracle: PriceOracleProxy, asset: AddressV}, NumberV>(` + #### Price + + * "Price asset:
" - Gets the price of the given asset + `, + "Price", + [ + new Arg("priceOracle", getPriceOracleProxy, {implicit: true}), + new Arg("asset", getAddressV) + ], + (world, {priceOracle, asset}) => getPrice(world, priceOracle, asset.val) + ) + ]; +} + +export async function getPriceOracleProxyValue(world: World, event: Event): Promise { + return await getFetcherValue("PriceOracle", priceOracleProxyFetchers(), world, event); +} diff --git a/scenario/src/Value/PriceOracleValue.ts b/scenario/src/Value/PriceOracleValue.ts new file mode 100644 index 000000000..f954bec9d --- /dev/null +++ b/scenario/src/Value/PriceOracleValue.ts @@ -0,0 +1,52 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {PriceOracle} from '../Contract/PriceOracle'; +import { + getAddressV +} from '../CoreValue'; +import { + AddressV, + NumberV, + Value} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getPriceOracle} from '../ContractLookup'; + +async function getPrice(world: World, priceOracle: PriceOracle, asset: string): Promise { + return new NumberV(await priceOracle.methods.assetPrices(asset).call()); +} + +export async function getPriceOracleAddress(world: World, priceOracle: PriceOracle): Promise { + return new AddressV(priceOracle._address); +} + +export function priceOracleFetchers() { + return [ + new Fetcher<{priceOracle: PriceOracle}, AddressV>(` + #### Address + + * "Address" - Gets the address of the global price oracle + `, + "Address", + [ + new Arg("priceOracle", getPriceOracle, {implicit: true}) + ], + (world, {priceOracle}) => getPriceOracleAddress(world, priceOracle) + ), + new Fetcher<{priceOracle: PriceOracle, asset: AddressV}, NumberV>(` + #### Price + + * "Price asset:
" - Gets the price of the given asset + `, + "Price", + [ + new Arg("priceOracle", getPriceOracle, {implicit: true}), + new Arg("asset", getAddressV,) + ], + (world, {priceOracle, asset}) => getPrice(world, priceOracle, asset.val) + ) + ]; +} + +export async function getPriceOracleValue(world: World, event: Event): Promise { + return await getFetcherValue("PriceOracle", priceOracleFetchers(), world, event); +} diff --git a/scenario/src/Value/UnitrollerValue.ts b/scenario/src/Value/UnitrollerValue.ts new file mode 100644 index 000000000..0dcea38bc --- /dev/null +++ b/scenario/src/Value/UnitrollerValue.ts @@ -0,0 +1,34 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import {Unitroller} from '../Contract/Unitroller'; +import { + getAddressV +} from '../CoreValue'; +import { + AddressV, + Value +} from '../Value'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import {getUnitroller} from '../ContractLookup'; + +export async function getUnitrollerAddress(world: World, unitroller: Unitroller): Promise { + return new AddressV(unitroller._address); +} + +export function unitrollerFetchers() { + return [ + new Fetcher<{unitroller: Unitroller}, AddressV>(` + #### Address + + * "Unitroller Address" - Returns address of unitroller + `, + "Address", + [new Arg("unitroller", getUnitroller, {implicit: true})], + (world, {unitroller}) => getUnitrollerAddress(world, unitroller) + ) + ]; +} + +export async function getUnitrollerValue(world: World, event: Event): Promise { + return await getFetcherValue("Unitroller", unitrollerFetchers(), world, event); +} diff --git a/scenario/src/Value/UserValue.ts b/scenario/src/Value/UserValue.ts new file mode 100644 index 000000000..df183ccf1 --- /dev/null +++ b/scenario/src/Value/UserValue.ts @@ -0,0 +1,36 @@ +import {Event} from '../Event'; +import {World} from '../World'; +import { + getAddressV +} from '../CoreValue'; +import {Arg, Fetcher, getFetcherValue} from '../Command'; +import { + AddressV, + Value +} from '../Value'; + +async function getUserAddress(world: World, user: string): Promise { + return new AddressV(user); +} + +export function userFetchers() { + return [ + new Fetcher<{account: AddressV}, AddressV>(` + #### Address + + * "User Address" - Returns address of user + * E.g. "User Geoff Address" - Returns Geoff's address + `, + "Address", + [ + new Arg("account", getAddressV) + ], + async (world, {account}) => account, + {namePos: 1} + ) + ]; +} + +export async function getUserValue(world: World, event: Event): Promise { + return await getFetcherValue("User", userFetchers(), world, event); +} diff --git a/scenario/src/Verify.ts b/scenario/src/Verify.ts new file mode 100644 index 000000000..03b41c10e --- /dev/null +++ b/scenario/src/Verify.ts @@ -0,0 +1,157 @@ +import {World} from './World'; +import {readFile} from './File'; +import request from 'request'; +import * as path from 'path'; +import truffleFlattener from 'truffle-flattener'; +import {getNetworkContracts} from './Contract'; + +interface DevDoc { + author: string + methods: object + title: string +} + +interface UserDoc { + methods: object + notice: string +} + +function getUrl(network: string): string { + let host = { + kovan: 'api-kovan.etherscan.io', + rinkeby: 'api-rinkeby.etherscan.io', + ropsten: 'api-ropsten.etherscan.io', + goerli: 'api-goerli.etherscan.io', + mainnet: 'api.etherscan.io' + }[network]; + + if (!host) { + throw new Error(`Unknown etherscan API host for network ${network}`); + } + + return `https://${host}/api`; +} + +function getConstructorABI(world: World, contractName: string): string { + let constructorAbi = world.getIn(['contractData', 'Constructors', contractName]); + + if (!constructorAbi) { + throw new Error(`Unknown Constructor ABI for ${contractName} on ${world.network}. Try deploying again?`); + } + + return constructorAbi; +} + +function post(url, data): Promise { + return new Promise((resolve, reject) => { + request.post(url, {form: data}, (err, httpResponse, body) => { + if (err) { + reject(err); + } else { + resolve(JSON.parse(body)); + } + }); + }); +} + +function get(url, data): Promise { + return new Promise((resolve, reject) => { + request.get(url, {form: data}, (err, httpResponse, body) => { + if (err) { + reject(err); + } else { + resolve(JSON.parse(body)); + } + }); + }); +} + +interface Result { + status: string + message: string + result: string +} + +async function sleep(timeout): Promise { + return new Promise((resolve, _reject) => { + setTimeout(() => resolve(), timeout); + }) +} + +async function checkStatus(world: World, url: string, token: string): Promise { + world.printer.printLine(`Checking status of ${token}...`); + + // Potential results: + // { status: '0', message: 'NOTOK', result: 'Fail - Unable to verify' } + // { status: '0', message: 'NOTOK', result: 'Pending in queue' } + // { status: '1', message: 'OK', result: 'Pass - Verified' } + + let result: Result = await get(url, { + guid: token, + module: "contract", + action: "checkverifystatus" + }); + + if (world.verbose) { + console.log(result); + } + + if (result.result === "Pending in queue") { + await sleep(5000); + return await checkStatus(world, url, token); + } + + if (result.result.startsWith('Fail')) { + throw new Error(`Etherscan failed to verify contract: ${result.message} "${result.result}"`) + } + + if (Number(result.status) !== 1) { + throw new Error(`Etherscan Error: ${result.message} "${result.result}"`) + } + + world.printer.printLine(`Verification result ${result.result}...`); +} + +export async function verify(world: World, apiKey: string, contractName: string, buildInfoName: string, address: string): Promise { + let contractAddress: string = address; + let {networkContracts, version} = await getNetworkContracts(world); + let networkContract = networkContracts[buildInfoName]; + if (!networkContract) { + throw new Error(`Cannot find contract ${buildInfoName}, found: ${Object.keys(networkContracts)}`) + } + let sourceCode: string = await truffleFlattener([networkContract.path]); + let compilerVersion: string = version.replace(/(\.Emscripten)|(\.clang)|(\.Darwin)|(\.appleclang)/gi, ''); + let constructorAbi = getConstructorABI(world, contractName); + let url = getUrl(world.network); + + const verifyData: object = { + apikey: apiKey, + module: 'contract', + action: 'verifysourcecode', + contractaddress: contractAddress, + sourceCode: sourceCode, + contractname: buildInfoName, + compilerversion: `v${compilerVersion}`, + optimizationUsed: '1', + runs: '200', + constructorArguements: constructorAbi.slice(2) + }; + + world.printer.printLine(`Verifying ${contractName} at ${address} with compiler version ${compilerVersion}...`); + + // Potential results + // {"status":"0","message":"NOTOK","result":"Invalid constructor arguments provided. Please verify that they are in ABI-encoded format"} + // {"status":"1","message":"OK","result":"usjpiyvmxtgwyee59wnycyiet7m3dba4ccdi6acdp8eddlzdde"} + + let result: Result = await post(url, verifyData); + + if (Number(result.status) === 0 || result.message !== "OK") { + if (result.result.includes('Contract source code already verified')) { + world.printer.printLine(`Contract already verified`); + } else { + throw new Error(`Etherscan Error: ${result.message}: ${result.result}`) + } + } else { + return await checkStatus(world, url, result.result); + } +} diff --git a/scenario/src/Web.ts b/scenario/src/Web.ts new file mode 100644 index 000000000..f68e4bbaf --- /dev/null +++ b/scenario/src/Web.ts @@ -0,0 +1,29 @@ +import {parse} from './Parser'; +import {IWeb3, World, initWorld} from './World'; +import {throwAssert} from './Assert'; +import {CallbackPrinter} from './Printer'; +import {runCommand} from './Runner'; +import {loadContractData, parseNetworkFile} from './Networks'; + +export async function webWorld(web3: IWeb3, networksData: string, networksABIData: string, printerCallback: (message: any) => void): Promise { + let printer = new CallbackPrinter(printerCallback); + let accounts = [web3.currentProvider.address]; + let network = 'rinkeby'; // TODO: Get from web3 + + let world = await initWorld(throwAssert, printer, web3, null, network, accounts, null); + + let networks = parseNetworkFile(networksData); + let networksABI = parseNetworkFile(networksABIData); + + [world,] = await loadContractData(world, networks, networksABI); + // world = loadInvokationOpts(world); + // world = loadVerbose(world); + // world = loadDryRun(world); + // world = await loadSettings(world); + + return world; +} + +export async function webParse(world: World, line: string): Promise { + return runCommand(world, line, {}); +} diff --git a/scenario/src/World.ts b/scenario/src/World.ts new file mode 100644 index 000000000..6319c57d2 --- /dev/null +++ b/scenario/src/World.ts @@ -0,0 +1,346 @@ +import {Assert, throwAssert} from './Assert'; +import {Action} from './Action'; +import {Contract} from './Contract'; +import {Record} from 'immutable'; +import {Artifacts} from './Artifact'; +import {Printer} from './Printer'; +import {Invariant} from './Invariant'; +import {SuccessInvariant} from './Invariant/SuccessInvariant'; +import {RemainsInvariant} from './Invariant/RemainsInvariant'; +import {StaticInvariant} from './Invariant/StaticInvariant'; +import {Expectation} from './Expectation'; +import {formatResult} from './ErrorReporter'; +import {Invokation, InvokationOpts} from './Invokation'; +import {Event} from './Event'; +import {formatEvent} from './Formatter'; +import {Map} from 'immutable'; +import {Settings} from './Settings'; +import {Accounts, loadAccounts} from './Accounts'; +import Web3 from 'web3'; + +export interface IWeb3 { + currentProvider: any +} + +const startingBlockNumber = 1000; + +type ContractIndex = { [address:string]: Contract; }; + +export interface WorldProps { + actions: Action[], + event: Event | null, + lastInvokation: Invokation | null + newInvokation: boolean + blockNumber: number + lastContract: Contract | null + invariants: Invariant[] + expectations: Expectation[] + contractIndex: ContractIndex, + contractData: Map, + assert: Assert, + web3: Web3 | null, + artifacts: Artifacts | null + printer: Printer | null + network: string | null, + dryRun: boolean, + verbose: boolean, + settings: Settings, + accounts: Accounts | null, + invokationOpts: InvokationOpts, + trxInvokationOpts: Map, + basePath: string | null +} + +const defaultWorldProps : WorldProps = { + actions: []> [], + event: null, + lastInvokation: null, + newInvokation: false, + blockNumber: 0, + lastContract: null, + invariants: [], + expectations: [], + contractIndex: {}, + contractData: Map({}), + assert: throwAssert, + web3: null, + artifacts: null, + printer: null, + network: null, + dryRun: false, + verbose: false, + settings: Settings.default(null, null), + accounts: null, + invokationOpts: {}, + trxInvokationOpts: Map({}), + basePath: null +}; + +export class World extends Record(defaultWorldProps) { + public readonly actions!: Action[] + public readonly event!: Event | null + public readonly value!: number | null + public readonly lastInvokation!: Invokation | null + public readonly newInvokation!: boolean + public readonly blockNumber!: number + public readonly lastContract!: Contract | null + public readonly invariants!: Invariant[] + public readonly expectations!: Expectation[] + public readonly contractIndex!: ContractIndex + public readonly contractData!: Map + public readonly assert!: Assert + public readonly web3!: Web3 + public readonly artifacts!: Artifacts | null + public readonly printer!: Printer + public readonly network!: string + public readonly dryRun!: boolean + public readonly verbose!: boolean + public readonly settings!: Settings + public readonly accounts!: Accounts + public readonly invokationOpts!: InvokationOpts + public readonly trxInvokationOpts!: Map + public readonly basePath!: string | null + + public constructor(values?: Partial) { + values ? super(values) : super() + } + + getInvokationOpts(baseOpts: InvokationOpts): InvokationOpts { + return { + ...baseOpts, + ...this.invokationOpts, + ...{value: this.value ? this.value.toString() : undefined} + }; + } + + isLocalNetwork(): boolean { + return this.network === "test" || this.network === "development" || this.network === "coverage"; + } + + async updateSettings(fn: (settings: Settings) => Promise): Promise { + // TODO: Should we do an immutable update? + const newSettings = await fn(this.settings); + + // TODO: Should we await or just let it clobber? + await newSettings.save(); + + return this.set('settings', newSettings); + } + + defaultFrom(): string | null { + let settingsFrom = this.settings.findAlias('Me'); + if (settingsFrom) { + return settingsFrom; + } + + let accountsDefault = this.accounts.get('default'); + if (accountsDefault) { + return accountsDefault.address; + } + + return null; + } +} + +export function loadInvokationOpts(world: World): World { + let networkOpts = {}; + const networkOptsStr = process.env[`${world.network}_opts`]; + if (networkOptsStr) { + networkOpts = JSON.parse(networkOptsStr); + } + + return world.set('invokationOpts', networkOpts); +} + +export function loadVerbose(world: World): World { + return world.set('verbose', !!process.env['verbose']); +} + +export function loadDryRun(world: World): World { + return world.set('dryRun', !!process.env['dry_run']); +} + +export async function loadSettings(world: World): Promise { + if (world.basePath) { + return world.set('settings', await Settings.load(world.basePath, world.network)); + } else { + return world; + } +} + +export async function initWorld(assert: Assert, printer: Printer, iweb3: IWeb3, artifacts: Artifacts | null, network: string, accounts: string[], basePath: string | null): Promise { + let web3 = new Web3(iweb3.currentProvider); + + return new World({ + actions: [], + event: null, + lastInvokation: null, + newInvokation: true, + blockNumber: startingBlockNumber, + lastContract: null, + invariants: [new SuccessInvariant()], // Start with invariant success, + expectations: [], + contractIndex: {}, + contractData: Map({}), + assert: assert, + web3: web3, + artifacts: artifacts, + printer: printer, + network: network, + settings: Settings.default(basePath, null), + accounts: loadAccounts(accounts), + trxInvokationOpts: Map({}), + basePath: basePath + }); +} + +export function setEvent(world: World, event: Event): World { + return world.set( + 'event', + event + ); +}; + +export function addAction(world: World, log: string, invokation: Invokation): World { + const action = new Action(log, invokation); + + world = world.update( + 'actions', + (actions) => actions.concat([action]) + ); + + // Print the action via the printer + world.printer.printAction(action); + + return world.merge( + world, + { + lastInvokation: invokation, + newInvokation: true + } + ); +} + +export function addInvariant(world: World, invariant: Invariant): World { + return world.update( + 'invariants', + (invariants) => invariants.concat([invariant]) + ); +} + +export function addExpectation(world: World, expectation: Expectation): World { + return world.update( + 'expectations', + (expectations) => expectations.concat([expectation]) + ); +} + +function getInvariantFilter(type: string) { + let filters: {[filter: string]: (invariant: Invariant) => boolean} = { + all: (_invariant) => true, + success: (invariant) => !(invariant instanceof SuccessInvariant), + remains: (invariant) => !(invariant instanceof RemainsInvariant), + static: (invariant) => !(invariant instanceof StaticInvariant) + }; + + let filter = filters[type.toLowerCase()]; + + if (!filter) { + throw new Error(`Unknown invariant type \`${type}\` when wiping invariants.`); + } + + return filter; +} + +export function clearInvariants(world: World, type: string): World { + let filter = getInvariantFilter(type); + + return world.update( + 'invariants', + (invariants) => world.invariants.filter(filter) + ); +} + +export function holdInvariants(world: World, type: string): World { + let filter = getInvariantFilter(type); + + return world.update('invariants', (invariants) => { + return world.invariants.map((invariant) => { + if (filter(invariant)) { + invariant.held = true; + } + + return invariant; + }); + }); +} + +export async function checkExpectations(world: World): Promise { + if (!world.get('newInvokation')) { + return world; + } else { + // Lastly, check invariants each hold + await Promise.all(world.get('expectations').map((expectation) => { + // Check the expectation holds + return expectation.checker(world); + })); + + return world.set('expectations', []); + } +} + +export async function checkInvariants(world: World): Promise { + if (!world.get('newInvokation')) { + return world; + } else { + // Lastly, check invariants each hold + await Promise.all(world.get('invariants').map((invariant) => { + // Check the invariant still holds + if (!invariant.held) { + return invariant.checker(world); + } + })); + + // Remove holds + return world.update('invariants', (invariants) => { + return invariants.map((invariant) => { + invariant.held = false; + + return invariant; + }); + }); + } +} + +export function describeUser(world: World, address: string): string { + // Look up by alias + let alias = Object.entries(world.settings.aliases).find(([name, aliasAddr]) => aliasAddr === address); + if (alias) { + return alias[0]; + } + + // Look up by `from` + if (world.settings.from === address) { + return 'root'; + } + + // Look up by unlocked accounts + let account = world.accounts.find((account) => account.address === address); + if (account) { + return account.name; + } + + // Otherwise, just return the address itself + return address; +} + +// Fails an assertion with reason +export function fail(world: World, reason: string): World { + if (world.event) { + world.assert.fail(0, 1, `${reason} processing ${formatEvent(world.event)}`); + } else { + world.assert.fail(0, 1, reason); + } + + return world; +} diff --git a/scenario/tsconfig.json b/scenario/tsconfig.json new file mode 100644 index 000000000..ef2183052 --- /dev/null +++ b/scenario/tsconfig.json @@ -0,0 +1,63 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["esnext"], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./.tsbuilt", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "include": [ + "./src/**/*" + ] +} diff --git a/scenario/webpack.config.js b/scenario/webpack.config.js new file mode 100644 index 000000000..e25a1fbae --- /dev/null +++ b/scenario/webpack.config.js @@ -0,0 +1,28 @@ +'use strict' +const webpack = require('webpack'); + +module.exports = { + stats: 'verbose', + devtool: 'source-map', + externals: { + file: '{}', + fs: '{}', + tls: '{}', + net: '{}', + xmlhttprequest: '{}', + 'truffle-flattener': '{}', + 'request': '{}' + }, + optimization: { + minimize: true + }, + plugins: [ + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + new webpack.DefinePlugin({ + 'process.env': { + // This has effect on the react lib size + 'NODE_ENV': JSON.stringify('production'), + } + }) + ] +} diff --git a/scenario/yarn.lock b/scenario/yarn.lock new file mode 100644 index 000000000..d34536cf9 --- /dev/null +++ b/scenario/yarn.lock @@ -0,0 +1,5093 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@resolver-engine/core@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.2.1.tgz#0d71803f6d3b8cb2e9ed481a1bf0ca5f5256d0c0" + integrity sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A== + dependencies: + debug "^3.1.0" + request "^2.85.0" + +"@resolver-engine/fs@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.2.1.tgz#f98a308d77568cc02651d03636f46536b941b241" + integrity sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg== + dependencies: + "@resolver-engine/core" "^0.2.1" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz#5a81ef3285dbf0411ab3b15205080a1ad7622d9e" + integrity sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ== + dependencies: + "@resolver-engine/fs" "^0.2.1" + "@resolver-engine/imports" "^0.2.2" + debug "^3.1.0" + +"@resolver-engine/imports@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.2.2.tgz#d3de55a1bb5f3beb7703fdde743298f321175843" + integrity sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg== + dependencies: + "@resolver-engine/core" "^0.2.1" + debug "^3.1.0" + hosted-git-info "^2.6.0" + +"@types/node@^10.3.2": + version "10.14.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.4.tgz#1c586b991457cbb58fef51bc4e0cfcfa347714b5" + integrity sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg== + +"@webassemblyjs/ast@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" + integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== + dependencies: + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" + +"@webassemblyjs/floating-point-hex-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" + integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== + +"@webassemblyjs/helper-api-error@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" + integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== + +"@webassemblyjs/helper-buffer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" + integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== + +"@webassemblyjs/helper-code-frame@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" + integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== + dependencies: + "@webassemblyjs/wast-printer" "1.8.5" + +"@webassemblyjs/helper-fsm@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" + integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== + +"@webassemblyjs/helper-module-context@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" + integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== + dependencies: + "@webassemblyjs/ast" "1.8.5" + mamacro "^0.0.3" + +"@webassemblyjs/helper-wasm-bytecode@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" + integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== + +"@webassemblyjs/helper-wasm-section@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" + integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + +"@webassemblyjs/ieee754@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" + integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" + integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" + integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== + +"@webassemblyjs/wasm-edit@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" + integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/helper-wasm-section" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-opt" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/wast-printer" "1.8.5" + +"@webassemblyjs/wasm-gen@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" + integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" + +"@webassemblyjs/wasm-opt@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" + integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + +"@webassemblyjs/wasm-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" + integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" + +"@webassemblyjs/wast-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" + integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/floating-point-hex-parser" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-code-frame" "1.8.5" + "@webassemblyjs/helper-fsm" "1.8.5" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" + integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= + dependencies: + mime-types "~2.1.18" + negotiator "0.6.1" + +acorn-dynamic-import@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" + integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== + +acorn-walk@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" + integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw== + +acorn@^6.0.5, acorn@^6.0.7: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" + integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== + +ajv@^6.1.0, ajv@^6.5.5: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + dependencies: + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.2.tgz#8b8a7ca2a658f927e9f307d6d1a42f4199f0f735" + integrity sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg== + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bfj@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" + integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ== + dependencies: + bluebird "^3.5.1" + check-types "^7.3.0" + hoopy "^0.1.2" + tryer "^1.0.0" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +bignumber.js@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.1.tgz#5d419191370fb558c64e3e5f70d68e5947138832" + integrity sha512-zAySveTJXkgLYCBi0b14xzfnOs+f3G6x36I8w2a1+PFQpWk/dp0mI0F+ZZK2bu+3ELewDcSyP+Cfq++NcHX7sg== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +bindings@^1.3.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + +bluebird@^2.9.34: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= + +bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3: + version "3.5.4" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714" + integrity sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.6, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +body-parser@1.18.3, body-parser@^1.16.0: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sha3@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.4.tgz#086c47b8c82316c9d47022c26185954576dd8e26" + integrity sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY= + dependencies: + js-sha3 "^0.6.1" + safe-buffer "^5.1.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^5.0.5, buffer@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +cacache@^11.0.2: + version "11.3.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" + integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg== + dependencies: + bluebird "^3.5.3" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.3" + graceful-fs "^4.1.15" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.2" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^2.3.0, chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +check-types@^7.3.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" + integrity sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg== + +chokidar@^2.0.2: + version "2.1.5" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d" + integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== + +chrome-trace-event@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" + integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A== + dependencies: + tslib "^1.9.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + dependencies: + delayed-stream "~1.0.0" + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== + +commander@^2.18.0, commander@^2.19.0, commander@^2.8.1: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== + +commander@~2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= + dependencies: + graceful-readlink ">= 1.0.0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + +cookiejar@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-browserify@3.12.0, crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= + +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" + integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== + +elliptic@6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" + integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + inherits "^2.0.1" + +elliptic@^6.0.0, elliptic@^6.4.0: + version "6.4.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" + integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +es-abstract@^1.5.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eth-ens-namehash@2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-lib@0.1.27, eth-lib@^0.1.26: + version "0.1.27" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" + integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + keccakjs "^0.2.1" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-lib@0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" + integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +ethers@4.0.0-beta.1: + version "4.0.0-beta.1" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.1.tgz#0648268b83e0e91a961b1af971c662cdf8cbab6d" + integrity sha512-SoYhktEbLxf+fiux5SfCEwdzWENMvgIbMZD90I62s4GZD9nEjgEWy8ZboI3hck193Vs0bDoTohDISx84f2H2tw== + dependencies: + "@types/node" "^10.3.2" + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.3.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.3" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + +ethers@^4.0.0-beta.1: + version "4.0.27" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.27.tgz#e570b0da9d805ad65c83d81919abe02b2264c6bf" + integrity sha512-+DXZLP/tyFnXWxqr2fXLT67KlGUfLuvDkHSOtSC9TUVG9OIj6yrG5JPeXRMYo15xkOYwnjgdMKrXp5V94rtjJA== + dependencies: + "@types/node" "^10.3.2" + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.3.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.4" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +eventemitter3@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" + integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= + +events@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +express@^4.14.0, express@^4.16.3: + version "4.16.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" + integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.3" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.4" + qs "6.5.2" + range-parser "~1.2.0" + safe-buffer "5.1.2" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= + +file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filesize@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.4.0" + unpipe "~1.0.0" + +find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^2.0.0, fs-extra@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" + integrity sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== + dependencies: + minipass "^2.2.1" + +fs-promise@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" + integrity sha1-9k5PhUvPaJqovdy6JokW2z20aFQ= + dependencies: + any-promise "^1.3.0" + fs-extra "^2.0.0" + mz "^2.6.0" + thenify-all "^1.6.0" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" + integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +fstream@^1.0.2, fstream@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global@~4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +got@7.1.0, got@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== + +gzip-size@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" + integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== + dependencies: + duplexer "^0.1.1" + pify "^3.0.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +hoopy@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + +hosted-git-info@^2.6.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + +http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +iconv-lite@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + dependencies: + minimatch "^3.0.4" + +immutable@^4.0.0-rc.12: + version "4.0.0-rc.12" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" + integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +ini@^1.3.4, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +interpret@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +ipaddr.js@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" + integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.3, is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +js-sha3@0.5.7, js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= + +js-sha3@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.6.1.tgz#5b89f77a7477679877f58c4a075240934b1f95c0" + integrity sha1-W4n3enR3Z5h39YxKB1JAk0sflcA= + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +keccakjs@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" + integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== + dependencies: + browserify-sha3 "^0.0.4" + sha3 "^1.2.2" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +loader-runner@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@^1.0.2, loader-utils@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash@^4.17.10: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + +lowercase-keys@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +mamacro@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" + integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.38.0: + version "1.38.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" + integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: + version "2.1.22" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" + integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== + dependencies: + mime-db "~1.38.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minipass@^2.2.1, minipass@^2.3.4: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== + dependencies: + minipass "^2.2.1" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + mkdirp "0.5.1" + supports-color "4.4.0" + +mock-fs@^4.1.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.8.0.tgz#eb0784ceba4b34c91a924a5112eeb36e1b5a9e29" + integrity sha512-Gwj4KnJOW15YeTJKO5frFd/WDO5Mc0zxXqL9oHx3+e9rBqW8EVARqQHSaIXznUdljrD6pvbNGW2ZGXKPEfYJfw== + +mout@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" + integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +mz@^2.6.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nan@2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== + +nan@^2.0.8, nan@^2.11.0, nan@^2.3.3, nan@^2.9.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" + integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= + +neo-async@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" + integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-libs-browser@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.0.tgz#c72f60d9d46de08a940dedbb25f3ffa2f9bbaa77" + integrity sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.0" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "0.0.4" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-packlist@^1.1.6: + version "1.4.1" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" + integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.12: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" + integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +oboe@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" + integrity sha1-K0hl29Rr6BIlcT9Om/5Lz09oCk8= + dependencies: + http-https "^1.0.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +opener@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" + integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-locale@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" + integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@~1.0.5: + version "1.0.10" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parse-asn1@^5.0.0: + version "5.1.4" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" + integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-headers@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.2.tgz#9545e8a4c1ae5eaea7d24992bca890281ed26e34" + integrity sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg== + dependencies: + for-each "^0.3.3" + string.prototype.trim "^1.1.2" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pegjs@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +proxy-addr@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" + integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.8.0" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.24: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + +punycode@^1.2.4, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.5.2, qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +randomhex@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" + integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + +raw-body@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +request@^2.79.0, request@^2.85.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +scrypt-js@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" + integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= + +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== + +scrypt.js@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" + integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= + dependencies: + scrypt "^6.0.2" + scryptsy "^1.2.1" + +scrypt@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" + integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= + dependencies: + nan "^2.0.8" + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= + dependencies: + pbkdf2 "^3.0.3" + +seek-bzip@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= + dependencies: + commander "~2.8.1" + +semver@^5.0.1, semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serialize-javascript@^1.4.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" + integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== + +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= + +setimmediate@^1.0.4, setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha3@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" + integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= + dependencies: + nan "2.10.0" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + +simple-get@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +solidity-parser-antlr@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.4.2.tgz#b862eba5936e7a90b4f5f1c8eb1d33fe86650f78" + integrity sha512-0OKT2YKZAqPe14HN7Nbo24hjmnyUYh92UjyZG0Zz2rpQhl/w8asX8qHb+ASSXfayQaiW8g9zGIupXEE355tOQQ== + +solparse@^2.2.8: + version "2.2.8" + resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" + integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== + dependencies: + mocha "^4.0.1" + pegjs "^0.10.0" + yargs "^10.0.3" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.10: + version "0.5.11" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" + integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string.prototype.trim@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" + integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.0" + function-bind "^1.0.2" + +string_decoder@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + dependencies: + is-natural-number "^4.0.1" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== + dependencies: + has-flag "^2.0.0" + +supports-color@^5.3.0, supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +swarm-js@0.1.37: + version "0.1.37" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" + integrity sha512-G8gi5fcXP/2upwiuOShJ258sIufBVztekgobr3cVgYXObZwJ5AXLqZn52AI+/ffft29pJexF9WNdUxjlkVehoQ== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + decompress "^4.0.0" + eth-lib "^0.1.26" + fs-extra "^2.1.2" + fs-promise "^2.0.0" + got "^7.1.0" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar.gz "^1.0.5" + xhr-request-promise "^0.1.2" + +tapable@^1.0.0, tapable@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" + integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA== + +tar-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar.gz@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" + integrity sha512-uhGatJvds/3diZrETqMj4RxBR779LKlIE74SsMcn5JProZsfs9j0QBwWO1RW+IWNJxS2x8Zzra1+AW6OQHWphg== + dependencies: + bluebird "^2.9.34" + commander "^2.8.1" + fstream "^1.0.8" + mout "^0.11.0" + tar "^2.1.1" + +tar@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +tar@^4: + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.3.4" + minizlib "^1.1.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +terser-webpack-plugin@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz#3f98bc902fac3e5d0de730869f50668561262ec8" + integrity sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA== + dependencies: + cacache "^11.0.2" + find-cache-dir "^2.0.0" + schema-utils "^1.0.0" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + terser "^3.16.1" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" + +terser@^3.16.1: + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== + dependencies: + commander "^2.19.0" + source-map "~0.6.1" + source-map-support "~0.5.10" + +thenify-all@^1.0.0, thenify-all@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= + dependencies: + any-promise "^1.0.0" + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" + integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + dependencies: + setimmediate "^1.0.4" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +truffle-flattener@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/truffle-flattener/-/truffle-flattener-1.3.0.tgz#a5b0340897e32cf8389fea105b52fa93c335f04c" + integrity sha512-ppJ9xI0tDuvCYjQlcWwMBcOKZph5U4YpG/gChyUVDxOjUIniG5g7y9vZho2PRj1FohPPnOjg1KOAVNlk/bPZrw== + dependencies: + "@resolver-engine/imports-fs" "^0.2.2" + find-up "^2.1.0" + mkdirp "^0.5.1" + solidity-parser-antlr "^0.4.0" + tsort "0.0.1" + +truffle-hdwallet-provider@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.5.tgz#76059fb37d13df70bf37a9c296cf27d5a944e112" + integrity sha512-T9qNm7b6MD0UPWVmmJEhgzW1DdR6mkMDijGBSbdJqYaaBLufoycE+qH3dsV+m1mLTE+ebM5RcJ4gF4oXgDW67w== + dependencies: + any-promise "^1.3.0" + bindings "^1.3.1" + websocket "^1.0.28" + +tryer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== + +ts-loader@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.3.3.tgz#8b4af042e773132d86b3c99ef0acf3b4d325f473" + integrity sha512-KwF1SplmOJepnoZ4eRIloH/zXL195F51skt7reEsS6jvDqzgc/YSbz9b8E07GxIUwLXdcD4ssrJu6v8CwaTafA== + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^3.1.4" + semver "^5.0.1" + +ts-pegjs@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/ts-pegjs/-/ts-pegjs-0.2.2.tgz#f4ae6cc277133083858033badf6991a12a400f7c" + integrity sha512-7PUw/w9pFNk/kiv1x7e2lu4WUetQYnaCXjxiRJTEWoLSXpjsg8VKMZpUwa+zACNuWPCL7tcI+1IaC9mm3Pqb7Q== + dependencies: + pegjs "^0.10.0" + +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.18" + +typedarray-to-buffer@^3.1.2, typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^3.3.3: + version "3.4.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.1.tgz#b6691be11a881ffa9a05765a205cb7383f3b63c6" + integrity sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbzip2-stream@^1.0.9: + version "1.3.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" + integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + +underscore@1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" + integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg== + dependencies: + imurmurhash "^0.1.4" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" + integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf8@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" + integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= + +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +v8-compile-cache@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" + integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vm-browserify@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= + dependencies: + indexof "0.0.1" + +watchpack@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + +web3-bzz@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.37.tgz#59e3e4f5a9d732731008fe9165c3ec8bf85d502f" + integrity sha512-E+dho49Nsm/QpQvYWOF35YDsQrMvLB19AApENxhlQsu6HpWQt534DQul0t3Y/aAh8rlKD6Kanxt8LhHDG3vejQ== + dependencies: + got "7.1.0" + swarm-js "0.1.37" + underscore "1.8.3" + +web3-core-helpers@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.37.tgz#04ec354b7f5c57234c309eea2bda9bf1f2fe68ba" + integrity sha512-efaLOzN28RMnbugnyelgLwPWWaSwElQzcAJ/x3PZu+uPloM/lE5x0YuBKvIh7/PoSMlHqtRWj1B8CpuQOUQ5Ew== + dependencies: + underscore "1.8.3" + web3-eth-iban "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-core-method@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.37.tgz#53d148e63f818b23461b26307afdfbdaa9457744" + integrity sha512-pKWFUeqnVmzx3VrZg+CseSdrl/Yrk2ioid/HzolNXZE6zdoITZL0uRjnsbqXGEzgRRd1Oe/pFndpTlRsnxXloA== + dependencies: + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.37" + web3-core-promievent "1.0.0-beta.37" + web3-core-subscriptions "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-core-promievent@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.37.tgz#4e51c469d0a7ac0a969885a4dbcde8504abe5b02" + integrity sha512-GTF2r1lP8nJBeA5Gxq5yZpJy9l8Fb9CXGZPfF8jHvaRdQHtm2Z+NDhqYmF833lcdkokRSyfPcXlz1mlWeClFpg== + dependencies: + any-promise "1.3.0" + eventemitter3 "1.1.1" + +web3-core-requestmanager@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.37.tgz#721a75df5920621bff42d9d74f7a64413675d56b" + integrity sha512-66VUqye5BGp1Zz1r8psCxdNH+GtTjaFwroum2Osx+wbC5oRjAiXkkadiitf6wRb+edodjEMPn49u7B6WGNuewQ== + dependencies: + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.37" + web3-providers-http "1.0.0-beta.37" + web3-providers-ipc "1.0.0-beta.37" + web3-providers-ws "1.0.0-beta.37" + +web3-core-subscriptions@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.37.tgz#40de5e2490cc05b15faa8f935c97fd48d670cd9a" + integrity sha512-FdXl8so9kwkRRWziuCSpFsAuAdg9KvpXa1fQlT16uoGcYYfxwFO/nkwyBGQzkZt7emShI2IRugcazyPCZDwkOA== + dependencies: + eventemitter3 "1.1.1" + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.37" + +web3-core@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.37.tgz#66c2c7000772c9db36d737ada31607ace09b7e90" + integrity sha512-cIwEqCj7OJyefQNauI0HOgW4sSaOQ98V99H2/HEIlnCZylsDzfw7gtQUdwnRFiIyIxjbWy3iWsjwDPoXNPZBYg== + dependencies: + web3-core-helpers "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-core-requestmanager "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-eth-abi@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.37.tgz#55592fa9cd2427d9f0441d78f3b8d0c1359a2a24" + integrity sha512-g9DKZGM2OqwKp/tX3W/yihcj7mQCtJ6CXyZXEIZfuDyRBED/iSEIFfieDOd+yo16sokLMig6FG7ADhhu+19hdA== + dependencies: + ethers "4.0.0-beta.1" + underscore "1.8.3" + web3-utils "1.0.0-beta.37" + +web3-eth-accounts@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.37.tgz#0a5a9f14a6c3bd285e001c15eb3bb38ffa4b5204" + integrity sha512-uvbHL62/zwo4GDmwKdqH9c/EgYd8QVnAfpVw8D3epSISpgbONNY7Hr4MRMSd/CqAP12l2Ls9JVQGLhhC83bW6g== + dependencies: + any-promise "1.3.0" + crypto-browserify "3.12.0" + eth-lib "0.2.7" + scrypt.js "0.2.0" + underscore "1.8.3" + uuid "2.0.1" + web3-core "1.0.0-beta.37" + web3-core-helpers "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-eth-contract@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.37.tgz#87f93c95ed16f320ba54943b7886890de6766013" + integrity sha512-h1B3A8Z/C7BlnTCHkrWbXZQTViDxfR12lKMeTkT8Sqj5phFmxrBlPE4ORy4lf1Dk5b23mZYE0r/IRACx4ThCrQ== + dependencies: + underscore "1.8.3" + web3-core "1.0.0-beta.37" + web3-core-helpers "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-core-promievent "1.0.0-beta.37" + web3-core-subscriptions "1.0.0-beta.37" + web3-eth-abi "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-eth-ens@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.37.tgz#714ecb01eb447ee3eb39b2b20a10ae96edb1f01f" + integrity sha512-dR3UkrVzdRrJhfP57xBPx0CMiVnCcYFvh+u2XMkGydrhHgupSUkjqGr89xry/j1T0BkuN9mikpbyhdCVMXqMbg== + dependencies: + eth-ens-namehash "2.0.8" + underscore "1.8.3" + web3-core "1.0.0-beta.37" + web3-core-helpers "1.0.0-beta.37" + web3-core-promievent "1.0.0-beta.37" + web3-eth-abi "1.0.0-beta.37" + web3-eth-contract "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-eth-iban@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.37.tgz#313a3f18ae2ab00ba98678ea1156b09ef32a3655" + integrity sha512-WQRniGJFxH/XCbd7miO6+jnUG+6bvuzfeufPIiOtCbeIC1ypp1kSqER8YVBDrTyinU1xnf1U5v0KBZ2yiWBJxQ== + dependencies: + bn.js "4.11.6" + web3-utils "1.0.0-beta.37" + +web3-eth-personal@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.37.tgz#187472f51861e2b6d45da43411801bc91a859f9a" + integrity sha512-B4dZpGbD+nGnn48i6nJBqrQ+HB7oDmd+Q3wGRKOsHSK5HRWO/KwYeA7wgwamMAElkut50lIsT9EJl4Apfk3G5Q== + dependencies: + web3-core "1.0.0-beta.37" + web3-core-helpers "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-net "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-eth@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.37.tgz#0e8ffcd857a5f85ae4b5f052ad831ca5c56f4f74" + integrity sha512-Eb3aGtkz3G9q+Z9DKgSQNbn/u8RtcZQQ0R4sW9hy5KK47GoT6vab5c6DiD3QWzI0BzitHzR5Ji+3VHf/hPUGgw== + dependencies: + underscore "1.8.3" + web3-core "1.0.0-beta.37" + web3-core-helpers "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-core-subscriptions "1.0.0-beta.37" + web3-eth-abi "1.0.0-beta.37" + web3-eth-accounts "1.0.0-beta.37" + web3-eth-contract "1.0.0-beta.37" + web3-eth-ens "1.0.0-beta.37" + web3-eth-iban "1.0.0-beta.37" + web3-eth-personal "1.0.0-beta.37" + web3-net "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-net@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.37.tgz#b494136043f3c6ba84fe4a47d4c028c2a63c9a8e" + integrity sha512-xG/uBtMdDa1UMXw9KjDUgf3fXA/fDEJUYUS0TDn+U9PMgngA+UVECHNNvQTrVVDxEky38V3sahwIDiopNsQdsw== + dependencies: + web3-core "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +web3-providers-http@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.37.tgz#c06efd60e16e329e25bd268d2eefc68d82d13651" + integrity sha512-FM/1YDB1jtZuTo78habFj7S9tNHoqt0UipdyoQV29b8LkGKZV9Vs3is8L24hzuj1j/tbwkcAH+ewIseHwu0DTg== + dependencies: + web3-core-helpers "1.0.0-beta.37" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.37.tgz#55d247e7197257ca0c3e4f4b0fe1561311b9d5b9" + integrity sha512-NdRPRxYMIU0C3u18NI8u4bwbhI9pCg5nRgDGYcmSAx5uOBxiYcQy+hb0WkJRRhBoyIXJmy+s26FoH8904+UnPg== + dependencies: + oboe "2.1.3" + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.37" + +web3-providers-ws@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.37.tgz#77c15aebc00b75d760d22d063ac2e415bdbef72f" + integrity sha512-8p6ZLv+1JYa5Vs8oBn33Nn3VGFBbF+wVfO+b78RJS1Qf1uIOzjFVDk3XwYDD7rlz9G5BKpxhaQw+6EGQ7L02aw== + dependencies: + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.37" + websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" + +web3-shh@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.37.tgz#3246ce5229601b525020828a56ee283307057105" + integrity sha512-h5STG/xqZNQWtCLYOu7NiMqwqPea8SfkKQUPUFxXKIPVCFVKpHuQEwW1qcPQRJMLhlQIv17xuoUe1A+RzDNbrw== + dependencies: + web3-core "1.0.0-beta.37" + web3-core-method "1.0.0-beta.37" + web3-core-subscriptions "1.0.0-beta.37" + web3-net "1.0.0-beta.37" + +web3-utils@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.37.tgz#ab868a90fe5e649337e38bdaf72133fcbf4d414d" + integrity sha512-kA1fyhO8nKgU21wi30oJQ/ssvu+9srMdjOTKbHYbQe4ATPcr5YNwwrxG3Bcpbu1bEwRUVKHCkqi+wTvcAWBdlQ== + dependencies: + bn.js "4.11.6" + eth-lib "0.1.27" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randomhex "0.1.5" + underscore "1.8.3" + utf8 "2.1.1" + +web3@1.0.0-beta.37: + version "1.0.0-beta.37" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.37.tgz#b42c30e67195f816cd19d048fda872f70eca7083" + integrity sha512-8XLgUspdzicC/xHG82TLrcF/Fxzj2XYNJ1KTYnepOI77bj5rvpsxxwHYBWQ6/JOjk0HkZqoBfnXWgcIHCDhZhQ== + dependencies: + web3-bzz "1.0.0-beta.37" + web3-core "1.0.0-beta.37" + web3-eth "1.0.0-beta.37" + web3-eth-personal "1.0.0-beta.37" + web3-net "1.0.0-beta.37" + web3-shh "1.0.0-beta.37" + web3-utils "1.0.0-beta.37" + +webpack-bundle-analyzer@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.1.0.tgz#2f19cbb87bb6d4f3cb4e59cb67c837bd9436e89d" + integrity sha512-nyDyWEs7C6DZlgvu1pR1zzJfIWSiGPbtaByZr8q+Fd2xp70FuM/8ngCJzj3Er1TYRLSFmp1F1OInbEm4DZH8NA== + dependencies: + acorn "^6.0.7" + acorn-walk "^6.1.1" + bfj "^6.1.1" + chalk "^2.4.1" + commander "^2.18.0" + ejs "^2.6.1" + express "^4.16.3" + filesize "^3.6.1" + gzip-size "^5.0.0" + lodash "^4.17.10" + mkdirp "^0.5.1" + opener "^1.5.1" + ws "^6.0.0" + +webpack-cli@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.0.tgz#55c8a74cae1e88117f9dda3a801c7272e93ca318" + integrity sha512-t1M7G4z5FhHKJ92WRKwZ1rtvi7rHc0NZoZRbSkol0YKl4HvcC8+DsmGDmK7MmZxHSAetHagiOsjOB6MmzC2TUw== + dependencies: + chalk "^2.4.1" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.0" + findup-sync "^2.0.0" + global-modules "^1.0.0" + import-local "^2.0.0" + interpret "^1.1.0" + loader-utils "^1.1.0" + supports-color "^5.5.0" + v8-compile-cache "^2.0.2" + yargs "^12.0.5" + +webpack-sources@^1.1.0, webpack-sources@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" + integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.29.6: + version "4.29.6" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.6.tgz#66bf0ec8beee4d469f8b598d3988ff9d8d90e955" + integrity sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.0.5" + acorn-dynamic-import "^4.0.0" + ajv "^6.1.0" + ajv-keywords "^3.1.0" + chrome-trace-event "^1.0.0" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.0" + json-parse-better-errors "^1.0.2" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + micromatch "^3.1.8" + mkdirp "~0.5.0" + neo-async "^2.5.0" + node-libs-browser "^2.0.0" + schema-utils "^1.0.0" + tapable "^1.1.0" + terser-webpack-plugin "^1.1.0" + watchpack "^1.5.0" + webpack-sources "^1.3.0" + +websocket@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3" + integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA== + dependencies: + debug "^2.2.0" + nan "^2.11.0" + typedarray-to-buffer "^3.1.5" + yaeti "^0.0.6" + +"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": + version "1.0.26" + resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + dependencies: + debug "^2.2.0" + nan "^2.3.3" + typedarray-to-buffer "^3.1.2" + yaeti "^0.0.6" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.14, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +worker-farm@^1.5.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + integrity sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ== + dependencies: + errno "~0.1.7" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +xhr-request-promise@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" + integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= + dependencies: + xhr-request "^1.0.1" + +xhr-request@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.3.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== + dependencies: + global "~4.3.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== + dependencies: + camelcase "^4.1.0" + +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" + +yargs@^12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== + dependencies: + cliui "^4.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^1.0.1" + os-locale "^3.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" + +yauzl@^2.4.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" diff --git a/script/README.md b/script/README.md new file mode 100644 index 000000000..01c920da1 --- /dev/null +++ b/script/README.md @@ -0,0 +1 @@ +Scripts to make common developer tasks easy to type. diff --git a/script/certora/Dockerfile b/script/certora/Dockerfile new file mode 100644 index 000000000..8e3df4f3d --- /dev/null +++ b/script/certora/Dockerfile @@ -0,0 +1,7 @@ +FROM openjdk:13-alpine + +# Install solc +RUN wget https://github.com/ethereum/solidity/releases/download/v0.5.8/solc-static-linux -O /usr/bin/solc && chmod +x /usr/bin/solc + +# Install bash & z3 +RUN apk add bash z3 diff --git a/script/console b/script/console new file mode 100755 index 000000000..f1d219f42 --- /dev/null +++ b/script/console @@ -0,0 +1,11 @@ +#!/usr/bin/env sh + +DIR=`dirname $0` +PROJ_ROOT="$DIR/.." +export BUILD_DIRECTORY="$PROJ_ROOT/.build-temp" +export NETWORK=${1:-development} +export NETWORK_ID=$(npx truffle exec script/javascript/networkId.js --network "$NETWORK" 3>&2 2>&1 1>&3 3>&-) + +rm -rf $BUILD_DIRECTORY +node "$DIR/javascript/buildTruffle.js" +npx truffle console --network "$NETWORK" diff --git a/script/coverage b/script/coverage new file mode 100755 index 000000000..700b48161 --- /dev/null +++ b/script/coverage @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +dir=`dirname $0` +proj_root="$dir/.." + +[[ ! -d ./.tsbuilt || -z $NO_TSC ]] && "$proj_root/scenario/script/tsc" +case $1 in + "mocha") + export TEST_COMMAND="NETWORK=coverage SCENARIOS="skipall" script/test" + export SKIP_UNITROLLER="" + ;; + "scenario") + export TEST_COMMAND="NETWORK=coverage script/test test/ScenarioTest.js" + export SKIP_UNITROLLER="true" + ;; + *) + ;; +esac + +echo "TEST_COMMAND: $TEST_COMMAND" +echo "SKIP_UNITROLLER: $SKIP_UNITROLLER" + +"$proj_root/node_modules/.bin/solidity-coverage" diff --git a/script/ganache b/script/ganache new file mode 100755 index 000000000..a8b0d2176 --- /dev/null +++ b/script/ganache @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +dir=`dirname $0` +proj_root="$dir/.." + +node "$proj_root/node_modules/ganache-cli/cli.js" \ + --gasLimit 20000000 \ + --gasPrice 20000 \ + --defaultBalanceEther 1000000000 \ + --allowUnlimitedContractSize \ + $@ diff --git a/script/ganache-coverage b/script/ganache-coverage new file mode 100755 index 000000000..c7f109d3f --- /dev/null +++ b/script/ganache-coverage @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +dir=`dirname $0` +proj_root="$dir/.." + +node "$proj_root/node_modules/ethereumjs-testrpc-sc/cli.js" \ + --port 8555 \ + --gasLimit 17592186044415 \ + --gasPrice 1 \ + --allowUnlimitedContractSize \ + $@ diff --git a/script/javascript/buildTruffle.js b/script/javascript/buildTruffle.js new file mode 100644 index 000000000..7bcb21cad --- /dev/null +++ b/script/javascript/buildTruffle.js @@ -0,0 +1,99 @@ +const fs = require('fs'); +const path = require('path'); + +const network = process.env['NETWORK']; +const jsonPath = `networks/${network}.json`; +const contractsPath = `networks/${network}-contracts.json`; +const buildDirectory = process.env['BUILD_DIRECTORY']; +const networkId = process.env['NETWORK_ID']; +let jsonRaw; +let json; + +function error(msg, e=undefined) { + console.error(msg); + if (e) { + console.error(e); + } + + process.exit(1); +} + +if (!buildDirectory) { + error(`required env $BUILD_DIRECTORY not set`); +} + +if (!network) { + error(`required env NETWORK not set`); +} + +function readJson(filePath) { + let json, jsonRaw; + + try { + jsonRaw = fs.readFileSync(filePath, 'utf8'); + } catch (e) { + error(`cannot read \`${filePath}\`, try running \`yarn run deploy\` first`, e) + } + + try { + json = JSON.parse(jsonRaw); + } catch (e) { + error(`cannot parse \`${filePath}\` as JSON. You may delete this file and redeploy.`, e); + } + + return json; +} + +json = readJson(jsonPath); +contracts = readJson(contractsPath); + +const contractTypes = { + PriceOracle: { + singleton: true + }, + Maximillion: { + singleton: true + }, + Comptroller: {}, + Tokens: {} +} + +fs.mkdirSync(path.join(buildDirectory, 'contracts'), { recursive: true }); + +let abis = {}; + +Object.entries(contracts['contracts']).forEach(([key, values]) => { + let [_, contractName] = key.split(':', 2); + + abis[contractName] = values['abi']; +}); + +function addContract(key, contract, address) { + console.info(`${key} (${contract}): ${address}`); + + const json = { + contractName: key, + abi: abis[contract], + networks: { + [networkId]: { + address: address + } + } + }; + + fs.writeFileSync(path.join(buildDirectory, 'contracts', `${key}.json`), JSON.stringify(json)); +} + +Object.entries(contractTypes).forEach(([key, {singleton}]) => { + if (singleton) { + if (json[key] && json[key].address) { + addContract(key, json.contract || key, json[key].address); + } + } else { + Object.entries(json[key]).forEach(([subKey, subJson]) => { + if (subJson.address) { + addContract(subKey, subJson.contract || subKey, subJson.address); + } + }); + } +}); diff --git a/script/javascript/networkId.js b/script/javascript/networkId.js new file mode 100644 index 000000000..aa2a4ed43 --- /dev/null +++ b/script/javascript/networkId.js @@ -0,0 +1,3 @@ +module.exports = function() { + web3.eth.net.getId().then((id) => console.error(id)); +}; \ No newline at end of file diff --git a/script/lint b/script/lint new file mode 100755 index 000000000..c85340a97 --- /dev/null +++ b/script/lint @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +set -e + +DIR=`dirname $0` +PROJ_ROOT="$DIR/.." + +"$PROJ_ROOT/node_modules/.bin/solium" -d "$PROJ_ROOT/test" +"$PROJ_ROOT/node_modules/.bin/solium" -d "$PROJ_ROOT/contracts" diff --git a/script/scen/deploy.scen b/script/scen/deploy.scen new file mode 100755 index 000000000..d9a66a506 --- /dev/null +++ b/script/scen/deploy.scen @@ -0,0 +1,31 @@ +#!/usr/bin/env yarn run repl -s +-- Deploys new Comptroller with some ERC20 and some cTokens + +-- First deploy a price oracle +Gate (PriceOracle Address) (PriceOracle Deploy Simple) + +-- Next a comptroller +Gate (Comptroller Address) (Comptroller Deploy YesNo) + +-- Next an interest rate model +Gate (InterestRateModel InterestRateModel Address) (InterestRateModel Deploy Fixed InterestRateModel 0.0004) + +-- Now deploy some ERC-20 faucet tokens +Gate (Erc20 ZRX Address) (Erc20 Deploy Standard ZRX "0x") +Gate (Erc20 BAT Address) (Erc20 Deploy NonStandard BAT "Basic Attention Token") +Gate (Erc20 DAI Address) (Erc20 Deploy Standard DAI "Dai") +Gate (Erc20 REP Address) (Erc20 Deploy Standard REP "Augur") +Gate (Erc20 USDC Address) (Erc20 Deploy Standard USDC "USD Coin" 6) + +-- Now deploy our cTokens +Gate (CToken cZRX Address) (CToken Deploy CErc20 cZRX "Test 0x 📈" (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel InterestRateModel Address) 0.2e9 8) +Gate (CToken cBAT Address) (CToken Deploy CErc20 cBAT "Test Basic Attention Token 📈" (Erc20 BAT Address) (Comptroller Address) (InterestRateModel InterestRateModel Address) 0.2e9 8) +Gate (CToken cDAI Address) (CToken Deploy CErc20 cDAI "Test Dai 📈" (Erc20 DAI Address) (Comptroller Address) (InterestRateModel InterestRateModel Address) 0.2e9 8) +Gate (CToken cREP Address) (CToken Deploy CErc20 cREP "Test Augur 📈" (Erc20 REP Address) (Comptroller Address) (InterestRateModel InterestRateModel Address) 0.2e9 8) +Gate (CToken cETH Address) (CToken Deploy CEther cETH "Test Ether 📈" (Comptroller Address) (InterestRateModel InterestRateModel Address) 0.2e9 8) +Gate (CToken cUSDC Address) (CToken Deploy CErc20 cUSDC "Test USD Coin 📈" (Erc20 USDC Address) (Comptroller Address) (InterestRateModel InterestRateModel Address) 2e-4 8) + +-- Deploy Maximillion +Gate (Maximillion Address) (Maximillion Deploy cETH) + +Print "Deployed Comptroller and cTokens: cETH, cBAT, cDAI, cREP, cUSDC and cZRX" diff --git a/script/scenario b/script/scenario new file mode 100755 index 000000000..e9b2a915b --- /dev/null +++ b/script/scenario @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +dir=`dirname $0` +proj_root="$dir/.." +verbose=${verbose:-} + +# Combine any params as simple regex (a|b|c) +IFS='|' +verbose="$verbose" SCENARIOS="$*" "$dir/test" "test/ScenarioTest.js" diff --git a/script/test b/script/test new file mode 100755 index 000000000..be995d2c1 --- /dev/null +++ b/script/test @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +dir=`dirname $0` +proj_root="$dir/.." +test_root="$dir/../test" +contracts_root="$dir/../contracts" +network=${NETWORK:-test} +verbose=${verbose:-} + +function cleanup { + mv "$contracts_root/test" "$test_root/contracts" +} + +trap cleanup EXIT + +mv "$test_root/contracts" "$contracts_root/test" + +if [ "$CI" -a ! "$1" ]; then + set -x + set -- "$@" $(circleci tests glob "test/**/*Test.js" "test/**/*Test.sol" | circleci tests split --split-by=timings) +fi + +# Coverage clones our project but not node_modules, so let's hop +# up one directory. +if [ ! -d "$proj_root/node_modules" -a -d "$proj_root/../node_modules" ]; then + proj_root="$proj_root/.." +fi + +# Compile scenario runner +[[ ! -d ./.tsbuilt || -z $NO_TSC ]] && "$proj_root/scenario/script/tsc" +[[ -z $no_compile ]] && solc --combined-json bin,abi --optimize contracts/*.sol contracts/**/*.sol --allow-paths ./contracts,./contracts/test > $proj_root/networks/${network}-contracts.json + +echo "cwd: $(pwd), proj_root: $(cd $proj_root && pwd), networks: $(ls -l $proj_root/networks/${network}-contracts.json)" +node --stack_size=10000 "$proj_root/node_modules/truffle/build/cli.bundled.js" compile --network "$network" +proj_root="$proj_root" verbose="$verbose" node --stack_size=10000 "$proj_root/node_modules/truffle/build/cli.bundled.js" test --network "$network" $@ diff --git a/script/verify b/script/verify new file mode 100755 index 000000000..03acc503e --- /dev/null +++ b/script/verify @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -eo + +dir=`dirname $0` +proj_root="$dir/.." +contracts="`(cd $proj_root && pwd)`/contracts" +emv_jar="$proj_root/scripts/certora/emv.jar" + +command -v java >/dev/null 2>&1 || { echo "Error: java is not installed." >&2; exit 1; } +command -v z3 >/dev/null 2>&1 || { echo "Error: z3 is not installed." >&2; exit 1; } + +function verify_spec { + [ -e "$1" ] || (echo "spec file not found: $1" && exit 1) + + set -x + java -jar "$emv_jar" -spec "$1" -theory INT -s z3 -graphDrawLimit 0 -path $contracts + set +x +} + +if [ "$CI" ]; then + all_specs=($(circleci tests glob "$proj_root/spec/formal/*.spclnk" | circleci tests split --split-by=timings)) + echo XXX disabled in CI for now... && exit 0 +else + if [[ $# -eq 0 ]] ; then + all_specs=($proj_root/spec/formal/*.spclnk) + else + all_specs=($@) + fi +fi + +echo "running specs ${all_specs[@]}" + +for spec in "${all_specs[@]}"; do + verify_spec "$spec" +done diff --git a/spec/formal/CompoundIgnoreExtCalls.spclnk b/spec/formal/CompoundIgnoreExtCalls.spclnk new file mode 100644 index 000000000..98c102acb --- /dev/null +++ b/spec/formal/CompoundIgnoreExtCalls.spclnk @@ -0,0 +1,13 @@ +{ + "contracts": [ + { + "name": "CErc20Certora", + "file": "spec/formal/contracts/CErc20Certora.sol", + "address": "123" + } + ], + + "cvlsToCheck": { + "CErc20Certora": ["spec/formal/general.cvl"] + } +} \ No newline at end of file diff --git a/spec/formal/EIP20.spclnk b/spec/formal/EIP20.spclnk new file mode 100644 index 000000000..cb89e5607 --- /dev/null +++ b/spec/formal/EIP20.spclnk @@ -0,0 +1,145 @@ +{ + "contracts": [ + { + "name": "ComptrollerModel", + "file": "spec/formal/contracts/ComptrollerModel.sol", + "address": "789", + "methods": [ + { + "name": "mintAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "mintVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "redeemAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "redeemVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "borrowAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "borrowVerify", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "repayBorrowAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "repayBorrowVerify", + "args": ["address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "liquidateBorrowAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "liquidateBorrowVerify", + "args": ["address","address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "seizeAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "seizeVerify", + "args": ["address","address","address","address","uint256"], + "returns": [] + }, + { + "name": "transferAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "transferVerify", + "args": ["address","address","address","uint256"], + "returns": [] + }, + { + "name": "liquidateCalculateSeizeTokens", + "args": ["address","address","uint256"], + "returns": ["uint256","uint256"] + } + ] + }, + + { + "name": "UnderlyingModelNonStandard", + "file": "spec/formal/contracts/UnderlyingModelNonStandard.sol", + "address": "456", + "methods": [ + { + "name": "balanceOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "allowance", + "args": ["address","address"], + "returns": ["uint256"] + }, + { + "name": "totalSupply", + "args": [], + "returns": ["uint256"] + }, + { + "name": "transfer", + "args": ["address","uint256"], + "returns": [] + }, + { + "name": "transferFrom", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "approve", + "args": ["address","uint256"], + "returns": ["bool"] + }, + { + "name": "dummy", + "args": [], + "returns": [] + } + ] + }, + + { + "name": "CErc20Certora", + "file": "spec/formal/contracts/CErc20Certora.sol", + "address": "123", + "state": { + 6: "789", + 18: "456" + } + } + ], + + "cvlsToCheck": { + "CErc20Certora": [ + "spec/formal/eip20.cvl" + ] + } +} \ No newline at end of file diff --git a/spec/formal/Liquidate.spclnk b/spec/formal/Liquidate.spclnk new file mode 100644 index 000000000..ee73e4aea --- /dev/null +++ b/spec/formal/Liquidate.spclnk @@ -0,0 +1,208 @@ +{ + "contracts": [ + { + "name": "ComptrollerModel", + "file": "spec/formal/contracts/ComptrollerModel.sol", + "address": "789", + "methods": [ + { + "name": "mintAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "mintVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "redeemAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "redeemVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "borrowAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "borrowVerify", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "repayBorrowAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "repayBorrowVerify", + "args": ["address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "liquidateBorrowAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "liquidateBorrowVerify", + "args": ["address","address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "seizeAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "seizeVerify", + "args": ["address","address","address","address","uint256"], + "returns": [] + }, + { + "name": "transferAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "transferVerify", + "args": ["address","address","address","uint256"], + "returns": [] + }, + { + "name": "liquidateCalculateSeizeTokens", + "args": ["address","address","uint256"], + "returns": ["uint256","uint256"] + } + ] + }, + + { + "name": "UnderlyingModelNonStandard", + "file": "spec/formal/contracts/UnderlyingModelNonStandard.sol", + "address": "456", + "methods": [ + { + "name": "balanceOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "allowance", + "args": ["address","address"], + "returns": ["uint256"] + }, + { + "name": "totalSupply", + "args": [], + "returns": ["uint256"] + }, + { + "name": "transfer", + "args": ["address","uint256"], + "returns": [] + }, + { + "name": "transferFrom", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "approve", + "args": ["address","uint256"], + "returns": ["bool"] + }, + { + "name": "dummy", + "args": [], + "returns": [] + } + ] + }, + + { + "name": "CTokenCollateral", + "file": "spec/formal/contracts/CTokenCollateral.sol", + "address": "321", + "state": { + 6: "789", + 18: "456" + }, + "methods": [ + { + "name": "accrualBlockNumber", + "args": [], + "returns": ["uint256"] + }, + { + "name": "balanceOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "borrowBalanceStored", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "exchangeRateStored", + "args": [], + "returns": ["uint256"] + }, + { + "name": "getCash", + "args": [], + "returns": ["uint256"] + }, + { + "name": "getCashOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "totalSupply", + "args": [], + "returns": ["uint256"] + }, + { + "name": "totalBorrows", + "args": [], + "returns": ["uint256"] + }, + { + "name": "totalReserves", + "args": [], + "returns": ["uint256"] + }, + { + "name": "seize", + "args": ["address,address,uint256"], + "returns": ["uint256"] + } + ] + }, + + { + "name": "CErc20Certora", + "file": "spec/formal/contracts/CErc20Certora.sol", + "address": "123", + "state": { + 6: "789", + 18: "456", + 19: "321" + } + } + ], + + "cvlsToCheck": { + "CErc20Certora": [ + "spec/formal/liquidateFresh.cvl" + ] + } +} \ No newline at end of file diff --git a/spec/formal/Maximillion.spclnk b/spec/formal/Maximillion.spclnk new file mode 100644 index 000000000..88c1213f1 --- /dev/null +++ b/spec/formal/Maximillion.spclnk @@ -0,0 +1,127 @@ +{ + "contracts": [ + { + "name": "ComptrollerModel", + "file": "spec/formal/contracts/ComptrollerModel.sol", + "address": "789", + "methods": [ + { + "name": "mintAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "mintVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "redeemAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "redeemVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "borrowAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "borrowVerify", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "repayBorrowAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "repayBorrowVerify", + "args": ["address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "liquidateBorrowAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "liquidateBorrowVerify", + "args": ["address","address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "seizeAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "seizeVerify", + "args": ["address","address","address","address","uint256"], + "returns": [] + }, + { + "name": "transferAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "transferVerify", + "args": ["address","address","address","uint256"], + "returns": [] + }, + { + "name": "liquidateCalculateSeizeTokens", + "args": ["address","address","uint256"], + "returns": ["uint256","uint256"] + } + ] + }, + + { + "name": "CEtherCertora", + "file": "spec/formal/contracts/CEtherCertora.sol", + "address": "234", + "state": { + 6: "789" + }, + "methods": [ + { + "name": "borrowBalanceCurrent", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "repayBorrowBehalf", + "args": ["address"], + "returns": [] + }, + { + "name": "totalBorrows", + "args": [], + "returns": ["uint256"] + } + ] + }, + + { + "name": "MaximillionCertora", + "file": "spec/formal/contracts/MaximillionCertora.sol", + "address": "666", + "state": { + 0: "234" + } + } + ], + + "cvlsToCheck": { + "MaximillionCertora": [ + "spec/formal/maximillion.cvl" + ] + } +} \ No newline at end of file diff --git a/spec/formal/MintRedeemBorrowRepay.spclnk b/spec/formal/MintRedeemBorrowRepay.spclnk new file mode 100644 index 000000000..ca6350e7a --- /dev/null +++ b/spec/formal/MintRedeemBorrowRepay.spclnk @@ -0,0 +1,209 @@ +{ + "contracts": [ + { + "name": "ComptrollerModel", + "file": "spec/formal/contracts/ComptrollerModel.sol", + "address": "789", + "methods": [ + { + "name": "mintAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "mintVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "redeemAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "redeemVerify", + "args": ["address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "borrowAllowed", + "args": ["address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "borrowVerify", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "repayBorrowAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "repayBorrowVerify", + "args": ["address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "liquidateBorrowAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "liquidateBorrowVerify", + "args": ["address","address","address","address","uint256","uint256"], + "returns": [] + }, + { + "name": "seizeAllowed", + "args": ["address","address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "seizeVerify", + "args": ["address","address","address","address","uint256"], + "returns": [] + }, + { + "name": "transferAllowed", + "args": ["address","address","address","uint256"], + "returns": ["uint256"] + }, + { + "name": "transferVerify", + "args": ["address","address","address","uint256"], + "returns": [] + }, + { + "name": "liquidateCalculateSeizeTokens", + "args": ["address","address","uint256"], + "returns": ["uint256","uint256"] + } + ] + }, + + { + "name": "UnderlyingModelNonStandard", + "file": "spec/formal/contracts/UnderlyingModelNonStandard.sol", + "address": "456", + "methods": [ + { + "name": "balanceOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "allowance", + "args": ["address","address"], + "returns": ["uint256"] + }, + { + "name": "totalSupply", + "args": [], + "returns": ["uint256"] + }, + { + "name": "transfer", + "args": ["address","uint256"], + "returns": [] + }, + { + "name": "transferFrom", + "args": ["address","address","uint256"], + "returns": [] + }, + { + "name": "approve", + "args": ["address","uint256"], + "returns": ["bool"] + }, + { + "name": "dummy", + "args": [], + "returns": [] + } + ] + }, + + { + "name": "CTokenCollateral", + "file": "spec/formal/contracts/CTokenCollateral.sol", + "address": "321", + "state": { + 6: "789", + 18: "456" + }, + "methods": [ + { + "name": "accrualBlockNumber", + "args": [], + "returns": ["uint256"] + }, + { + "name": "balanceOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "borrowBalanceStored", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "exchangeRateStored", + "args": [], + "returns": ["uint256"] + }, + { + "name": "getCash", + "args": [], + "returns": ["uint256"] + }, + { + "name": "getCashOf", + "args": ["address"], + "returns": ["uint256"] + }, + { + "name": "totalSupply", + "args": [], + "returns": ["uint256"] + }, + { + "name": "totalBorrows", + "args": [], + "returns": ["uint256"] + }, + { + "name": "totalReserves", + "args": [], + "returns": ["uint256"] + }, + { + "name": "seize", + "args": ["address,address,uint256"], + "returns": ["uint256"] + } + ] + }, + + { + "name": "CErc20Certora", + "file": "spec/formal/contracts/CErc20Certora.sol", + "address": "123", + "state": { + 6: "789", + 18: "456", + 19: "321" + } + } + ], + + "cvlsToCheck": { + "CErc20Certora": [ + "spec/formal/mintAndRedeemFresh.cvl", + "spec/formal/borrowAndRepayFresh.cvl" + ] + } +} \ No newline at end of file diff --git a/spec/formal/_setMarketPolicyHook.cvl b/spec/formal/_setMarketPolicyHook.cvl new file mode 100644 index 000000000..f109b36a4 --- /dev/null +++ b/spec/formal/_setMarketPolicyHook.cvl @@ -0,0 +1,72 @@ +methods { + admin() returns address + _setMarketPolicyHook(address,address) returns uint256 + markets(address) returns bool,uint256,uint256,address,address,uint256,uint256,uint256,uint256,uint256,uint256 +} + +_setMarketPolicyHook(uint result, uint currentAdmin, address asset, address currentPolicyHook, address reqPolicyHook,address newPolicyHook, bool isListed) +description "Failed to set market policy hook from $currentPolicyHook to $reqPolicyHook for $asset (result=$result, admin=$currentAdmin, newPolicyHook=newPolicyHook, isListed=$isListed)" { + // N.B. The implementation calls `policyHook.isPolicyHook()` + // which needs to return true for the call to _setMarketPolicyHook to succeed. + // We can't currently control or specify that, so we may get intermittent failures. + + bool isListedT; + address currentPolicyHookT; + address newPolicyHookT; + + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + // Capture current admin and collateral factor + static_require currentAdmin == sinvoke admin(e0); + + isListedT, _, _, _, currentPolicyHookT, _, _, _, _, _, _ = sinvoke markets(e0, asset); + + static_require isListed == isListedT; + static_require currentPolicyHook == currentPolicyHookT; + + // Invoke set collateral factor + uint256 resultT = sinvoke _setMarketPolicyHook(e1, asset, reqPolicyHook); + + static_require result == resultT; + + _, _, _, _, newPolicyHookT, _, _, _, _, _, _ = sinvoke markets(e2, asset); + + static_require newPolicyHook == newPolicyHookT; + + static_assert ( + ( + // success + result == 0 && + e1.msg.sender == currentAdmin && + newPolicyHook == reqPolicyHook && + isListed + ) || + ( + // fail unauthorized + result == 1 && + e1.msg.sender != currentAdmin && + newPolicyHook == currentPolicyHook + ) || + ( + // fail not listed + result == 10 && + e1.msg.sender == currentAdmin && + newPolicyHook == currentPolicyHook && + !isListed + ) || + ( + // fail bad input + result == 5 && + e1.msg.sender == currentAdmin && + newPolicyHook == currentPolicyHook && + isListed + ) + ); +} \ No newline at end of file diff --git a/spec/formal/_setMarketPriceOracle.cvl b/spec/formal/_setMarketPriceOracle.cvl new file mode 100644 index 000000000..60d0675aa --- /dev/null +++ b/spec/formal/_setMarketPriceOracle.cvl @@ -0,0 +1,63 @@ +methods { + admin() returns address + markets(address) returns bool,uint256,uint256,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256 + _setMarketPriceOracle(address,address) returns uint256 +} + +_setMarketPriceOracle(uint result, address asset, address reqPriceOracle) +description "Failed to set market oracle for $asset with result $result (result=$result, asset=$asset, reqPriceOracle=$reqPriceOracle)" { + // N.B. The implementation calls `priceOracle.assetPrices(address(0))` + // which needs to not revert for the call to succeed. + + address currAdmin; + bool currListed; + address currPriceOracle; + address nextPriceOracle; + + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + // Capture curr values + uint currAdmin = sinvoke admin(e0); + currListed, _, _, currPriceOracle, _, _, _, _, _, _, _, _ = sinvoke markets(e0, asset); + + // Invoke set market oracle + uint256 resultT = sinvoke _setMarketPriceOracle(e1, asset, reqPriceOracle); + static_require result == resultT; + + // Get next value + _, _, _, nextPriceOracle, _, _, _, _, _, _, _, _ = sinvoke markets(e2, asset); + + // Guarantee return values + static_assert( + result == 0 || + result == 1 || + result == 10 + ); + + // Success case updates market + static_assert(result == 0 <=> ( + e1.msg.sender == currAdmin && + nextPriceOracle == reqPriceOracle && + currListed + )); + + // Unauthorized case + static_assert(result == 1 <=> ( + e1.msg.sender != currAdmin && + nextPriceOracle == currPriceOracle + )); + + // Unlisted case + static_assert(result == 10 <=> ( + e1.msg.sender == currAdmin && + nextPriceOracle == currPriceOracle && + !currListed + )); +} \ No newline at end of file diff --git a/spec/formal/accrueInterest.cvl b/spec/formal/accrueInterest.cvl new file mode 100644 index 000000000..184e0fb1a --- /dev/null +++ b/spec/formal/accrueInterest.cvl @@ -0,0 +1,77 @@ +methods { + getCash() returns uint256 + accrueInterest() returns uint256 + interestRateModelGetBorrowRate() returns uint256, uint256 + accrualBlockNumber() returns uint256 + borrowIndex() returns uint256 + totalBorrows() returns uint256 + totalReserves() returns uint256 + reserveFactorMantissa() returns uint256 +} + +accrueInterest(uint result) +description "Break accrueInterest with result=$result, block delta is $delta" { + // Pre/action/post environments + env e0; havoc e0; // pre+action + env e1; havoc e1; // post + + static_require e1.block.number >= e0.block.number; + + // fetch pre + uint256 cTokenCashPre = sinvoke getCash(e0); + uint256 interestRateModelErr; + uint256 borrowRateMantissaPre; + interestRateModelErr, borrowRateMantissaPre = sinvoke interestRateModelGetBorrowRate(e0); + uint256 accrualBlockNumberPre = sinvoke accrualBlockNumber(e0); + uint256 borrowIndexPre = sinvoke borrowIndex(e0); + uint256 totalBorrowsPre = sinvoke totalBorrows(e0); + uint256 totalReservesPre = sinvoke totalReserves(e0); + uint256 reserveFactorPre = sinvoke reserveFactorMantissa(e0); + + // internal computations + uint256 delta = e0.block.number-accrualBlockNumberPre; + uint256 simpleInterestFactor = delta*borrowRateMantissaPre; + uint256 interestAccumulated = (totalBorrowsPre * simpleInterestFactor) / 1000000000000000000; // div 1000000000000000000 + + // post expected + uint256 borrowIndexPostExpected = borrowIndexPre + (borrowIndexPre*simpleInterestFactor)/1000000000000000000; // div 1000000000000000000 the right multiplicand + uint256 totalBorrowsPostExpected = totalBorrowsPre + interestAccumulated; + uint256 totalReservesPostExpected = totalReservesPre + (interestAccumulated*reserveFactorPre)/1000000000000000000; // div 1000000000000000000 the right multiplicand + + // Action! + static_require result == invoke accrueInterest(e0); + bool accrueInterestReverted = lastReverted; + + // fetch post + uint256 accrualBlockNumberPost = sinvoke accrualBlockNumber(e1); + uint256 borrowIndexPostActual = sinvoke borrowIndex(e1); + uint256 totalBorrowsPostActual = sinvoke totalBorrows(e1); + uint256 totalReservesPostActual = sinvoke totalReserves(e1); + + uint256 NO_ERROR = 0; + uint256 INTEREST_RATE_MODEL_ERROR = 5; + uint256 MATH_ERROR = 9; + + // Guarantee return values + static_assert (!accrueInterestReverted) => + (result == NO_ERROR || + result == INTEREST_RATE_MODEL_ERROR || + result == MATH_ERROR), "Got unexpected error code $result"; + + static_assert (!accrueInterestReverted => (result == INTEREST_RATE_MODEL_ERROR <=> interestRateModelErr != 0)), "Mismatch in case of interest rate model error"; + + static_assert (!accrueInterestReverted => + ((result != 0 || delta == 0) <=> + (accrualBlockNumberPost == accrualBlockNumberPre && + borrowIndexPostActual == borrowIndexPre && + totalBorrowsPostActual == totalBorrowsPre && + totalReservesPostActual == totalReservesPre))), "Mismatch in error case"; + + static_assert (!accrueInterestReverted => + ((result == 0 /*&& delta > 0*/) <=> + (accrualBlockNumberPost == e0.block.number && + borrowIndexPostActual == borrowIndexPostExpected && + totalBorrowsPostActual == totalBorrowsPostExpected && + totalReservesPostActual == totalReservesPostExpected + ))), "Mismatch in no error case: borrowIndex: pre=$borrowIndexPre, actual=$borrowIndexPostActual, expected=$borrowIndexPostExpected; totalBorrows: pre=$totalBorrowsPre, actual=$totalBorrowsPostActual, expected=$totalBorrowsPostExpected; totalReserves: pre=$totalReservesPre, acutal=$totalReservesPostActual, expected=$totalReservesPostExpected"; +} diff --git a/spec/formal/admin_setCollateralFactor.cvl b/spec/formal/admin_setCollateralFactor.cvl new file mode 100644 index 000000000..b6695f5b2 --- /dev/null +++ b/spec/formal/admin_setCollateralFactor.cvl @@ -0,0 +1,101 @@ +methods { +// taken from solc --hashes contracts/MoneyMarket.sol +/*e4028eee: */ _setCollateralFactor(address,uint256) returns uint256 +/*f851a440: */ admin() returns address +/*3b8a7478: */ getCollateralFactorREMOVE_ME(address) returns uint256 +/*e43fb3a9: */ getMarketListedREMOVE_ME(address) returns bool +/*8e8f294b: */ markets(address) // TODO: returns market tuple +/*7dc0d1d0: */ oracle() returns address +} + +_setCollateralFactor(uint currentAdmin, address asset, uint currentCollateralFactor, uint newCollateralFactor) +description "Failed to set collateralFactor from $currentCollateralFactor to $newCollateralFactor for $asset (admin=$currentAdmin)" { + // N.B. For non-zero collateralFactor, the implementation calls `oracleInterface.assetPrices(address($asset))` + // which needs to return non-zero for the call to _setCollateralFactor to succeed. + // We can't currently control or specify that, so we may get intermittent failures. + + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + // Capture current admin and collateral factor + static_require currentAdmin == sinvoke admin(e0); + // getCollateralFactorREMOVE_ME is a workaround until we have support for structs + static_require currentCollateralFactor == sinvoke getCollateralFactorREMOVE_ME(e0, asset); + + // Invoke set collateral factor + uint256 result = sinvoke _setCollateralFactor(e1, asset, newCollateralFactor); + + // collateralFactor changes <=> msg.sender == currentAdmin + + // newCollateralFactor > 0 && oracle non-zero & price > 0 + // newCollateralFactor == 0 + + static_assert ( + ( + // fail is caller is not admin + e1.msg.sender != currentAdmin && + result != 0 && + // getCollateralFactorREMOVE_ME is a workaround until we have support for structs + sinvoke getCollateralFactorREMOVE_ME(e2, asset) == currentCollateralFactor + ) + || + ( + // fail if not listed + e1.msg.sender == currentAdmin && + sinvoke getMarketListedREMOVE_ME(e2, asset) != true && + result == 9 && // MARKET_NOT_LISTED + sinvoke getCollateralFactorREMOVE_ME(e2, asset) == currentCollateralFactor + ) + || + ( + // fail if listed but newCollateralFactor too high + e1.msg.sender == currentAdmin && + sinvoke getMarketListedREMOVE_ME(e2, asset) && + // 0.9 * 1e18: 9e17 + newCollateralFactor > 900000000000000000 && + result == 25 && // INVALID_COLLATERAL_FACTOR + sinvoke getCollateralFactorREMOVE_ME(e2, asset) == currentCollateralFactor + ) + || + ( + // Succeed if sender is admin, market listed, newCollateralFactor > 0 and oracle set + // In this case we also require oracleInterface.assetPrices(asset) > 0, but we can't currently specify that + // as it involves a call to another contract. + e1.msg.sender == currentAdmin && + sinvoke getMarketListedREMOVE_ME(e2, asset) && + // 0.9 * 1e18: 9e17 + newCollateralFactor > 0 && + newCollateralFactor <= 900000000000000000 && + sinvoke oracle(e2) > 0 && + result == 0 && + sinvoke getCollateralFactorREMOVE_ME(e2, asset) == newCollateralFactor + ) + || + ( + // Succeed if sender is admin, market listed, newCollateralFactor == 0 + e1.msg.sender == currentAdmin && + sinvoke getMarketListedREMOVE_ME(e2, asset) && + newCollateralFactor == 0 && + result == 0 && + sinvoke getCollateralFactorREMOVE_ME(e2, asset) == newCollateralFactor + ) + || + ( + // fail if listed and newCollateralFactor > 0 but not too high but no oracle has been set + e1.msg.sender == currentAdmin && + sinvoke getMarketListedREMOVE_ME(e2, asset) && + // 0.9 * 1e18: 9e17 + newCollateralFactor > 0 && + newCollateralFactor <= 900000000000000000 && + sinvoke oracle(e2) == 0 && + result == 23 && // ZERO_ORACLE_ADDRESS + sinvoke getCollateralFactorREMOVE_ME(e2, asset) == currentCollateralFactor + ) + ); +} \ No newline at end of file diff --git a/spec/formal/borrowAndRepayFresh.cvl b/spec/formal/borrowAndRepayFresh.cvl new file mode 100644 index 000000000..bf48f8106 --- /dev/null +++ b/spec/formal/borrowAndRepayFresh.cvl @@ -0,0 +1,257 @@ +methods { + totalSupply() returns uint256 + totalBorrows() returns uint256 + totalReserves() returns uint256 + + balanceOf(address) returns uint256 + borrowBalanceStored(address) returns uint256 + exchangeRateStored() returns uint256 + + getCash() returns uint256 + getCashOf(address) returns uint256 // not part of API + + borrowFreshPub(address, uint256) returns uint256 + repayBorrowFreshPub(address, address, uint256) returns uint256 + + checkTransferInPub(address,uint256) returns uint256 + doTransferInPubSim(address,uint256) returns uint256 +} + +borrowFresh(uint result, address borrower, uint256 borrowAmount) +description "Break borrow with result=$result borrower=$borrower borrowAmount=$borrowAmount" { + // Pre/action/post environments + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Any other account + address other; havoc other; + static_require other != borrower && other != currentContract; + + /* + - exchange rate should not change + - errors should have no effect + - no *other* storage should change - XXX can we specify this? + + |----------+--------+----------+-------| + | | CToken | Borrower | Other | + |----------+--------+----------+-------| + | cash | -A | +A | 0 | + | borrows | +A | +A | 0 | + | tokens | 0 | 0 | 0 | + | reserves | 0 | | | + |----------+--------+----------+-------| + */ + + /* Pre */ + + uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); + + uint256 cTokenCashPre = sinvoke getCash(e0); + uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); + uint256 otherCashPre = sinvoke getCashOf(e0, other); + + uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); + uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); + uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); + + uint256 cTokenTokensPre = sinvoke totalSupply(e0); + uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); + uint256 otherTokensPre = sinvoke balanceOf(e0, other); + + uint256 cTokenReservesPre = sinvoke totalReserves(e0); + + // Just Do It + static_require result == invoke borrowFreshPub(e1, borrower, borrowAmount); + bool borrowFreshReverted = lastReverted; + + /* Post */ + + uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); + + uint256 cTokenCashPost = sinvoke getCash(e2); + uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); + uint256 otherCashPost = sinvoke getCashOf(e2, other); + + uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); + uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); + uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); + + uint256 cTokenTokensPost = sinvoke totalSupply(e2); + uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); + uint256 otherTokensPost = sinvoke balanceOf(e2, other); + + uint256 cTokenReservesPost = sinvoke totalReserves(e2); + + // Measure + bool staticBalance = + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (borrowerCashPost == borrowerCashPre) && + (borrowerBorrowsPost == borrowerBorrowsPre) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + bool dynamicBalance = + (borrowAmount != 0) && + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre - borrowAmount) && + (cTokenBorrowsPost == cTokenBorrowsPre + borrowAmount) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (borrowerCashPost == borrowerCashPre + borrowAmount) && + (borrowerBorrowsPost == borrowerBorrowsPre + borrowAmount) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + // XXX would be nice to pull named enums from actual contract? + static_assert (!borrowFreshReverted => + ((result != 0 || borrowAmount == 0) <=> staticBalance)), "Mismatch in static case"; + static_assert (!borrowFreshReverted => + ((result == 0 && borrowAmount != 0 && borrower != currentContract) <=> dynamicBalance)), "Mismatch in dynamic case"; +} + +repayBorrowFresh(uint result, address payer, address borrower, uint256 repayAmount) +description "Break repay borrow with realRepayAmount=$realRepayAmount borrowerBorrowsPre=$borrowerBorrowsPre" { + // Pre/action/post environments + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Any other account + address other; havoc other; + static_require other != payer && other != borrower && other != currentContract; + + // We assume this cannot happen + // OQ: should we enforce in the code such that it need not be assumed? + static_require borrower != currentContract; + + /* + |----------+--------+-------+----------+-------| + | | CToken | Payer | Borrower | Other | + |----------+--------+-------+----------+-------| + | cash | +A | -A | -A/0 | 0 | + | borrows | -A | -A/0 | -A | 0 | + | tokens | 0 | 0 | 0 | 0 | + | reserves | 0 | | | | + |----------+--------+-------+----------+-------| + */ + + /* Pre */ + + uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); + + uint256 cTokenCashPre = sinvoke getCash(e0); + uint256 payerCashPre = sinvoke getCashOf(e0, payer); + uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); + uint256 otherCashPre = sinvoke getCashOf(e0, other); + + uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); + uint256 payerBorrowsPre = sinvoke borrowBalanceStored(e0, payer); + uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); + uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); + + uint256 cTokenTokensPre = sinvoke totalSupply(e0); + uint256 payerTokensPre = sinvoke balanceOf(e0, payer); + uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); + uint256 otherTokensPre = sinvoke balanceOf(e0, other); + + uint256 cTokenReservesPre = sinvoke totalReserves(e0); + + // Just Do It + static_require result == invoke repayBorrowFreshPub(e1, payer, borrower, repayAmount); + bool repayBorrowFreshReverted = lastReverted; + + /* Post */ + + uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); + + uint256 cTokenCashPost = sinvoke getCash(e2); + uint256 payerCashPost = sinvoke getCashOf(e2, payer); + uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); + uint256 otherCashPost = sinvoke getCashOf(e2, other); + + uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); + uint256 payerBorrowsPost = sinvoke borrowBalanceStored(e2, payer); + uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); + uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); + + uint256 cTokenTokensPost = sinvoke totalSupply(e2); + uint256 payerTokensPost = sinvoke balanceOf(e2, payer); + uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); + uint256 otherTokensPost = sinvoke balanceOf(e2, other); + + uint256 cTokenReservesPost = sinvoke totalReserves(e2); + + // Measure + bool staticBalance = + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (payerCashPost == payerCashPre) && + (payerBorrowsPost == payerBorrowsPre) && + (payerTokensPost == payerTokensPre) && + (borrowerCashPost == borrowerCashPre) && + (borrowerBorrowsPost == borrowerBorrowsPre) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + // XXX more convenient way to represent uint max? + uint256 UINT_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + uint256 realRepayAmount; + static_require + ((repayAmount == UINT_MAX) => + (realRepayAmount == borrowerBorrowsPre)) && + ((repayAmount != UINT_MAX) => + (realRepayAmount == repayAmount)); + + uint256 payerBorrowsExpected; + uint256 borrowerCashExpected; + static_require + ((payer == borrower) => + (payerBorrowsExpected == payerBorrowsPre - realRepayAmount) && + (borrowerCashExpected == borrowerCashPre - realRepayAmount)) && + ((payer != borrower) => + (payerBorrowsExpected == payerBorrowsPre) && + (borrowerCashExpected == borrowerCashPre)); + + bool dynamicBalance = + (realRepayAmount != 0) && + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre + realRepayAmount) && + (cTokenBorrowsPost == cTokenBorrowsPre - realRepayAmount) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (payerCashPost == payerCashPre - realRepayAmount) && + (payerBorrowsPost == payerBorrowsExpected) && + (payerTokensPost == payerTokensPre) && + (borrowerCashPost == borrowerCashExpected) && + (borrowerBorrowsPost == borrowerBorrowsPre - realRepayAmount) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + // XXX would be nice to pull named enums from actual contract? + static_assert (!repayBorrowFreshReverted => + ((result != 0 || realRepayAmount == 0) <=> staticBalance)), "Mismatch in static case"; + static_assert (!repayBorrowFreshReverted => + ((result == 0 && realRepayAmount != 0 && payer != currentContract) <=> dynamicBalance)), "Mismatch in dynamic case"; +} diff --git a/spec/formal/compound.cvl b/spec/formal/compound.cvl new file mode 100644 index 000000000..eafe86ae9 --- /dev/null +++ b/spec/formal/compound.cvl @@ -0,0 +1,266 @@ +methods { +// taken from solc --hashes. Need to add "returns" +/*e9c714f2: */ _acceptAdmin() returns uint256 +/*5cf756d2: */ _setMarketInterestRateModel(address,address) returns uint256 +/*d9226ced: */ _setMaxAssets(uint256) returns uint256 +/*3be59443: */ _setOracle(address) returns uint256 +/*24021127: */ _setOriginationFee(uint256) returns uint256 +/*26617c28: */ _setPaused(bool) returns uint256 +/*b71d1a0c: */ _setPendingAdmin(address) returns uint256 +/*c365a646: */ _setRiskParameters(uint256,uint256) returns uint256 +/*c1abfaa3: */ _supportMarket(address,address) returns uint256 +/*dbe2bc84: */ _suspendMarket(address) returns uint256 +/*f851a440: */ admin() returns address +/*5e9a523c: */ assetPrices(address) returns uint256 +/*4b8a3529: */ borrow(address,uint256) returns uint256 +/*fc7d42d7: */ borrowBalances(address,address) returns uint256 +/*9f180cf1: */ calculateAccountValues(address) // TODO: returns (uint256, uint256, uint256) +/*beb54615: */ collateralMarkets(uint256) returns address +/*b4eae1cb: */ collateralRatio() returns uint256 +/*5ec88c79: */ getAccountLiquidity(address) // TODO: returns int256 +/*118e31b7: */ getBorrowBalance(address,address) returns uint256 +/*6e2ede03: */ getCollateralMarketsLength() returns uint256 +/*ba377731: */ getSupplyBalance(address,address) returns uint256 +/*e61604cf: */ liquidateBorrow(address,address,address,uint256) returns uint256 +/*8053fcbe: */ liquidationDiscount() returns uint256 +/*8e8f294b: */ markets(address) // TODO: returns market tuple +/*94b2294b: */ maxAssets() returns uint256 +/*7dc0d1d0: */ oracle() returns address +/*b8bb5c42: */ originationFee() returns uint256 +/*5c975abb: */ paused() // TODO: returns bool +/*26782247: */ pendingAdmin() returns address +/*abdb5ea8: */ repayBorrow(address,uint256) returns uint256 +/*f2b9fdb8: */ supply(address,uint256) returns uint256 +/*b7adddac: */ supplyBalances(address,address) returns uint256 +/*f3fef3a3: */ withdraw(address,uint256) returns uint256 +} + +_setOriginationFee(uint currentAdmin, uint currentFee, uint newOriginationFee) +description "Failed to set origination fee from $currentFee to $newOriginationFee (admin=$currentAdmin)" { + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + // Capture current admin and origination fee + static_require currentAdmin == sinvoke admin(e0); + static_require currentFee == sinvoke originationFee(e0); + + // Invoke set origination fee + uint256 result = sinvoke _setOriginationFee(e1, newOriginationFee); + + // originationFee changes <=> msg.sender == currentAdmin + static_assert ( + ( + e1.msg.sender == currentAdmin && + result == 0 && + sinvoke originationFee(e2) == newOriginationFee + ) + || + ( + e1.msg.sender != currentAdmin && + result != 0 && + sinvoke originationFee(e2) == currentFee + ) + ); +} + +_setPendingAdmin(address currentAdmin, address currentPendingAdmin, address newPendingAdmin) +description "Failed to set new pending admin $currentPendingAdmin to $newPendingAdmin (admin=$currentAdmin)" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require currentAdmin == sinvoke admin(e0); + static_require currentPendingAdmin == sinvoke pendingAdmin(e0); + + // Invoke set new pending admin + uint256 result = sinvoke _setPendingAdmin(e1, newPendingAdmin); + + // pendingAdmin changes <=> msg.sender == currentAdmin + static_assert ( + ( + e1.msg.sender == currentAdmin && + result == 0 && + sinvoke pendingAdmin(e2) == newPendingAdmin + ) + || + ( + e1.msg.sender != currentAdmin && + result != 0 && + sinvoke pendingAdmin(e2) == currentPendingAdmin + ) + ); +} + +_acceptAdmin(address currentAdmin, address currentPendingAdmin, address newAdmin, address newPendingAdmin) +description "Failed to accept pending admin currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, newPendingAdmin=$newPendingAdmin, newAdmin=$newAdmin" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require currentAdmin == sinvoke admin(e0); + static_require currentPendingAdmin == sinvoke pendingAdmin(e0); + + // Invoke accept admin + uint256 result = sinvoke _acceptAdmin(e1); + + static_require newAdmin == sinvoke admin(e2); + static_require newPendingAdmin == sinvoke pendingAdmin(e2); + + // admin == pendingAdmin <=> msg.sender == pendingAdmin + static_assert ( + ( + e1.msg.sender == currentPendingAdmin && + currentPendingAdmin != 0 && + result == 0 && + newAdmin == currentPendingAdmin && + newPendingAdmin == 0 + ) + || + ( + ( + e1.msg.sender != currentPendingAdmin || + currentPendingAdmin == 0 + ) && + result != 0 && + newAdmin == currentAdmin && + newPendingAdmin == currentPendingAdmin + ) + ); +} + +// Invariant: To change admin or currentPendingAdmin, must come from current admin +invariantRequireAdminToChangeAdmin(address caller, address currentAdmin, address currentPendingAdmin, address desiredAdmin, address newAdmin, address newPendingAdmin) +description "Failed to prove that required to be admin to change admin (caller=$caller, currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, desiredAdmin=$desiredAdmin, newAdmin=$newAdmin, newPendingAdmin=$newPendingAdmin)" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + env e3; havoc e3; + + // Strict ordering (TODO: Can e2.block == e1.block?) + static_require e1.block > e0.block; + static_require e2.block > e1.block; + static_require e3.block > e2.block; + + static_require currentAdmin == sinvoke admin(e0); + static_require currentPendingAdmin == sinvoke pendingAdmin(e0); + + // Start with a zero admin + static_require currentPendingAdmin == 0; + + static_require caller == e1.msg.caller; + + // Invoke set new pending admin + uint256 result0 = sinvoke _setPendingAdmin(e1, desiredAdmin); + uint256 result1 = sinvoke _acceptAdmin(e2); + + static_require newAdmin == sinvoke admin(e3); + static_require newPendingAdmin == sinvoke pendingAdmin(e3); + + static_assert ( + e1.msg.sender == currentAdmin || + ( + newAdmin == currentAdmin && + newPendingAdmin == currentPendingAdmin + ) + ); +} + +_setOracle(address sender, address currAdmin, address currOracle, address desiredOracle, address nextOracle) +description "Failed to set oracle (sender=$sender, currAdmin=$currAdmin, currOracle=$currOracle, desiredOracle=$desiredOracle, nextOracle=$nextOracle)" { + // N.B. This merely havocs `oracleInterface.assetPrices(address(0))` + // and does not check or concern itself with the result. + + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require currAdmin == sinvoke admin(e0); + static_require currOracle == sinvoke oracle(e0); + + static_require sender == e1.msg.sender; + + // Invoke set new pending admin + uint256 result = sinvoke _setOracle(e1, desiredOracle); + + static_require nextOracle == sinvoke oracle(e2); + + // nextOracle == desiredOracle <=> msg.sender == admin + static_assert ( + ( + sender == currAdmin && + result == 0 && + nextOracle == desiredOracle + ) + || + ( + sender != currAdmin && + result != 0 && + ( + // It's possible that we're trying to set + // it to what it previously was. This is + // really the same as "succeeding," since + // it does become (remain) what you set it to. + desiredOracle == currOracle || + nextOracle != desiredOracle + ) + ) + ); +} + +_setMaxAssets(address currentAdmin, uint newMaxAssets, uint oldMaxAssets) +description "Failed to set new maxAssets admin: $currentAdmin, new: $newMaxAssets, old: $old" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require oldMaxAssets == sinvoke maxAssets(e0); + static_require currentAdmin == sinvoke admin(e0); + + // Invoke set new max assets + uint256 result = sinvoke _setMaxAssets(e1, newMaxAssets); + + static_assert ( + ( + e1.msg.sender == currentAdmin && + result == 0 && + sinvoke maxAssets(e2) == newMaxAssets + ) + || + ( + e1.msg.sender != currentAdmin && + result != 0 && + sinvoke maxAssets(e2) == oldMaxAssets + ) + ); +} diff --git a/spec/formal/contracts/CErc20Certora.sol b/spec/formal/contracts/CErc20Certora.sol new file mode 100644 index 000000000..ba4fa5c18 --- /dev/null +++ b/spec/formal/contracts/CErc20Certora.sol @@ -0,0 +1,164 @@ +pragma solidity ^0.5.8; + +import "../../../contracts/CErc20.sol"; +import "../../../contracts/EIP20Interface.sol"; + +import "./CTokenCollateral.sol"; +import "./SimulationInterface.sol"; + +contract CErc20Certora is CErc20 { + CTokenCollateral public otherToken; + + constructor(address underlying_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa_, + string memory name_, + string memory symbol_, + uint decimals_) public CErc20(underlying_, comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_) { + } + + function comptrollerMintAllowed(address currentContract, address minter, uint mintAmount) public returns (uint) { + return comptroller.mintAllowed(currentContract, minter, mintAmount); + } + + function comptrollerRedeemAllowed(address currentContract, address minter, uint mintAmount) public returns (uint) { + return comptroller.redeemAllowed(currentContract, minter, mintAmount); + } + + function exchangeRateStoredInternalPub() public view returns (MathError, uint) { + return exchangeRateStoredInternal(); + } + + function cTokenMintComputation(uint mintAmount) public returns (uint) { + MathError mathErr; + uint exchangeRateMantissa; + uint mintTokens; + + (mathErr, exchangeRateMantissa) = exchangeRateStoredInternal(); + require (mathErr == MathError.NO_ERROR); + + (mathErr, mintTokens) = divScalarByExpTruncate(mintAmount, Exp({mantissa: exchangeRateMantissa})); + require (mathErr == MathError.NO_ERROR); + + return mintTokens; + } + + function cTokenRedeemComputation(uint redeemTokens) public returns (uint) { + MathError mathErr; + uint exchangeRateMantissa; + uint redeemAmount; + + (mathErr, exchangeRateMantissa) = exchangeRateStoredInternal(); + require (mathErr == MathError.NO_ERROR); + + (mathErr, redeemAmount) = mulScalarTruncate(Exp({mantissa: exchangeRateMantissa}), redeemTokens); + require (mathErr == MathError.NO_ERROR); + + return redeemAmount; + } + + function checkTransferInPub(address from, uint amount) public view returns (uint) { + return uint(checkTransferIn(from,amount)); + } + + function doTransferInPub(address from, uint amount) public returns (uint) { + return uint(doTransferIn(from,amount)); + } + + function simulateUnderlying(uint expectedError) internal returns (uint) { + SimulationInterface token = SimulationInterface(underlying); + bool result; + + token.dummy(); + + // solium-disable-next-line security/no-inline-assembly + assembly { + switch returndatasize() + case 0 { // This is a non-standard ERC-20 + result := not(0) // set result to true + } + case 32 { // This is a complaint ERC-20 + returndatacopy(0, 0, 32) + result := mload(0) // Set `result = returndata` of external call + } + default { // This is an excessively non-compliant ERC-20, revert. + revert(0, 0) + } + } + + if (!result) { + return expectedError; + } + + return uint(Error.NO_ERROR); + } + + function doTransferInPubSim(address from, uint amount) public returns (uint) { + return simulateUnderlying(uint(Error.TOKEN_TRANSFER_IN_FAILED)); + } + + function doTransferOutPub(address payable to, uint amount) public returns (uint) { + return uint(doTransferOut(to, amount)); + } + + function doTransferOutPubSim(address payable to, uint amount) public returns (uint) { + return simulateUnderlying(uint(Error.TOKEN_TRANSFER_OUT_FAILED)); + } + + function balanceOfInOther(address account) public view returns (uint) { + return otherToken.balanceOf(account); + } + + function borrowBalanceStoredInOther(address account) public view returns (uint) { + return otherToken.borrowBalanceStored(account); + } + + function exchangeRateStoredInOther() public view returns (uint) { + return otherToken.exchangeRateStored(); + } + + function getCashInOther() public view returns (uint) { + return otherToken.getCash(); + } + + function getCashOf(address account) public view returns (uint) { + return EIP20Interface(underlying).balanceOf(account); + } + + function getCashOfInOther(address account) public view returns (uint) { + return otherToken.getCashOf(account); + } + + function totalSupplyInOther() public view returns (uint) { + return otherToken.totalSupply(); + } + + function totalBorrowsInOther() public view returns (uint) { + return otherToken.totalBorrows(); + } + + function totalReservesInOther() public view returns (uint) { + return otherToken.totalReserves(); + } + + function mintFreshPub(address minter, uint mintAmount) public returns (uint) { + return mintFresh(minter, mintAmount); + } + + function redeemFreshPub(address payable redeemer, uint redeemTokens, uint redeemUnderlying) public returns (uint) { + return redeemFresh(redeemer, redeemTokens, redeemUnderlying); + } + + function borrowFreshPub(address payable borrower, uint borrowAmount) public returns (uint) { + return borrowFresh(borrower, borrowAmount); + } + + function repayBorrowFreshPub(address payer, address borrower, uint repayAmount) public returns (uint) { + return repayBorrowFresh(payer, borrower, repayAmount); + } + + function liquidateBorrowFreshPub(address liquidator, address borrower, uint repayAmount) public returns (uint) { + return liquidateBorrowFresh(liquidator, borrower, repayAmount, otherToken); + } +} diff --git a/spec/formal/contracts/CEtherCertora.sol b/spec/formal/contracts/CEtherCertora.sol new file mode 100644 index 000000000..f6e8a6dd6 --- /dev/null +++ b/spec/formal/contracts/CEtherCertora.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.5.8; + +import "../../../contracts/CEther.sol"; + +contract CEtherCertora is CEther { + constructor(ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa_, + string memory name_, + string memory symbol_, + uint decimals_) public CEther(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_) { + } +} diff --git a/spec/formal/contracts/CTokenCollateral.sol b/spec/formal/contracts/CTokenCollateral.sol new file mode 100644 index 000000000..19e4957bb --- /dev/null +++ b/spec/formal/contracts/CTokenCollateral.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.5.8; + +import "../../../contracts/CErc20.sol"; +import "../../../contracts/EIP20Interface.sol"; + +contract CTokenCollateral is CErc20 { + constructor(address underlying_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa_, + string memory name_, + string memory symbol_, + uint decimals_) public CErc20(underlying_, comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_) { + } + + function getCashOf(address account) public view returns (uint) { + return EIP20Interface(underlying).balanceOf(account); + } +} diff --git a/spec/formal/contracts/ComptrollerModel.sol b/spec/formal/contracts/ComptrollerModel.sol new file mode 100644 index 000000000..7586e0edd --- /dev/null +++ b/spec/formal/contracts/ComptrollerModel.sol @@ -0,0 +1,100 @@ +pragma solidity ^0.5.8; + +import "../../../contracts/CToken.sol"; + +contract ComptrollerModel { + uint mintAllowedResult; + uint redeemAllowedResult; + uint borrowAllowedResult; + uint repayBorrowAllowedResult; + uint liquidateBorrowAllowedResult; + uint seizeAllowedResult; + uint transferAllowedResult; + uint liquidateCalculateSeizeTokensResult1; + uint liquidateCalculateSeizeTokensResult2; + + + function mintAllowed(CToken cToken, address minter, uint mintAmount) public returns (uint) { + return mintAllowedResult; + } + + function mintVerify(CToken cToken, address minter, uint mintAmount, uint mintTokens) external {} + + + function redeemAllowed(CToken cToken, address redeemer, uint redeemTokens) public returns (uint) { + return redeemAllowedResult; + } + + function redeemVerify(CToken cToken, address redeemer, uint redeemAmount, uint redeemTokens) external {} + + + function borrowAllowed(CToken cToken, address borrower, uint borrowAmount) public returns (uint) { + return borrowAllowedResult; + } + + function borrowVerify(CToken cToken, address borrower, uint borrowAmount) external {} + + + function repayBorrowAllowed( + address cToken, + address payer, + address borrower, + uint repayAmount) external returns (uint) { + return repayBorrowAllowedResult; + } + + function repayBorrowVerify( + address cToken, + address payer, + address borrower, + uint repayAmount, + uint borrowerIndex) external {} + + + function liquidateBorrowAllowed( + address cTokenBorrowed, + address cTokenCollateral, + address liquidator, + address borrower, + uint repayAmount) external returns (uint) { + return liquidateBorrowAllowedResult; + } + + function liquidateBorrowVerify( + address cTokenBorrowed, + address cTokenCollateral, + address liquidator, + address borrower, + uint repayAmount, + uint seizeTokens) external {} + + + function seizeAllowed( + address cTokenCollateral, + address cTokenBorrowed, + address liquidator, + address borrower, + uint seizeTokens) external returns (uint) { + return seizeAllowedResult; + } + + function seizeVerify( + address cTokenCollateral, + address cTokenBorrowed, + address liquidator, + address borrower, + uint seizeTokens) external {} + + function transferAllowed(address cToken, address src, address dst, uint transferTokens) external returns (uint) { + return transferAllowedResult; + } + + function transferVerify(address cToken, address src, address dst, uint transferTokens) external {} + + function liquidateCalculateSeizeTokens( + address cTokenBorrowed, + address cTokenCollateral, + uint repayAmount) external view returns (uint, uint) { + return (liquidateCalculateSeizeTokensResult1, liquidateCalculateSeizeTokensResult2); + } +} \ No newline at end of file diff --git a/spec/formal/contracts/MaximillionCertora.sol b/spec/formal/contracts/MaximillionCertora.sol new file mode 100644 index 000000000..4037e92db --- /dev/null +++ b/spec/formal/contracts/MaximillionCertora.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.5.8; + +import "../../../contracts/Maximillion.sol"; + +contract MaximillionCertora is Maximillion { + constructor(CEther cEther_) public Maximillion(cEther_) {} + + function borrowBalance(address account) external returns (uint) { + return cEther.borrowBalanceCurrent(account); + } + + function etherBalance(address account) external returns (uint) { + return account.balance; + } + + function repayBehalf(address borrower) public payable { + return super.repayBehalf(borrower); + } +} \ No newline at end of file diff --git a/spec/formal/contracts/SimulationInterface.sol b/spec/formal/contracts/SimulationInterface.sol new file mode 100644 index 000000000..91af008d3 --- /dev/null +++ b/spec/formal/contracts/SimulationInterface.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.5.8; + +interface SimulationInterface { + function dummy() external; +} diff --git a/spec/formal/contracts/UnderlyingModelNonStandard.sol b/spec/formal/contracts/UnderlyingModelNonStandard.sol new file mode 100644 index 000000000..d8c27522b --- /dev/null +++ b/spec/formal/contracts/UnderlyingModelNonStandard.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.5.8; + +import "../../../contracts/EIP20NonStandardInterface.sol"; + +import "./SimulationInterface.sol"; + +contract UnderlyingModelNonStandard is EIP20NonStandardInterface, SimulationInterface { + uint256 _totalSupply; + mapping (address => uint256) balances; + mapping (address => mapping (address => uint256)) allowances; + + function totalSupply() external view returns (uint256) { + return _totalSupply; + } + + /** + * @notice Gets the balance of the specified address + * @param owner The address from which the balance will be retrieved + * @return The balance + */ + function balanceOf(address owner) external view returns (uint256 balance) { + balance = balances[owner]; + } + + function transfer(address dst, uint256 amount) external { + address src = msg.sender; + require (balances[src]>=amount); + require (balances[dst]+amount>=balances[dst]); + + balances[src] -= amount; + balances[dst] += amount; + } + + function transferFrom(address src, address dst, uint256 amount) external { + require (allowances[src][msg.sender] >= amount); + require (balances[src]>=amount); + require (balances[dst]+amount>=balances[dst]); + + allowances[src][msg.sender] -= amount; + balances[src] -= amount; + balances[dst] += amount; + } + + function approve(address spender, uint256 amount) external returns (bool success) { + allowances[msg.sender][spender] = amount; + } + + function allowance(address owner, address spender) external view returns (uint256 remaining) { + remaining = allowances[owner][spender]; + } + + function dummy() external { + return; + } +} \ No newline at end of file diff --git a/spec/formal/dummy.cvl b/spec/formal/dummy.cvl new file mode 100644 index 000000000..82ccf67ed --- /dev/null +++ b/spec/formal/dummy.cvl @@ -0,0 +1 @@ +// hello diff --git a/spec/formal/eip20.cvl b/spec/formal/eip20.cvl new file mode 100644 index 000000000..e5654d78a --- /dev/null +++ b/spec/formal/eip20.cvl @@ -0,0 +1,154 @@ +methods { + totalSupply() returns uint256 + totalBorrows() returns uint256 + totalReserves() returns uint256 + + balanceOf(address) returns uint256 + borrowBalanceStored(address) returns uint256 + exchangeRateStored() returns uint256 + + getCash() returns uint256 + getCashOf(address) returns uint256 // not part of API + + allowance(address, address) returns uint256 + approve(address, uint256) returns bool + transferFrom(address, address, uint256) returns bool +} + +transferFrom(bool success, address src, address dst, uint256 amount) +description "Break transferFrom" { + // Pre/action/post environments + env e0; havoc e0; + env e1a; havoc e1a; + env e1b; havoc e1b; + env e2; havoc e2; + + static_require e1a.block.number >= e0.block.number; + static_require e1b.block.number >= e1a.block.number; + static_require e2.block.number >= e1b.block.number; + + // Any other account + address other; havoc other; + static_require other != src && other != dst; + + /* + - no effect on exchange rate + - no more than approved + |----------+--------+-----+-----+-------| + | | CToken | Src | Dst | Other | + |----------+--------+-----+-----+-------| + | cash | 0 | 0 | 0 | 0 | + | borrows | 0 | 0 | 0 | 0 | + | tokens | 0 | -T | +T | 0 | + | reserves | 0 | | | | + |----------+--------+-----+-----+-------| + */ + + /* Pre */ + + uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); + + uint256 cTokenCashPre = sinvoke getCash(e0); + uint256 srcCashPre = sinvoke getCashOf(e0, src); + uint256 dstCashPre = sinvoke getCashOf(e0, dst); + uint256 otherCashPre = sinvoke getCashOf(e0, other); + + uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); + uint256 srcBorrowsPre = sinvoke borrowBalanceStored(e0, src); + uint256 dstBorrowsPre = sinvoke borrowBalanceStored(e0, dst); + uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); + + uint256 cTokenSupplyPre = sinvoke totalSupply(e0); + uint256 srcTokensPre = sinvoke balanceOf(e0, src); + uint256 dstTokensPre = sinvoke balanceOf(e0, dst); + uint256 otherTokensPre = sinvoke balanceOf(e0, other); + + uint256 cTokenReservesPre = sinvoke totalReserves(e0); + + // Approve + bool doApprove; havoc doApprove; + uint256 approvedAmount; havoc approvedAmount; + if (doApprove) { + static_require e1a.msg.sender == src; + sinvoke approve(e1a, e1b.msg.sender, approvedAmount); + } else {} + + uint256 allowancePre = sinvoke allowance(e1a, src, e1b.msg.sender); + + // Just Do It + static_require success == invoke transferFrom(e1b, src, dst, amount); + bool transferReverted = lastReverted; + + /* Post */ + + uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); + + uint256 cTokenCashPost = sinvoke getCash(e2); + uint256 srcCashPost = sinvoke getCashOf(e2, src); + uint256 dstCashPost = sinvoke getCashOf(e2, dst); + uint256 otherCashPost = sinvoke getCashOf(e2, other); + + uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); + uint256 srcBorrowsPost = sinvoke borrowBalanceStored(e2, src); + uint256 dstBorrowsPost = sinvoke borrowBalanceStored(e2, dst); + uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); + + uint256 cTokenSupplyPost = sinvoke totalSupply(e2); + uint256 srcTokensPost = sinvoke balanceOf(e2, src); + uint256 dstTokensPost = sinvoke balanceOf(e2, dst); + uint256 otherTokensPost = sinvoke balanceOf(e2, other); + + uint256 cTokenReservesPost = sinvoke totalReserves(e2); + + uint256 allowancePost = sinvoke allowance(e2, src, e1b.msg.sender); + + // Measure + bool staticBalance = + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenSupplyPost == cTokenSupplyPre) && + (cTokenReservesPost == cTokenReservesPre) && + (srcCashPost == srcCashPre) && + (srcBorrowsPost == srcBorrowsPre) && + (srcTokensPost == srcTokensPre) && + (dstCashPost == dstCashPre) && + (dstBorrowsPost == dstBorrowsPre) && + (dstTokensPost == dstTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + bool dynamicBalance = + (amount != 0) && + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenSupplyPost == cTokenSupplyPre) && + (cTokenReservesPost == cTokenReservesPre) && + (srcCashPost == srcCashPre) && + (srcBorrowsPost == srcBorrowsPre) && + (srcTokensPost == srcTokensPre - amount) && + (dstCashPost == dstCashPre) && + (dstBorrowsPost == dstBorrowsPre) && + (dstTokensPost == dstTokensPre + amount) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + // XXX better way to write uint max? + uint256 UINT_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + static_assert (!transferReverted => + ((!success || amount == 0 || src == dst) <=> staticBalance)), "Mismatch in static case"; + static_assert (!transferReverted => + ((success && amount != 0) <=> dynamicBalance)), "Mismatch in dynamic case"; + static_assert (!transferReverted && success => + (amount > allowancePre => e1b.msg.sender == src)), "Only owner can transfer > allowance"; + static_assert (!transferReverted && success => + (doApprove => allowancePre >= approvedAmount)), "Approval must increase the allowance"; + static_assert (!transferReverted && success => + (allowancePre == UINT_MAX || e1b.msg.sender == src || amount == 0) <=> allowancePost == allowancePre), "Mismatch not touching allowance"; + static_assert (!transferReverted && success && e1b.msg.sender != src && amount != 0 => + (allowancePre != UINT_MAX <=> allowancePost == allowancePre - amount)), "Spender transfer uses allowance"; +} \ No newline at end of file diff --git a/spec/formal/frame.cvl b/spec/formal/frame.cvl new file mode 100644 index 000000000..877ae3393 --- /dev/null +++ b/spec/formal/frame.cvl @@ -0,0 +1,359 @@ +methods { +/*70a08231:*/ balanceOf(address) returns uint256 +/*95dd9193:*/ borrowBalanceStored(address) returns uint256 +/*aa5af0fd:*/ borrowIndex() returns uint256 +/*f8f9da28:*/ borrowRatePerBlock() returns uint256 +/*5fe3b567:*/ comptroller() returns address +/*182df0f5:*/ exchangeRateStored() returns uint256 +/*c37f68e2:*/ getAccountSnapshot(address) returns uint256,uint256,uint256,uint256 +/*3b1d21a2:*/ getCash() returns uint256 +/*675d972c:*/ initialExchangeRateMantissa() returns uint256 +/*f3fdb15a:*/ interestRateModel() returns address +/*fe9c44ae:*/ isCToken() returns bool +/*26782247:*/ pendingAdmin() returns address +/*173b9904:*/ reserveFactorMantissa() returns uint256 +/*ae9d70b0:*/ supplyRatePerBlock() returns uint256 +/*47bd3718:*/ totalBorrows() returns uint256 +/*8f840ddd:*/ totalReserves() returns uint256 +/*18160ddd:*/ totalSupply() returns uint256 + + +// all other methods +/*e9c714f2:*/ _acceptAdmin() +/*601a0bf1:*/ _reduceReserves(uint256) +/*4576b5db:*/ _setComptroller(address) +/*f2b3abbd:*/ _setInterestRateModel(address) +/*b71d1a0c:*/ _setPendingAdmin(address) +/*fca7820b:*/ _setReserveFactor(uint256) +/*6c540baf:*/ accrualBlockNumber() +/*a6afed95:*/ accrueInterest() +/*f851a440:*/ admin() +/*dd62ed3e:*/ allowance(address,address) +/*095ea7b3:*/ approve(address,uint256) +/*3af9e669:*/ balanceOfUnderlying(address) +/*c5ebeaec:*/ borrow(uint256) +/*17bfdfbc:*/ borrowBalanceCurrent(address) +/*0bc1d628:*/ borrowFreshPub(address,uint256) +/*5d2b2256:*/ cTokenMintComputation(uint256) +/*f1651460:*/ cTokenRedeemComputation(uint256) +/*b8b8b26b:*/ checkTransferInPub(address,uint256) +/*d9d9e5e5:*/ comptrollerMintAllowed(address,address,uint256) +/*92ac96fa:*/ comptrollerRedeemAllowed(address,address,uint256) +/*313ce567:*/ decimals() +/*19ec23ba:*/ doTransferInPub(address,uint256) +/*f782def5:*/ doTransferInPubSim(address,uint256) +/*b5d229bb:*/ doTransferOutPub(address,uint256) +/*18628ce7:*/ doTransferOutPubSim(address,uint256) +/*bd6d894d:*/ exchangeRateCurrent() +/*934213e8:*/ exchangeRateStoredInternalPub() +/*f414bbaf:*/ getCashOf(address) +/*5b1c10f6:*/ getCashPub() +/*529ca4b7:*/ interestRateModelGetBorrowRate() +/*f5e3c462:*/ liquidateBorrow(address,uint256,address) +/*a0712d68:*/ mint(uint256) +/*c9645990:*/ mintFreshPub(address,uint256) +/*06fdde03:*/ name() +/*db006a75:*/ redeem(uint256) +/*8c1a1b80:*/ redeemFreshPub(address,uint256,uint256) +/*852a12e3:*/ redeemUnderlying(uint256) +/*0e752702:*/ repayBorrow(uint256) +/*2608f818:*/ repayBorrowBehalf(address,uint256) +/*7a6a0162:*/ repayBorrowFreshPub(address,address,uint256) +/*b2a02ff1:*/ seize(address,address,uint256) +/*95d89b41:*/ symbol() +/*73acee98:*/ totalBorrowsCurrent() +/*a9059cbb:*/ transfer(address,uint256) +/*23b872dd:*/ transferFrom(address,address,uint256) +/*6f307dc3:*/ underlying() +} + +frame_balanceOf(address a, method f) +description "$f may change value of balanceOf($a)" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke balanceOf(e0, a); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke balanceOf(e2, a); + + static_assert old == new; +} + +frame_borrowBalanceStored(address a, method f) +description "$f may change value of borrowBalanceStored($a)" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke borrowBalanceStored(e0, a); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke borrowBalanceStored(e2, a); + + static_assert old == new; +} + +frame_borrowIndex(method f) +description "$f may change value of borrowIndex()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke borrowIndex(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke borrowIndex(e2); + + static_assert old == new; +} + +frame_borrowRatePerBlock(method f) +description "$f may change value of borrowRatePerBlock()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke borrowRatePerBlock(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke borrowRatePerBlock(e2); + + static_assert old == new; +} + +frame_comptroller(method f) +description "$f may change value of comptroller()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + address old = sinvoke comptroller(e0); + calldataarg arg; + invoke f(e1, arg); + address new = sinvoke comptroller(e2); + + static_assert old == new; +} + +frame_exchangeRateStored(address a, method f) +description "$f may change value of exchangeRateStored()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke exchangeRateStored(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke exchangeRateStored(e2); + + static_assert old == new; +} + +frame_getAccountSnapshot(address a, method f) +description "$f may change value of getAccountSnapshot($a)" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old1; uint256 old2; uint256 old3; uint256 old4; + old1,old2,old3,old4 = sinvoke getAccountSnapshot(e0, a); + calldataarg arg; + invoke f(e1, arg); + uint256 new1; uint256 new2; uint256 new3; uint256 new4; + new1,new2,new3,new4 = sinvoke getAccountSnapshot(e2, a); + + static_assert old1 == new1 && old2 == new2 && old3 == new3 && old4 == new4; +} + +frame_getCash(method f) +description "$f may change value of getCash()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke getCash(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke getCash(e2); + + static_assert old == new; +} + +frame_initialExchangeRateMantissa(method f) +description "$f may change value of initialExchangeRateMantissa()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke initialExchangeRateMantissa(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke initialExchangeRateMantissa(e2); + + static_assert old == new; +} + +frame_interestRateModel(method f) +description "$f may change value of interestRateModel()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + address old = sinvoke interestRateModel(e0); + calldataarg arg; + invoke f(e1, arg); + address new = sinvoke interestRateModel(e2); + + static_assert old == new; +} + +frame_isCToken(method f) +description "$f may change value of isCToken()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + bool old = sinvoke isCToken(e0); + calldataarg arg; + invoke f(e1, arg); + bool new = sinvoke isCToken(e2); + + static_assert old == new; +} + +frame_pendingAdmin(method f) +description "$f may change value of pendingAdmin()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + address old = sinvoke pendingAdmin(e0); + calldataarg arg; + invoke f(e1, arg); + address new = sinvoke pendingAdmin(e2); + + static_assert old == new; +} + +frame_reserveFactorMantissa(method f) +description "$f may change value of reserveFactorMantissa()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke reserveFactorMantissa(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke reserveFactorMantissa(e2); + + static_assert old == new; +} + +frame_supplyRatePerBlock(method f) +description "$f may change value of supplyRatePerBlock()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke supplyRatePerBlock(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke supplyRatePerBlock(e2); + + static_assert old == new; +} + +frame_totalBorrows(method f) +description "$f may change value of totalBorrows()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke totalBorrows(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke totalBorrows(e2); + + static_assert old == new; +} + +frame_totalReserves(address a, method f) +description "$f may change value of totalReserves()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke totalReserves(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke totalReserves(e2); + + static_assert old == new; +} + +frame_totalSupply(method f) +description "$f may change value of totalSupply()" +{ + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + uint256 old = sinvoke totalSupply(e0); + calldataarg arg; + invoke f(e1, arg); + uint256 new = sinvoke totalSupply(e2); + + static_assert old == new; +} \ No newline at end of file diff --git a/spec/formal/general.cvl b/spec/formal/general.cvl new file mode 100644 index 000000000..b87bb9797 --- /dev/null +++ b/spec/formal/general.cvl @@ -0,0 +1,167 @@ +methods { + _setPendingAdmin(address) returns uint256 + pendingAdmin() returns address + + _acceptAdmin() returns uint256 + admin() returns address + + _setComptroller(address) returns uint256 + comptroller() returns address +} + +_setPendingAdmin(address currentAdmin, address currentPendingAdmin, address newPendingAdmin) +description "Failed to set new pending admin $currentPendingAdmin to $newPendingAdmin (admin=$currentAdmin)" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require currentAdmin == sinvoke admin(e0); + static_require currentPendingAdmin == sinvoke pendingAdmin(e0); + + // Invoke set new pending admin + uint256 result = sinvoke _setPendingAdmin(e1, newPendingAdmin); + + // pendingAdmin changes <=> msg.sender == currentAdmin + static_assert ( + ( + e1.msg.sender == currentAdmin && + result == 0 && + sinvoke pendingAdmin(e2) == newPendingAdmin + ) + || + ( + e1.msg.sender != currentAdmin && + result != 0 && + sinvoke pendingAdmin(e2) == currentPendingAdmin + ) + ); +} + +_acceptAdmin(address currentAdmin, address currentPendingAdmin, address newAdmin, address newPendingAdmin) + description "Failed to accept pending admin currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, newPendingAdmin=$newPendingAdmin, newAdmin=$newAdmin" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require currentAdmin == sinvoke admin(e0); + static_require currentPendingAdmin == sinvoke pendingAdmin(e0); + + // Invoke accept admin + uint256 result = sinvoke _acceptAdmin(e1); + + static_require newAdmin == sinvoke admin(e2); + static_require newPendingAdmin == sinvoke pendingAdmin(e2); + + // admin == pendingAdmin <=> msg.sender == pendingAdmin + static_assert ( + ( + e1.msg.sender == currentPendingAdmin && + currentPendingAdmin != 0 && + result == 0 && + newAdmin == currentPendingAdmin && + newPendingAdmin == 0 + ) + || + ( + ( + e1.msg.sender != currentPendingAdmin || + currentPendingAdmin == 0 + ) && + result != 0 && + newAdmin == currentAdmin && + newPendingAdmin == currentPendingAdmin + ) + ); +} + +// Invariant: To change admin or currentPendingAdmin, must come from current admin +invariantRequireAdminToChangeAdmin(address caller, address currentAdmin, address currentPendingAdmin, address desiredAdmin, address newAdmin, address newPendingAdmin) + description "Failed to prove that required to be admin to change admin (caller=$caller, currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, desiredAdmin=$desiredAdmin, newAdmin=$newAdmin, newPendingAdmin=$newPendingAdmin)" +{ + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + env e3; havoc e3; + + // Strict ordering (TODO: Can e2.block == e1.block?) + static_require e1.block > e0.block; + static_require e2.block > e1.block; + static_require e3.block > e2.block; + + static_require currentAdmin == sinvoke admin(e0); + static_require currentPendingAdmin == sinvoke pendingAdmin(e0); + + // Start with a zero admin + static_require currentPendingAdmin == 0; + + static_require caller == e1.msg.caller; + + // Invoke set new pending admin + uint256 result0 = sinvoke _setPendingAdmin(e1, desiredAdmin); + uint256 result1 = sinvoke _acceptAdmin(e2); + + static_require newAdmin == sinvoke admin(e3); + static_require newPendingAdmin == sinvoke pendingAdmin(e3); + + static_assert ( + e1.msg.sender == currentAdmin || + ( + newAdmin == currentAdmin && + newPendingAdmin == currentPendingAdmin + ) + ); +} + +_setComptroller(address sender, address currAdmin, address currComptroller, address desiredComptroller, address nextComptroller) + description "Failed to set comptroller: result=$result (sender=$sender, currAdmin=$currAdmin, currComptroller=$currComptroller, desiredComptroller=$desiredComptroller, nextComptroller=$nextComptroller)" { + // N.B. This merely havocs `oracleInterface.assetPrices(address(0))` + // and does not check or concern itself with the result. + + // Free Variables + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + // Strict ordering + static_require e1.block > e0.block; + static_require e2.block > e1.block; + + static_require currAdmin == sinvoke admin(e0); + static_require currComptroller == sinvoke comptroller(e0); + + static_require sender == e1.msg.sender; + + // Invoke set new comptroller + uint256 result = sinvoke _setComptroller(e1, desiredComptroller); + + static_require nextComptroller == sinvoke comptroller(e2); + + // nextComptroller == desiredComptroller <=> msg.sender == admin + static_assert ((sender == currAdmin && + result == 0 && + nextComptroller == desiredComptroller) + || + (sender != currAdmin && + result == 1 && // UNAUTHORIZED + ( + // It's possible that we're trying to set + // it to what it previously was. This is + // really the same as "succeeding," since + // it does become (remain) what you set it to. + desiredComptroller == currComptroller || + nextComptroller != desiredComptroller + ))); +} diff --git a/spec/formal/liquidateFresh.cvl b/spec/formal/liquidateFresh.cvl new file mode 100644 index 000000000..8b8e9c5ab --- /dev/null +++ b/spec/formal/liquidateFresh.cvl @@ -0,0 +1,331 @@ +methods { + totalSupply() returns uint256 + totalSupplyInOther() returns uint256 // not part of API + totalBorrows() returns uint256 + totalBorrowsInOther() returns uint256 // not part of API + totalReserves() returns uint256 + totalReservesInOther() returns uint256 // not part of API + + balanceOf(address) returns uint256 + balanceOfInOther(address) returns uint256 // not part of API + borrowBalanceStored(address) returns uint256 + borrowBalanceStoredInOther(address) returns uint256 // not part of API + exchangeRateStored() returns uint256 + exchangeRateStoredInOther() returns uint256 // not part of API + + getCash() returns uint256 + getCashInOther() returns uint256 // not part of API + getCashOf(address) returns uint256 // not part of API + getCashOfInOther(address) returns uint256 // not part of API + + liquidateBorrowFreshPub(address, address, uint256) returns uint256 + seize(address, address, uint256) returns uint256 +} + +liquidateBorrowFresh(uint result, address liquidator, address borrower, uint256 repayAmount) +description "Break liquidate" { + // Pre/action/post environments + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Any other account + address other; havoc other; + static_require other != liquidator && other != borrower && other != currentContract; + + // We assume this cannot happen + // OQ: should we enforce in the code such that it need not be assumed? + static_require borrower != currentContract; + + /* + - no effect on exchange rate + - self-liquidate has no effect + |---------------------+--------+------------+----------+-------| + | | CToken | Liquidator | Borrower | Other | + |---------------------+--------+------------+----------+-------| + | cash | +A | -A | 0 | 0 | + | borrows | -A | 0 | -A | 0 | + | tokens | 0 | 0 | 0 | 0 | + | reserves | 0 | | | | + | collateral cash | 0 | 0 | 0 | 0 | + | collateral borrows | 0 | 0 | 0 | 0 | + | collateral tokens | 0 | +T | -T | 0 | + | collateral reserves | 0 | | | | + |---------------------+--------+------------+----------+-------| + */ + + /* Pre */ + + // borrowed + uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); + + uint256 cTokenCashPre = sinvoke getCash(e0); + uint256 liquidatorCashPre = sinvoke getCashOf(e0, liquidator); + uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); + uint256 otherCashPre = sinvoke getCashOf(e0, other); + + uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); + uint256 liquidatorBorrowsPre = sinvoke borrowBalanceStored(e0, liquidator); + uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); + uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); + + uint256 cTokenTokensPre = sinvoke totalSupply(e0); + uint256 liquidatorTokensPre = sinvoke balanceOf(e0, liquidator); + uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); + uint256 otherTokensPre = sinvoke balanceOf(e0, other); + + uint256 cTokenReservesPre = sinvoke totalReserves(e0); + + // collateral + uint256 collateralExchangeRatePre = sinvoke exchangeRateStoredInOther(e0); + + uint256 collateralCashPre = sinvoke getCashInOther(e0); + uint256 liquidatorCollateralCashPre = sinvoke getCashOfInOther(e0, liquidator); + uint256 borrowerCollateralCashPre = sinvoke getCashOfInOther(e0, borrower); + uint256 otherCollateralCashPre = sinvoke getCashOfInOther(e0, other); + + uint256 collateralBorrowsPre = sinvoke totalBorrowsInOther(e0); + uint256 liquidatorCollateralBorrowsPre = sinvoke borrowBalanceStoredInOther(e0, liquidator); + uint256 borrowerCollateralBorrowsPre = sinvoke borrowBalanceStoredInOther(e0, borrower); + uint256 otherCollateralBorrowsPre = sinvoke borrowBalanceStoredInOther(e0, other); + + uint256 collateralTokensPre = sinvoke totalSupplyInOther(e0); + uint256 liquidatorCollateralTokensPre = sinvoke balanceOfInOther(e0, liquidator); + uint256 borrowerCollateralTokensPre = sinvoke balanceOfInOther(e0, borrower); + uint256 otherCollateralTokensPre = sinvoke balanceOfInOther(e0, other); + + uint256 collateralReservesPre = sinvoke totalReservesInOther(e0); + + // Just Do It + // Note: cTokenCollateral is linked via Compound.spclnk in order to support checking its balances + // not perfect since it only proves the balance sheet is safe for a particular token configuration + static_require result == invoke liquidateBorrowFreshPub(e1, liquidator, borrower, repayAmount); + bool liquidateBorrowFreshReverted = lastReverted; + + /* Post */ + + // borrowed + uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); + + uint256 cTokenCashPost = sinvoke getCash(e2); + uint256 liquidatorCashPost = sinvoke getCashOf(e2, liquidator); + uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); + uint256 otherCashPost = sinvoke getCashOf(e2, other); + + uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); + uint256 liquidatorBorrowsPost = sinvoke borrowBalanceStored(e2, liquidator); + uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); + uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); + + uint256 cTokenTokensPost = sinvoke totalSupply(e2); + uint256 liquidatorTokensPost = sinvoke balanceOf(e2, liquidator); + uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); + uint256 otherTokensPost = sinvoke balanceOf(e2, other); + + uint256 cTokenReservesPost = sinvoke totalReserves(e2); + + // collateral + uint256 collateralExchangeRatePost = sinvoke exchangeRateStoredInOther(e2); + + uint256 collateralCashPost = sinvoke getCashInOther(e2); + uint256 liquidatorCollateralCashPost = sinvoke getCashOfInOther(e2, liquidator); + uint256 borrowerCollateralCashPost = sinvoke getCashOfInOther(e2, borrower); + uint256 otherCollateralCashPost = sinvoke getCashOfInOther(e2, other); + + uint256 collateralBorrowsPost = sinvoke totalBorrowsInOther(e2); + uint256 liquidatorCollateralBorrowsPost = sinvoke borrowBalanceStoredInOther(e2, liquidator); + uint256 borrowerCollateralBorrowsPost = sinvoke borrowBalanceStoredInOther(e2, borrower); + uint256 otherCollateralBorrowsPost = sinvoke borrowBalanceStoredInOther(e2, other); + + uint256 collateralTokensPost = sinvoke totalSupplyInOther(e2); + uint256 liquidatorCollateralTokensPost = sinvoke balanceOfInOther(e2, liquidator); + uint256 borrowerCollateralTokensPost = sinvoke balanceOfInOther(e2, borrower); + uint256 otherCollateralTokensPost = sinvoke balanceOfInOther(e2, other); + + uint256 collateralReservesPost = sinvoke totalReservesInOther(e2); + + // Measure + bool staticBalance = + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (liquidatorCashPost == liquidatorCashPre) && + (liquidatorBorrowsPost == liquidatorBorrowsPre) && + (liquidatorTokensPost == liquidatorTokensPre) && + (borrowerCashPost == borrowerCashPre) && + (borrowerBorrowsPost == borrowerBorrowsPre) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre) && + + (collateralExchangeRatePost == collateralExchangeRatePre) && + (collateralCashPost == collateralCashPre) && + (collateralBorrowsPost == collateralBorrowsPre) && + (collateralTokensPost == collateralTokensPre) && + (collateralReservesPost == collateralReservesPre) && + (liquidatorCollateralCashPost == liquidatorCollateralCashPre) && + (liquidatorCollateralBorrowsPost == liquidatorCollateralBorrowsPre) && + (liquidatorCollateralTokensPost == liquidatorCollateralTokensPre) && + (borrowerCollateralCashPost == borrowerCollateralCashPre) && + (borrowerCollateralBorrowsPost == borrowerCollateralBorrowsPre) && + (borrowerCollateralTokensPost == borrowerCollateralTokensPre) && + (otherCollateralCashPost == otherCollateralCashPre) && + (otherCollateralBorrowsPost == otherCollateralBorrowsPre) && + (otherCollateralTokensPost == otherCollateralTokensPre); + + bool dynamicBalance = + (repayAmount != 0) && + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre + repayAmount) && + (cTokenBorrowsPost == cTokenBorrowsPre - repayAmount) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (liquidatorCashPost == liquidatorCashPre - repayAmount) && + (liquidatorBorrowsPost == liquidatorBorrowsPre) && + (liquidatorTokensPost == liquidatorTokensPre) && + (borrowerCashPost == borrowerCashPre) && + (borrowerBorrowsPost == borrowerBorrowsPre - repayAmount) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre) && + (borrowerCollateralCashPost == borrowerCollateralCashPre) && + + (collateralExchangeRatePost == collateralExchangeRatePre) && + (collateralCashPost == collateralCashPre) && + (collateralBorrowsPost == collateralBorrowsPre) && + (collateralTokensPost == collateralTokensPre) && + (collateralReservesPost == collateralReservesPre) && + (liquidatorCollateralCashPost == liquidatorCollateralCashPre) && + (liquidatorCollateralBorrowsPost == liquidatorCollateralBorrowsPre) && + (liquidatorCollateralTokensPost - liquidatorCollateralTokensPre == borrowerCollateralTokensPre - borrowerCollateralTokensPost) && + (borrowerCollateralCashPost == borrowerCollateralCashPre) && + (borrowerCollateralBorrowsPost == borrowerCollateralBorrowsPre) && + (otherCollateralCashPost == otherCollateralCashPre) && + (otherCollateralBorrowsPost == otherCollateralBorrowsPre) && + (otherCollateralTokensPost == otherCollateralTokensPre); + + + static_assert (!liquidateBorrowFreshReverted => + ((result != 0 || repayAmount == 0 || liquidator == borrower) <=> staticBalance)), "Mismatch in static case"; + static_assert (!liquidateBorrowFreshReverted => + ((result == 0 && repayAmount != 0 && liquidator != currentContract) <=> dynamicBalance)), "Mismatch in dynamic case"; +} + +seize(uint result, address liquidator, address borrower, uint256 seizeTokens) +description "Break seize" { + // Pre/action/post environments + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Any other account + address other; havoc other; + static_require other != liquidator && other != borrower && other != currentContract; + + /* + - no effect on exchange rate + |----------+--------+------------+----------+-------| + | | CToken | Liquidator | Borrower | Other | + |----------+--------+------------+----------+-------| + | cash | 0 | 0 | 0 | 0 | + | borrows | 0 | 0 | 0 | 0 | + | tokens | 0 | +T | -T | 0 | + | reserves | 0 | | | | + |----------+--------+------------+----------+-------| + */ + + /* Pre */ + + uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); + + uint256 cTokenCashPre = sinvoke getCash(e0); + uint256 liquidatorCashPre = sinvoke getCashOf(e0, liquidator); + uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); + uint256 otherCashPre = sinvoke getCashOf(e0, other); + + uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); + uint256 liquidatorBorrowsPre = sinvoke borrowBalanceStored(e0, liquidator); + uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); + uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); + + uint256 cTokenTokensPre = sinvoke totalSupply(e0); + uint256 liquidatorTokensPre = sinvoke balanceOf(e0, liquidator); + uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); + uint256 otherTokensPre = sinvoke balanceOf(e0, other); + + uint256 cTokenReservesPre = sinvoke totalReserves(e0); + + // Just Do It + static_require result == invoke seize(e1, liquidator, borrower, seizeTokens); + bool seizeReverted = lastReverted; + + /* Post */ + + uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); + + uint256 cTokenCashPost = sinvoke getCash(e2); + uint256 liquidatorCashPost = sinvoke getCashOf(e2, liquidator); + uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); + uint256 otherCashPost = sinvoke getCashOf(e2, other); + + uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); + uint256 liquidatorBorrowsPost = sinvoke borrowBalanceStored(e2, liquidator); + uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); + uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); + + uint256 cTokenTokensPost = sinvoke totalSupply(e2); + uint256 liquidatorTokensPost = sinvoke balanceOf(e2, liquidator); + uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); + uint256 otherTokensPost = sinvoke balanceOf(e2, other); + + uint256 cTokenReservesPost = sinvoke totalReserves(e2); + + // Measure + bool staticBalance = + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (liquidatorCashPost == liquidatorCashPre) && + (liquidatorBorrowsPost == liquidatorBorrowsPre) && + (liquidatorTokensPost == liquidatorTokensPre) && + (borrowerCashPost == borrowerCashPre) && + (borrowerBorrowsPost == borrowerBorrowsPre) && + (borrowerTokensPost == borrowerTokensPre) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + bool dynamicBalance = + (seizeTokens != 0) && + (exchangeRatePost == exchangeRatePre) && + (cTokenCashPost == cTokenCashPre) && + (cTokenBorrowsPost == cTokenBorrowsPre) && + (cTokenTokensPost == cTokenTokensPre) && + (cTokenReservesPost == cTokenReservesPre) && + (liquidatorCashPost == liquidatorCashPre) && + (liquidatorBorrowsPost == liquidatorBorrowsPre) && + (liquidatorTokensPost == liquidatorTokensPre + seizeTokens) && + (borrowerCashPost == borrowerCashPre) && + (borrowerBorrowsPost == borrowerBorrowsPre) && + (borrowerTokensPost == borrowerTokensPre - seizeTokens) && + (otherCashPost == otherCashPre) && + (otherBorrowsPost == otherBorrowsPre) && + (otherTokensPost == otherTokensPre); + + static_assert (!seizeReverted => + ((result != 0 || seizeTokens == 0 || liquidator == borrower) <=> staticBalance)), "Mismatch in static case"; + static_assert (!seizeReverted => + ((result == 0 && seizeTokens != 0) <=> dynamicBalance)), "Mismatch in dynamic case"; +} \ No newline at end of file diff --git a/spec/formal/maximillion.cvl b/spec/formal/maximillion.cvl new file mode 100644 index 000000000..933d614ec --- /dev/null +++ b/spec/formal/maximillion.cvl @@ -0,0 +1,33 @@ +methods { + borrowBalance(address) returns uint256 + etherBalance(address) returns uint256 + + repayBehalf(address) returns uint256 +} + +repayBehalf(uint256 repayAmount, address borrower) +description "Break repayBehalf" { + env e0; havoc e0; + env e1; havoc e1; + env e2; havoc e2; + + static_require e1.block.number == e0.block.number; + static_require e2.block.number >= e1.block.number; + + static_require e0.msg.value == 0; + uint256 borrowed = sinvoke borrowBalance(e0, borrower); + + static_require repayAmount == e1.msg.value; + invoke repayBehalf(e1, borrower); + bool repayReverted = lastReverted; + + static_require e2.msg.value == 0; + uint256 borrows = sinvoke borrowBalance(e2, borrower); + uint256 balance = sinvoke etherBalance(e2, e1.msg.sender); + + static_assert (!repayReverted => + ((repayAmount >= borrowed) => (balance >= repayAmount - borrowed))), "Mismatch in refund"; + static_assert (!repayReverted => + ((repayAmount >= borrowed) => (borrows == 0)) && + ((repayAmount < borrowed) => (borrows == borrowed - repayAmount))), "Mismatch in borrows repaid"; +} \ No newline at end of file diff --git a/spec/formal/mintAndRedeemFresh.cvl b/spec/formal/mintAndRedeemFresh.cvl new file mode 100644 index 000000000..379bcd70c --- /dev/null +++ b/spec/formal/mintAndRedeemFresh.cvl @@ -0,0 +1,447 @@ +methods { + admin() returns address + totalSupply() returns uint256 + balanceOf(address) returns uint256 + accrualBlockNumber() returns uint256 + initialExchangeRateMantissa() returns uint256 + totalBorrows() returns uint256 + totalReserves() returns uint256 + + // Exposing internal functions + mintFreshPub(address,uint256) returns uint256 + redeemFreshPub(address,uint256,uint256) returns uint256 + + exchangeRateStoredInternalPub() returns uint256, uint256 + checkTransferInPub(address,uint256) returns uint256 + doTransferInPub(address,uint256) returns uint256 + getCash() returns uint256 + comptrollerMintAllowed(address,address,uint256) returns uint256 + comptrollerRedeemAllowed(address,address,uint256) returns uint256 + + // Simulation of functions that have effects on external contracts + doTransferInPubSim(address,uint256) returns uint256 + doTransferOutPubSim(address,uint256) returns uint256 + + // Lemmas + cTokenMintComputation(uint256) returns uint256 + cTokenRedeemComputation(uint256) returns uint256 +} + +mintFresh(uint result, address account, uint256 amount) +description "Failed to mint fresh asset with result $result (minter account=$account, amount=$amount)" { + + // Free Variables + env e0; havoc e0; // pre + env e1; havoc e1; // invocation + env e1b; havoc e1b; // invocations on behalf of CToken + env e2; havoc e2; // post + + // Strict ordering + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Capture current values + uint256 totalSupplyPre = sinvoke totalSupply(e0); + uint256 accountSupplyPre = sinvoke balanceOf(e0, account); + uint256 marketBlockNumber = sinvoke accrualBlockNumber(e0); + + // Simulate checks that depend on external contracts + uint comptrollerCheckResult = sinvoke comptrollerMintAllowed(e1, currentContract,account,amount); + uint labelCheckTransferIn = sinvoke checkTransferInPub(e1b, account, amount); + uint labelDoTransferIn = sinvoke doTransferInPubSim(e1, account, amount); // SG: make sure doTransferInPubSim and doTransferIn return the same value when starting from the same state, and make sure dummy can simulate all observable external behaviors of the call. + + // Invoke mintFresh + static_require result == invoke mintFreshPub(e1, account, amount); + bool mintFreshReverted = lastReverted; + + // Get next values + uint256 totalSupplyPost = sinvoke totalSupply(e2); + uint256 accountSupplyPost = sinvoke balanceOf(e2, account); + + // Helper for checking balance has not changed + bool staticBalance = + ( totalSupplyPost == totalSupplyPre && + accountSupplyPost == accountSupplyPre ); + + // Helper for checking balance has not changed, as expected. + // Precise change is computed in cTokenComputationLemma + bool dynamicBalance = (totalSupplyPost - totalSupplyPre == accountSupplyPost - accountSupplyPre) // Change in totalSupply is same as change in accountSupply + && (totalSupplyPost - totalSupplyPre >= 0); // The change in supplies must be >= 0 + + bool comptrollerCheckSuccess = comptrollerCheckResult == 0; + bool accrued = marketBlockNumber == e1.block.number; + bool checkTransferSuccess = labelCheckTransferIn == 0; + bool doTransferSuccess = labelDoTransferIn == 0; + + // Track error codes + uint256 NO_ERROR = 0; + uint256 COMPTROLLER_REJECTION = 3; + uint256 NOT_ACCRUED = 10; + uint256 CHECK_TRANSFER_FAILED_1 = 12; + uint256 CHECK_TRANSFER_FAILED_2 = 13; + uint256 TOKEN_TRANSFER_IN_FAILED = 15; + uint256 MATH_ERROR = 9; + + // Guarantee return values + static_assert (!mintFreshReverted && result != MATH_ERROR) => ( + result == NO_ERROR || + result == COMPTROLLER_REJECTION || + result == NOT_ACCRUED || + result == CHECK_TRANSFER_FAILED_1 || + result == CHECK_TRANSFER_FAILED_2 || + result == TOKEN_TRANSFER_IN_FAILED || + result == MATH_ERROR + ), "Got unexpected error code $result"; + + /* All these cases depend on: (1) mintFresh not reverting; and (2) the error code being anything other than a math error. + The idea is that (1) reverts, if are not catched by the caller (could it be a contract by Compound?), will have no effect on the state; + and (2) math errors, which are handled separately. + */ + // Success case updates market accordingly + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == NO_ERROR <=> ( + comptrollerCheckSuccess && + accrued && + checkTransferSuccess && + doTransferSuccess && + dynamicBalance + )), "Mismatch in no error case (0). Got result $result"; + + // Policy hook rejected case + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == COMPTROLLER_REJECTION <=> ( + !comptrollerCheckSuccess && + staticBalance + )), "Mismatch in comptroller rejection case (3). Got result $result"; + + // Not accrued + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == NOT_ACCRUED <=> ( + comptrollerCheckSuccess && + !accrued && + staticBalance + )), "Mismatch in non-accrued case (10=0xa). Got result $result"; + + // Check transfer failure + static_assert (!mintFreshReverted && result != MATH_ERROR) => ((result == CHECK_TRANSFER_FAILED_1 || result == CHECK_TRANSFER_FAILED_2) <=> ( + comptrollerCheckSuccess && + accrued && + !checkTransferSuccess && + staticBalance + )), "Mismatch in check transfer failure (12,13). Got result $result"; + + // TODO: SG: I think Geoff said a revert was the intention! + // Do transfer failure + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == TOKEN_TRANSFER_IN_FAILED <=> + ( + comptrollerCheckSuccess && + accrued && + checkTransferSuccess && + !doTransferSuccess && + staticBalance + )), "Mismatch in do transfer failure (15). Got result $result"; + + // Math error -> no state changes (at least, the ones we observe here! This is not checking about the FULL state of the contract) + // SG: Idea - this could be a useful check that is reused across many of Compound's functions that may return math error codes, and will be more thorough. + static_assert !mintFreshReverted => (result == MATH_ERROR => + ( + staticBalance + )), "State changes occuring despite math error, totalSupplyPre=$totalSupplyPre, totalSupplyPost=$totalSupplyPost ; accountSupplyPre=$accountSupplyPre, accountSupplyPost=$accountSupplyPost"; +} + +mintFresh_extended(uint result, address account, uint256 amount) +description "Failed to mint fresh asset with result $result (account=$account, amount=$amount)" { + // Free Variables + env e0; havoc e0; // pre + env e1; havoc e1; // invocation + env e2; havoc e2; // post + + // Strict ordering + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Minting to self is assumed to be impossible + static_require account != currentContract; + + // Capture current values + uint256 totalSupplyPre = sinvoke totalSupply(e0); + uint256 accountSupplyPre = sinvoke balanceOf(e0, account); + uint256 marketBlockNumber = sinvoke accrualBlockNumber(e0); + + uint256 cash = sinvoke getCash(e0); + + // Label CALL results + uint comptrollerCheckResult = sinvoke comptrollerMintAllowed(e1, currentContract, account, amount); + uint labelCheckTransferIn = sinvoke checkTransferInPub(e1, account, amount); + uint labelDoTransferIn = sinvoke doTransferInPubSim(e1, account, amount); + + // Invoke mintFresh + static_require result == invoke mintFreshPub(e1, account, amount); + bool mintFreshReverted = lastReverted; + + // Get next values + uint256 totalSupplyPost = sinvoke totalSupply(e2); + uint256 accountSupplyPost = sinvoke balanceOf(e2, account); + uint256 newCash = sinvoke getCash(e2); + + // Helper for checking balance has not changed + bool staticBalance = + ( totalSupplyPost == totalSupplyPre && + accountSupplyPost == accountSupplyPre ) + && cash == newCash ; + + // Helper for checking balance has not changed, as expected. + // Precise change is computed in cTokenComputationLemma + bool dynamicBalance = (totalSupplyPost - totalSupplyPre == accountSupplyPost - accountSupplyPre) // Change in totalSupply is same as change in accountSupply + && (totalSupplyPost - totalSupplyPre >= 0) // The change in supplies must be >= 0 + && (newCash - cash == amount); // The change in cash must be amount + + bool comptrollerCheckSuccess = comptrollerCheckResult == 0; // Comptroller is an external contract and its error is converted to COMPTROLLER_REJECTION, so no need to require on the label + bool accrued = marketBlockNumber == e1.block.number; + bool checkTransferSuccess = labelCheckTransferIn == 0; + bool doTransferSuccess = labelDoTransferIn == 0; + + // Track error codes + uint256 NO_ERROR = 0; + uint256 COMPTROLLER_REJECTION = 3; + uint256 NOT_ACCRUED = 10; + uint256 CHECK_TRANSFER_FAILED_1 = 12; + uint256 CHECK_TRANSFER_FAILED_2 = 13; + uint256 TOKEN_TRANSFER_IN_FAILED = 15; + uint256 MATH_ERROR = 9; + + // Guarantee return values + static_assert (!mintFreshReverted && result != MATH_ERROR) => ( + result == NO_ERROR || + result == COMPTROLLER_REJECTION || + result == NOT_ACCRUED || + result == CHECK_TRANSFER_FAILED_1 || + result == CHECK_TRANSFER_FAILED_2 || + result == TOKEN_TRANSFER_IN_FAILED || + result == MATH_ERROR + ), "Got unexpected error code $result"; + + /* All these cases depend on: (1) mintFresh not reverting; and (2) the error code being anything other than a math error. + The idea is that (1) reverts, if are not catched by the caller (could it be a contract by Compound?), will have no effect on the state; + and (2) math errors, which are handled separately. + */ + // Success case updates market accordingly + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == NO_ERROR <=> ( + comptrollerCheckSuccess && + accrued && + checkTransferSuccess && + doTransferSuccess && + dynamicBalance + )), "Mismatch in no error case (0). Got result $result"; + + // Policy hook rejected case + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == COMPTROLLER_REJECTION <=> ( + !comptrollerCheckSuccess && + staticBalance + )), "Mismatch in comptroller rejection case (3). Got result $result"; + + // Not accrued + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == NOT_ACCRUED <=> ( + comptrollerCheckSuccess && + !accrued && + staticBalance + )), "Mismatch in non-accrued case (10=0xa). Got result $result"; + + // Check transfer failure + static_assert (!mintFreshReverted && result != MATH_ERROR) => ((result == CHECK_TRANSFER_FAILED_1 || result == CHECK_TRANSFER_FAILED_2) <=> ( + comptrollerCheckSuccess && + accrued && + !checkTransferSuccess && + staticBalance + )), "Mismatch in check transfer failure (12,13). Got result $result"; + + // Do transfer failure + static_assert (!mintFreshReverted && result != MATH_ERROR) => (result == TOKEN_TRANSFER_IN_FAILED <=> + ( + comptrollerCheckSuccess && + accrued && + checkTransferSuccess && + !doTransferSuccess && + staticBalance + )), "Mismatch in do transfer failure (15). Got result $result"; + + // Math error -> no state changes (at least, the ones we observe here! This is not checking about the FULL state of the contract) + // SG: Idea - this could be a useful check that is reused across many of Compound's functions that may return math error codes, and will be more thorough. + static_assert !mintFreshReverted => (result == MATH_ERROR => + ( + staticBalance + )), "State changes occuring despite math error, totalSupplyPre=$totalSupplyPre, totalSupplyPost=$totalSupplyPost ; accountSupplyPre=$accountSupplyPre, accountSupplyPost=$accountSupplyPost"; +} + + +redeemFresh(uint result, address account, uint256 amountCTokens, uint256 amountUnderlying) +description "Failed to redeemFresh fresh asset with result $result (account=$account, amountCTokens=$amountCTokens, amountUnderlying=$amountUnderlying)" { + // Free Variables + env e0; havoc e0; // pre + env e1; havoc e1; // invocation + env e1b; havoc e1b; // invocations on behalf of CToken + env e2; havoc e2; // post + + // Strict ordering + static_require e1.block.number >= e0.block.number; + static_require e2.block.number >= e1.block.number; + + // Redeeming from self is assumed to be impossible + static_require account != currentContract; + + // Capture current values + uint256 totalSupplyPre = sinvoke totalSupply(e0); + uint256 accountSupplyPre = sinvoke balanceOf(e0, account); + uint256 marketBlockNumber = sinvoke accrualBlockNumber(e0); + uint256 cash = sinvoke getCash(e0); + + // Simulate checks that depend on external contracts + uint comptrollerCheckResult = sinvoke comptrollerRedeemAllowed(e1, currentContract, account, amountCTokens); // Should include amountUnderlying? + uint labelDoTransferOut = sinvoke doTransferOutPubSim(e1, account, amountUnderlying); + + // Invoke mintFresh + static_require result == invoke redeemFreshPub(e1, account, amountCTokens, amountUnderlying); + bool redeemFreshReverted = lastReverted; + + // Get next values + uint256 totalSupplyPost = sinvoke totalSupply(e2); + uint256 accountSupplyPost = sinvoke balanceOf(e2, account); + uint256 newCash = sinvoke getCash(e2); + + // Helper for checking balance has not changed + bool staticBalance = + ( totalSupplyPost == totalSupplyPre && + accountSupplyPost == accountSupplyPre ) + && cash == newCash ; + + // Helper for checking balance has not changed, as expected. + // Precise change is computed in cTokenComputationLemma + bool dynamicBalanceBasic = (totalSupplyPre - totalSupplyPost == accountSupplyPre - accountSupplyPost) // Change in totalSupply is same as change in accountSupply + && (totalSupplyPre - totalSupplyPost >= 0) // The change in supplies must be <= 0 + && (cash - newCash >= 0); // This operation transfers out + bool dynamicBalanceRedeemingUnderlying = (cash - newCash == amountUnderlying); // The change in cash must be amount + bool dynamicBalanceRedeemingCToken = (totalSupplyPre-totalSupplyPost == amountCTokens); // The change in CToken must be -amountCTokens + bool dynamicBalanceAdvanced = ((amountCTokens > 0 && amountUnderlying == 0) => dynamicBalanceRedeemingCToken) + && ((amountCTokens == 0 && amountUnderlying > 0) => dynamicBalanceRedeemingUnderlying) + && ((amountCTokens == 0 && amountUnderlying == 0) => (dynamicBalanceRedeemingCToken && dynamicBalanceRedeemingUnderlying)) + && !(amountCTokens > 0 && amountUnderlying > 0); + + bool comptrollerCheckSuccess = comptrollerCheckResult == 0; + bool accrued = marketBlockNumber == e1.block.number; + bool checkTransferSuccess = cash >= amountUnderlying; + bool doTransferSuccess = labelDoTransferOut == 0; + + // Track error codes + uint256 NO_ERROR = 0; + uint256 COMPTROLLER_REJECTION = 3; + uint256 NOT_ACCRUED = 10; + uint256 CHECK_TRANSFER_FAILED = 14; // TOKEN_INSUFFICIENT_CASH + uint256 TOKEN_TRANSFER_OUT_FAILED = 16; + uint256 MATH_ERROR = 9; + + // Guarantee return values + static_assert (!redeemFreshReverted && result != MATH_ERROR) => ( + result == NO_ERROR || + result == COMPTROLLER_REJECTION || + result == NOT_ACCRUED || + result == CHECK_TRANSFER_FAILED || + result == TOKEN_TRANSFER_OUT_FAILED || + result == MATH_ERROR + ), "Got unexpected error code $result"; + + + // Success case updates market accordingly + static_assert (!redeemFreshReverted && result != MATH_ERROR) => (result == NO_ERROR <=> ( + comptrollerCheckSuccess && + accrued && + checkTransferSuccess && + doTransferSuccess && + dynamicBalanceBasic && + dynamicBalanceAdvanced + )), "Mismatch in no error case (0). Got result $result"; + + // Policy hook rejected case + static_assert (!redeemFreshReverted && result != MATH_ERROR) => (result == COMPTROLLER_REJECTION <=> ( + !comptrollerCheckSuccess && + staticBalance + )), "Mismatch in comptroller rejection case (3=0x3). Got result $result"; + + // Not accrued + static_assert (!redeemFreshReverted && result != MATH_ERROR) => (result == NOT_ACCRUED <=> ( + comptrollerCheckSuccess && + !accrued && + staticBalance + )), "Mismatch in non-accrued case (10=0xa). Got result $result"; + + // Check transfer failure + // Note that since if amountUnderlying == 0 we do not compute in the spec the computed amountUnderlying, so we skip the test for now + static_assert (!redeemFreshReverted && result != MATH_ERROR && amountUnderlying > 0) => ((result == CHECK_TRANSFER_FAILED) <=> ( + comptrollerCheckSuccess && + accrued && + !checkTransferSuccess && + staticBalance + )), "Mismatch in check transfer failure (14). Got result $result"; + + // Do transfer failure + // Should be: static_assert !doTransferSuccess => redeemFreshReverted; + static_assert (!redeemFreshReverted && result != MATH_ERROR) => (result == TOKEN_TRANSFER_OUT_FAILED <=> + ( + comptrollerCheckSuccess && + accrued && + checkTransferSuccess && + !doTransferSuccess && + staticBalance + )), "Mismatch in do transfer failure (16). Got result $result"; + + // Math error -> no state changes (at least, the ones we observe here! This is not checking about the FULL state of the contract) + // SG: Idea - this could be a useful check that is reused across many of Compound's functions that may return math error codes, and will be more thorough. + static_assert !redeemFreshReverted => (result == MATH_ERROR => + ( + staticBalance && + newCash == cash + )), "State changes occuring despite math error, totalSupplyPre=$totalSupplyPre, totalSupplyPost=$totalSupplyPost ; accountSupplyPre=$accountSupplyPre, accountSupplyPost=$accountSupplyPost"; +} + +mintThenRedeem(address account, uint256 amountUnderlying) +description "Mint and redeem are not inverses for account $account, amount $amountUnderlying" +{ + env e0; havoc e0; + + uint origCash = sinvoke getCash(e0); + + // both calls are "fresh" + uint resultMint = invoke mintFreshPub(e0, account, amountUnderlying); + bool revertedMint = lastReverted; + + uint resultRedeem = invoke redeemFreshPub(e0, account, 0, amountUnderlying); + bool revertedRedeem = lastReverted; + + uint newCash = sinvoke getCash(e0); + + static_assert (resultMint == 0 && !revertedMint && resultRedeem == 0 && !revertedRedeem) => newCash == origCash; + + // check that exchange rate is the same, check all the 4 variables that affect the exchange rate are retained. + // check that accounts balances are the same. + // the only thing that changes is the interest index. rounding errors. +} + + +/* +ERRORS: + +0 NO_ERROR, +1 UNAUTHORIZED, +2 BAD_INPUT, +3 COMPTROLLER_REJECTION, +4 COMPTROLLER_CALCULATION_ERROR, +5 INTEREST_RATE_MODEL_ERROR, +6 INVALID_ACCOUNT_PAIR, +7 INVALID_CLOSE_AMOUNT_REQUESTED, +8 INVALID_COLLATERAL_FACTOR, +9 MATH_ERROR, +10 MARKET_NOT_FRESH, +11 MARKET_NOT_LISTED, +12 TOKEN_INSUFFICIENT_ALLOWANCE, +13 TOKEN_INSUFFICIENT_BALANCE, +14 TOKEN_INSUFFICIENT_CASH, +15 TOKEN_TRANSFER_IN_FAILED, +16 TOKEN_TRANSFER_OUT_FAILED + +*/ diff --git a/spec/scenario/Borrow.scen b/spec/scenario/Borrow.scen new file mode 100644 index 000000000..3790a73cf --- /dev/null +++ b/spec/scenario/Borrow.scen @@ -0,0 +1,46 @@ + +-- Waiting on Comptroller actually checking market entered +Test "Borrow some BAT fails when BAT not entered" + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken BAT cBAT + Support cZRX collateralFactor:0.5 + Support cBAT collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX + Invariant Static (CToken cZRX ExchangeRateStored) + AllowFailures + Borrow Geoff 1e18 cBAT + Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION MARKET_NOT_ENTERED + +Test "Borrow some BAT fails when no BAT available" + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken BAT cBAT + Support cZRX collateralFactor:0.5 + Support cBAT collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cBAT + Invariant Static (CToken cZRX ExchangeRateStored) + AllowFailures + Borrow Geoff 1e18 cBAT + Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE + +Test "Borrow some BAT from Excess Cash" + Invariant Success + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken BAT cBAT + Give cBAT 10e18 BAT -- Faucet some bat to borrow + Support cZRX collateralFactor:0.5 + Support cBAT collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cBAT + Borrow Geoff 1e18 cBAT + EnterMarkets Geoff cZRX cBAT + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) diff --git a/spec/scenario/Borrow.scen.old b/spec/scenario/Borrow.scen.old new file mode 100644 index 000000000..e53c1619c --- /dev/null +++ b/spec/scenario/Borrow.scen.old @@ -0,0 +1,87 @@ +-- Borrow Tests + +Macro CreateSupportedAsset token price interestRate policyHook + AddToken token + SupportMarket token price interestRate policyHook + Assert Success + +Macro CreateSupply user token amount + Approve user token amount + Faucet user token amount + Supply user token amount + Assert Success + +Test "Supply Ether and Borrow OMG" + -- Note that borrow reduces Cash but does not reduce the Supply balance sheet. + CreateSupportedAsset Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + CreateSupply Geoff Ether 10.0e18 + Assert Equal (SupplyBalance Geoff Ether) (Exactly 10.0e18) + FastForward 2 Blocks + CreateSupportedAsset OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + AddCash OMG 1e20 + CreateSupply Torrey OMG 5.0e18 + Assert Equal (BalanceSheetSupply OMG) (Exactly 5.0e18) + Assert Equal (TokenBalance Geoff OMG) (Exactly 0.0e18) + EnterMarkets Geoff OMG + Borrow Geoff OMG 2.0e18 + Assert Success + Assert Equal (BalanceSheetBorrow OMG) (Exactly 2.1e18) -- includes origination fee + Assert Equal (BorrowBalance Geoff OMG) (Exactly 2.1e18) -- includes origination fee + Assert Equal (TokenBalance Geoff OMG) (Exactly 2.0e18) -- does not include origination fee + -- + -- OMG total supply unchanged + Assert Equal (BalanceSheetSupply OMG) (Exactly 5.0e18) + + +Test "Supply Ether and attempt to Borrow more OMG than supported by collateral ratio" + -- Note that borrow reduces Cash but does not reduce the Supply balance sheet. + CreateSupportedAsset Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + CreateSupply Geoff Ether 3.0e18 + Assert Equal (SupplyBalance Geoff Ether) (Exactly 3.0e18) + Assert Equal (MaxBorrow Geoff) (Exactly 1.5e18) -- the original supply has doubled due to interest, so max borrow value has also doubled + FastForward 2 Blocks + CreateSupportedAsset OMG (FixedPrice 0.2) (FixedRate 0.5 0.75) SimplePolicyHook + AddCash OMG 1e20 + CreateSupply Torrey OMG 30.0e18 + Assert Equal (BalanceSheetSupply OMG) (Exactly 30.0e18) + Assert Equal (TokenBalance Geoff OMG) (Exactly 0.0e18) + Assert Equal (MaxBorrow Geoff) (Exactly 3.0e18) -- the original supply has doubled due to interest, so max borrow value has also doubled + EnterMarkets Geoff OMG + Borrow Geoff OMG 20.0e18 + Assert Failure INSUFFICIENT_LIQUIDITY BORROW_AMOUNT_LIQUIDITY_SHORTFALL + Assert Equal (BorrowBalance Geoff OMG) (Exactly 0.0e18) + Assert Equal (TokenBalance Geoff OMG) (Exactly 0.0e18) + Assert Equal (BalanceSheetBorrow OMG) (Exactly 0.0e18) + -- + -- OMG total supply unchanged + Assert Equal (BalanceSheetSupply OMG) (Exactly 30.0e18) + +Test "Can't borrow an initial state asset" + CreateSupportedAsset Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + CreateSupply Geoff Ether 30.0e18 + FastForward 2 Blocks + AddToken OMG + AddCash OMG 1e20 + Borrow Geoff OMG 1e18 + Assert Failure MARKET_NOT_LISTED BORROW_MARKET_NOT_LISTED + +Test "Can't borrow when contract is paused" + CreateSupportedAsset Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + CreateSupply Geoff Ether 10.0e18 + Assert Equal (SupplyBalance Geoff Ether) (Exactly "10.0e18") + FastForward 2 Blocks + CreateSupportedAsset OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + CreateSupply Torrey OMG 5.0e18 + AddCash OMG 1e20 + Assert Equal (BalanceSheetSupply OMG) (Exactly 5.0e18) + Assert Equal (TokenBalance Geoff OMG) (Exactly 0.0e18) + PolicyHook OMG (SetPaused True) + Borrow Geoff OMG 2.0e18 + Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION 1 + Assert Equal (BorrowBalance Geoff OMG) (Exactly 0.0e18) + Assert Equal (TokenBalance Geoff OMG) (Exactly 0.0e18) + +Test "Can't borrow if have not entered market" + CreateSupportedAsset OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Borrow Geoff OMG 2.0e18 + Assert Failure ASSET_NOT_ENTERED BORROW_ASSET_NOT_ENTERED diff --git a/spec/scenario/BorrowBalance.scen b/spec/scenario/BorrowBalance.scen new file mode 100644 index 000000000..312f8a748 --- /dev/null +++ b/spec/scenario/BorrowBalance.scen @@ -0,0 +1,84 @@ +-- Tests for the current borrow balance in a number of scenarios + +Macro NewBorrow borrowAmount borrowRate user=Geoff + NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset + NewCToken ZRX cZRX + NewCToken BAT cBAT borrowRate -- note: cannot use macros with named args right now + Give cBAT 10e18 BAT -- Faucet some bat to borrow + Support cZRX collateralFactor:0.5 + Support cBAT collateralFactor:0.5 + SimpleBorrow user borrowAmount + +Macro SimpleBorrow user borrowAmount + Prep user Some ZRX cZRX + Mint user 100e18 cZRX + EnterMarkets user cZRX cBAT + Borrow user borrowAmount cBAT + +Test "Borrow Balance after 3000 blocks" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) + +Test "Borrow Balance after 3000 blocks and then 6000 blocks" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + AccrueInterest cBAT + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) + FastForward 6000 Blocks -- 1e18 * (1 + 3000 * 0.0005) * (1 + 6000 * 0.0005) + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 10e18) + +Test "Borrow Balance after accrual then changed interest rate" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) + Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- Current: 1e18 * (1 + 3000 * 0.0005) + -- Note: this should accrue interest + InterestRateModel Deploy Fixed Std 0.0004 + CToken cBAT SetInterestRateModel (InterestRateModel Std Address) + -- Check borrow balance still based on old figure (with previous interest accrual) + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) + -- Now accrue with new rate + FastForward 8000 Blocks -- 1e18 * (1 + 3000 * 0.0005) * (1 + 8000 * 0.0004) + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10.5e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 10.5e18) + +Test "Total Borrow Balance with Two Borrowers" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 user:Geoff + FastForward 3000 Blocks + InterestRateModel Deploy Fixed Std 0.0004 + CToken cBAT SetInterestRateModel (InterestRateModel Std Address) + -- Check borrow balance still based on old figure (with previous interest accrual) + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) + SimpleBorrow user:Torrey borrowAmount:5e18 + -- Now accrue with new rate + FastForward 8000 Blocks + -- Geoff: 1e18 * (1 + 3000 * 0.0005) * (1 + 8000 * 0.0004) + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10.5e18) + -- Torrey: 5e18 * (1 + 8000 * 0.0004) + Assert Equal (cToken cBAT BorrowBalance Torrey) (Exactly 21e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 31.5e18) + -- And test some repayment + From Torrey (Erc20 BAT Approve cBAT 2.0e18) + RepayBorrow Torrey 2.0e18 cBAT + Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10.5e18) + Assert Equal (cToken cBAT BorrowBalance Torrey) (Exactly 19e18) + Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 29.5e18) diff --git a/spec/scenario/BorrowEth.scen b/spec/scenario/BorrowEth.scen new file mode 100644 index 000000000..83ba4d5b5 --- /dev/null +++ b/spec/scenario/BorrowEth.scen @@ -0,0 +1,49 @@ + +Test "Borrow some Eth fails when Eth not entered" + NewComptroller price:1.0 + ListedCToken ZRX cZRX + ListedEtherToken cETH initialExchangeRate:0.005e9 + SetCollateralFactor cZRX collateralFactor:0.5 + SetCollateralFactor cETH collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX + AllowFailures + Invariant Static (CToken cZRX ExchangeRateStored) + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Static (Comptroller Liquidity Geoff) + Invariant Static (EtherBalance Geoff) + BorrowEth Geoff 1e18 cETH + Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION MARKET_NOT_ENTERED + +Test "Borrow some ETH fails when no ETH available" + NewComptroller price:1.0 + ListedCToken ZRX cZRX + ListedEtherToken cETH initialExchangeRate:0.005e9 + SetCollateralFactor cZRX collateralFactor:0.5 + SetCollateralFactor cETH collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cETH + AllowFailures + Invariant Static (CToken cZRX ExchangeRateStored) + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Static (Comptroller Liquidity Geoff) + Invariant Static (EtherBalance Geoff) + BorrowEth Geoff 1e18 cETH + Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE + +Test "Borrow some ETH from excess cash" + NewComptroller price:1.0 + ListedCToken ZRX cZRX + ListedEtherToken cETH initialExchangeRate:0.005e9 + SetCollateralFactor cZRX collateralFactor:0.5 + SetCollateralFactor cETH collateralFactor:0.5 + Donate cETH 0.003e18 + Prep Geoff Some ZRX cZRX + Mint Geoff 1e18 cZRX + EnterMarkets Geoff cZRX cETH + Expect Changes (EtherBalance Geoff) +0.001e18 + BorrowEth Geoff 0.001e18 cETH + Assert Equal (EtherBalance cETH) 0.002e18 + Assert Equal (Comptroller Liquidity Geoff) 4.99e17 diff --git a/spec/scenario/BorrowWBTC.scen b/spec/scenario/BorrowWBTC.scen new file mode 100644 index 000000000..5607efd97 --- /dev/null +++ b/spec/scenario/BorrowWBTC.scen @@ -0,0 +1,62 @@ + +-- Waiting on Comptroller actually checking market entered +Test "Borrow some WBTC fails when WBTC not entered" + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken WBTC cWBTC tokenType:WBTC + Support cZRX collateralFactor:0.5 + Support cWBTC collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX + Invariant Static (CToken cZRX ExchangeRateStored) + AllowFailures + Borrow Geoff 1e8 cWBTC + Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION MARKET_NOT_ENTERED + +Test "Borrow some WBTC fails when no WBTC available" + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken WBTC cWBTC tokenType:WBTC + Support cZRX collateralFactor:0.5 + Support cWBTC collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cWBTC + Invariant Static (CToken cZRX ExchangeRateStored) + AllowFailures + Borrow Geoff 1e8 cWBTC + Assert Failure TOKEN_INSUFFICIENT_CASH BORROW_CASH_NOT_AVAILABLE + +Test "Borrow some WBTC fails when WBTC paused" + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken WBTC cWBTC tokenType:WBTC + Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow + Support cZRX collateralFactor:0.5 + Support cWBTC collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cWBTC + Invariant Static (CToken cZRX ExchangeRateStored) + Erc20 WBTC Pause + AllowFailures + Borrow Geoff 1e8 cWBTC + Assert Revert + +Test "Borrow some WBTC from Excess Cash" + Invariant Success + NewComptroller price:1.0 + NewCToken ZRX cZRX + NewCToken WBTC cWBTC tokenType:WBTC + Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow + Support cZRX collateralFactor:0.5 + Support cWBTC collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cWBTC + Borrow Geoff 1e8 cWBTC + EnterMarkets Geoff cZRX cWBTC + Assert Equal (cToken cWBTC BorrowBalance Geoff) (Exactly 1e8) + Assert Equal (Erc20 WBTC TokenBalance Geoff) (Exactly 1e8) + Assert Equal (Erc20 WBTC TokenBalance cWBTC) (Exactly 9e8) diff --git a/spec/scenario/BreakLiquidate.scen b/spec/scenario/BreakLiquidate.scen new file mode 100644 index 000000000..0990ef2ae --- /dev/null +++ b/spec/scenario/BreakLiquidate.scen @@ -0,0 +1,82 @@ + +Macro NewBorrow borrowAmount mintAmount borrowRate=0.0005 user=Geoff collateralPrice=1.0 borrowPrice=1.0 liquidationIncentive=1.1 + PricedComptroller closeFactor:0.9 -- Set the close factor high to reduce number of steps to demonstrate + Comptroller LiquidationIncentive liquidationIncentive + NewCToken ZRX cZRX + NewCToken BAT cBAT borrowRate + Give cBAT 10e18 BAT -- Faucet some bat to borrow + PriceOracle SetPrice cZRX collateralPrice + Support cZRX collateralFactor:0.7 + PriceOracle SetPrice cBAT borrowPrice + Support cBAT collateralFactor:0 + SimpleBorrow user borrowAmount mintAmount + +Macro SimpleBorrow user borrowAmount mintAmount + Prep user mintAmount ZRX cZRX + Mint user mintAmount cZRX + EnterMarkets user cZRX cBAT + Borrow user borrowAmount cBAT + +Test "When account goes further underwater than the liquidation incentive and cannot pay down debt fully" + -- Happens whenever collateral ratio > liquidation discount (i.e. 1 / liquidation incentive) + -- + -- Start right around the liquidity threshold + NewBorrow borrowAmount:1e18 mintAmount:1.43e18 liquidationIncentive:1.1 + -- + -- Verify that the borrow results in the correct state + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 1.43e18 + -- + -- Put the account underwater s.t. 0.91 < Borrow/Supply + -- i.e. (1 / liquidationIncentive) < Borrow/Supply + PriceOracle SetPrice cZRX 0.76 + -- + -- Pay back a bunch of debt by liquidating + Prep Jared 10e18 BAT cBAT + Liquidate Jared "->" Geoff 0.9e18 cBAT "Seizing" cZRX + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.127368422e18 + -- Do it again, and note that the collateral is gone but borrows remain + -- if we had set the close factor lower, it would just take more steps + Liquidate Jared "->" Geoff 0.0880000008e18 cBAT "Seizing" cZRX + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.0119999992e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0 + +Test "When liquidation incentive is too high to be effective" + -- Happens whenever liquidation discount < collateral factor + -- + -- Start right around the liquidity threshold + NewBorrow borrowAmount:1e18 mintAmount:1.43e18 liquidationIncentive:1.5 + -- + -- Verify that the borrow results in the correct state + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 1.43e18 + -- + -- Put the account underwater s.t. 0.7 < Borrow/Supply + -- i.e. collateral factor < Borrow/Supply + PriceOracle SetPrice cZRX 0.87 + -- + -- Now any amount of debt that we pay back by liquidating will make liquidity worse + -- + -- First, prepare to liquidate + Prep Jared 10e18 BAT cBAT + Expect Changes (Comptroller Liquidity Geoff) -0.024999999076e18 + -- Note that the account collateral ratio will become worse than before + -- although shortfall decreases in absolute terms + -- had Supply/Borrow = 1.430000000 * 0.87 / 1.0 = 1.244100000 + -- now Supply/Borrow = 0.567931036 * 0.87 / 0.5 = 1.135862072 + -- + -- Now perform the liquidation + Liquidate Jared "->" Geoff 0.5e18 cBAT "Seizing" cZRX + -- + -- Verify that the liquidation went through + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.5e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.567931036e18 + -- + -- Test succeeded which means our expectation was correct + -- liquidity went down after a liquidation! + -- + -- Now lets see that lowering the incentive and liquidating improves the situation + Comptroller LiquidationIncentive 1.2 + Expect Changes (Comptroller Liquidity Geoff) 0.016000000294e18 + Liquidate Jared "->" Geoff 0.1e18 cBAT "Seizing" cZRX diff --git a/spec/scenario/CTokenAdmin.scen b/spec/scenario/CTokenAdmin.scen new file mode 100644 index 000000000..dfd317f82 --- /dev/null +++ b/spec/scenario/CTokenAdmin.scen @@ -0,0 +1,30 @@ + +Test "Set admin" + NewComptroller + NewCToken ZRX cZRX + Assert Equal (CToken cZRX Admin) (Address Root) + Assert Equal (CToken cZRX PendingAdmin) (Address Zero) + From Root (CToken cZRX SetPendingAdmin Geoff) + Assert Equal (CToken cZRX Admin) (Address Root) + Assert Equal (CToken cZRX PendingAdmin) (Address Geoff) + From Geoff (CToken cZRX AcceptAdmin) + Assert Equal (CToken cZRX Admin) (Address Geoff) + Assert Equal (CToken cZRX PendingAdmin) (Address Zero) + +Test "Fail to set pending admin" + NewComptroller + NewCToken ZRX cZRX + Invariant Remains (CToken cZRX Admin) (Address Root) + Invariant Remains (CToken cZRX PendingAdmin) (Address Zero) + AllowFailures + From Geoff (CToken cZRX SetPendingAdmin Geoff) + Assert Failure UNAUTHORIZED SET_PENDING_ADMIN_OWNER_CHECK + +Test "Fail to accept admin" + NewComptroller + NewCToken ZRX cZRX + Invariant Remains (CToken cZRX Admin) (Address Root) + Invariant Remains (CToken cZRX PendingAdmin) (Address Zero) + AllowFailures + From Geoff (CToken cZRX AcceptAdmin) + Assert Failure UNAUTHORIZED ACCEPT_ADMIN_PENDING_ADMIN_CHECK diff --git a/spec/scenario/CoreMacros b/spec/scenario/CoreMacros new file mode 100644 index 000000000..c55ce3956 --- /dev/null +++ b/spec/scenario/CoreMacros @@ -0,0 +1,185 @@ +-- These are included in each scenario + +Macro Successfully + Invariant Success + +Macro AllowFailures + ClearInvariants Success + +Macro PricedComptroller closeFactor=0.1 maxAssets=20 + Unitroller Deploy + PriceOracle Deploy Simple + ComptrollerImpl Deploy Scenario ScenComptroller + Unitroller SetPendingImpl ScenComptroller + PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (Address Zero) (Address Zero) -- Final argument is a Junk address, if listing cEther use ListedEtherToken to replace proxy + ComptrollerImpl ScenComptroller Become (PriceOracleProxy Address) closeFactor maxAssets + +Macro NewComptroller price=1.0 closeFactor=0.1 maxAssets=20 + Unitroller Deploy + PriceOracle Deploy Fixed price + ComptrollerImpl Deploy Scenario ScenComptroller + Unitroller SetPendingImpl ScenComptroller + PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (Address Zero) (Address Zero) -- Junk address, if listing cEther use ListedEtherToken to replace proxy + ComptrollerImpl ScenComptroller Become (PriceOracleProxy Address) closeFactor maxAssets + +Macro NewCToken erc20 cToken borrowRate=0.0005 initialExchangeRate=2e9 decimals=8 tokenType=Standard cTokenType=Scenario + Erc20 Deploy tokenType erc20 erc20 + InterestRateModel Deploy Fixed StdInterest borrowRate -- Note: interest rate model probably shouldn't be global + CToken Deploy cTokenType cToken cToken (Erc20 erc20 Address) (Comptroller Address) (InterestRateModel StdInterest Address) initialExchangeRate decimals + +Macro NewEtherToken cToken borrowRate=0.0005 initialExchangeRate=2e9 decimals=8 + InterestRateModel Deploy Fixed StdInterest borrowRate -- Note: interest rate model probably shouldn't be global + CToken Deploy CEtherScenario cToken cToken (Comptroller Address) (InterestRateModel StdInterest Address) initialExchangeRate decimals + +Macro ListedCToken erc20 cToken borrowRate=0.0005 initialExchangeRate=2e9 decimals=8 tokenType=Standard cTokenType=Scenario + NewCToken erc20 cToken borrowRate initialExchangeRate decimals tokenType cTokenType + Comptroller SupportMarket cToken + +Macro ListedEtherToken cToken borrowRate=0.0005 initialExchangeRate=2e9 decimals=8 + NewEtherToken cToken borrowRate initialExchangeRate decimals + Comptroller SupportMarket cToken + PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (Address cETH) (Address Zero) + Comptroller SetPriceOracle (PriceOracleProxy Address) + +Macro ListedEtherTokenMinted cToken borrowRate=0.0005 initialExchangeRate=2e9 decimals=8 + NewEtherToken cToken borrowRate initialExchangeRate decimals + Comptroller SupportMarket cToken + CallMintEth Root 1e18 cToken + +Macro SetPriceCF cToken price collateralFactor + PriceOracle SetPrice cToken price + Comptroller SetCollateralFactor cToken collateralFactor + +Macro Give user amount erc20 + Erc20 erc20 Faucet user amount + +Macro Donate token amount + (Trx Value amount (CToken token Donate)) + +Macro Prep user amount erc20 token allowanceAmount=Nothing + Erc20 erc20 Faucet user amount + From user (Erc20 erc20 Approve token (Default allowanceAmount amount)) + +Macro Allow user token + From user (Erc20 (CToken token Underlying) Approve token Max) + +Macro AccrueInterest token + CToken token AccrueInterest + +Macro Mint user amount token + From user (CToken token Mint amount) + +Macro SendMintEth user amount token + From user (Trx GasPrice 0 (Trx Value amount (Send token amount))) + +Macro CallMintEth user amount token + From user (Trx GasPrice 0 (Trx Value amount (CToken token Mint))) + +Macro Redeem user amount token + From user (CToken token Redeem amount) + +Macro RedeemEth user amount token + Trx GasPrice 0 (From user (CToken token Redeem amount)) + +Macro RedeemUnderlying user amount token + From user (CToken token RedeemUnderlying amount) + +Macro RedeemUnderlyingEth user amount token + Trx GasPrice 0 (From user (CToken token RedeemUnderlying amount)) + +Macro BorrowEth user amount token + Trx GasPrice 0 (From user (CToken token Borrow amount)) + +Macro Borrow user amount token + From user (CToken token Borrow amount) + +Macro RepayBorrow user amount token + From user (CToken token RepayBorrow amount) + +Macro RepayBorrowEth user amount token + From user (Trx GasPrice 0 (Trx Value amount (CToken token RepayBorrow))) + +Macro RepayBorrowEthMax user amount token + From user (Trx GasPrice 0 (Trx Value amount (Maximillion RepayBehalf user))) + +Macro RepayBorrowBehalf user behalf amount token + From user (CToken token RepayBorrowBehalf behalf amount) + +Macro RepayBorrowEthBehalf user behalf amount token + From user (Trx GasPrice 0 (Trx Value amount (CToken token RepayBorrowBehalf behalf))) + +Macro Liquidate liquidator _ borrower amount token _ collateral + From liquidator (CToken token Liquidate borrower collateral amount) + +Macro LiquidateEthColl liquidator _ borrower amount token _ collateral + From liquidator (Trx GasPrice 0 (CToken token Liquidate borrower collateral amount)) + +Macro LiquidateEthBorrow liquidator _ borrower amount token _ collateral + From liquidator (Trx GasPrice 0 (Trx Value amount (CToken token Liquidate borrower collateral))) + +Macro Seize amount token caller liquidator borrower + From caller (CToken token Seize liquidator borrower amount) + +Macro EvilSeize token amount treasure seizer seizee + CToken token EvilSeize treasure seizer seizee amount + +Macro Support cToken collateralFactor=0.5 + Comptroller SupportMarket cToken + Comptroller SetCollateralFactor cToken collateralFactor + +Macro SetCollateralFactor cToken collateralFactor=0.5 + Comptroller SetCollateralFactor cToken collateralFactor + +Macro ReduceReserves amount token + CToken token ReduceReserves amount + +Macro FastForward n blocks + Comptroller FastForward n blocks + +Macro EnterMarkets user ...markets + From user (Comptroller EnterMarkets markets) + +Macro ExitMarket user market + From user (Comptroller ExitMarket market) + +Macro Transfer from to amount token + From from (Erc20 token Transfer to amount) + +Macro Cash cToken + Read Erc20 (CToken cToken Underlying) TokenBalance cToken + +Macro QuickMint amount cToken from=Me + Give from amount (CToken cToken Underlying) + Allow from cToken + From from (CToken cToken Mint amount) + +Macro QuickBorrow amount cToken ...collateral + From Me (Comptroller EnterMarkets collateral) + From Me (Comptroller EnterMarkets (cToken)) + From Me (CToken cToken Borrow amount) + +-- Macro for performing a borrow with the sole +-- purpose of adding interest to the erc20 market +Macro BorrowAndRepayWithInterest erc20 cToken amount interestAmount interestRate blocks reserveRate=0 + -- TODO: Make invariant success for these? + -- TODO: Named args as macros + InterestRateModel Deploy Fixed Std interestRate + CToken cToken SetInterestRateModel (InterestRateModel Std Address) + CToken cToken SetReserveFactor reserveRate + ListedCToken COLLAT cCOLLAT + Comptroller SetCollateralFactor cCOLLAT 0.9 + Prep Torrey 1e30 COLLAT cCOLLAT + Mint Torrey 1e30 cCOLLAT + EnterMarkets Torrey cCOLLAT cToken + Assert True (Comptroller CheckMembership Torrey cCOLLAT) + Assert True (Comptroller CheckMembership Torrey cToken) + Borrow Torrey amount cToken + -- Cool, we've borrowed, now let's accrue interest then repay all + FastForward blocks Blocks + -- RepayBorrow Torrey (CToken BorrowBalance Torrey) cToken + From Torrey (Erc20 erc20 Approve cToken amount) + RepayBorrow Torrey amount cToken + From Torrey (Erc20 erc20 Approve cToken interestAmount) + Give Torrey interestAmount erc20 + RepayBorrow Torrey interestAmount cToken + Assert Equal (CToken cToken BorrowBalance Torrey) Zero diff --git a/spec/scenario/EnterExitMarkets.scen b/spec/scenario/EnterExitMarkets.scen new file mode 100644 index 000000000..aefc43955 --- /dev/null +++ b/spec/scenario/EnterExitMarkets.scen @@ -0,0 +1,157 @@ +-- Enter and Exit Markets Tests + +Test "Enter Markets Idempotent" + NewComptroller + Assert Equal (Comptroller MembershipLength Geoff) Zero + Assert Equal (Comptroller AssetsIn Geoff) [] + ListedCToken ZRX cZRX + EnterMarkets Geoff cZRX + Assert Log MarketEntered (cToken (Address cZRX)) (account (Address Geoff)) + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) + Assert True (Comptroller CheckMembership Geoff cZRX) + ListedCToken OMG cOMG + EnterMarkets Geoff cZRX cOMG + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) + Assert True (Comptroller CheckMembership Geoff cZRX) + Assert True (Comptroller CheckMembership Geoff cOMG) + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG)] + +Test "Entered Market Must Be Supported" + NewComptroller + Assert Equal (Comptroller MembershipLength Geoff) Zero + ListedCToken ZRX cZRX + EnterMarkets Geoff cZRX + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) + NewCToken OMG cOMG + EnterMarkets Geoff cZRX cOMG + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) + Assert True (Comptroller CheckMembership Geoff cZRX) + Assert False (Comptroller CheckMembership Geoff cOMG) + Support cOMG + EnterMarkets Geoff cZRX cOMG + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) + Assert True (Comptroller CheckMembership Geoff cZRX) + Assert True (Comptroller CheckMembership Geoff cOMG) + +Test "Cannot enter Markets beyond max assets" + NewComptroller + Comptroller SetMaxAssets 1 + Assert Equal (Comptroller MembershipLength Geoff) Zero + ListedCToken ZRX cZRX + ListedCToken OMG cOMG + EnterMarkets Geoff cZRX cOMG + Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) + Assert True (Comptroller CheckMembership Geoff cZRX) + Assert False (Comptroller CheckMembership Geoff cOMG) + +Test "Exit single market" + NewComptroller + ListedCToken ZRX cZRX + EnterMarkets Geoff cZRX + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX)] + ExitMarket Geoff cZRX + Assert Equal (Comptroller AssetsIn Geoff) [] + +Test "Exit non-entered market" + NewComptroller + ListedCToken ZRX cZRX + ExitMarket Geoff cZRX + Assert Equal (Comptroller AssetsIn Geoff) [] + +Test "Exit one of two market from the front" + NewComptroller + ListedCToken ZRX cZRX + ListedCToken OMG cOMG + EnterMarkets Geoff cZRX cOMG + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG)] + ExitMarket Geoff cZRX + Assert Equal (Comptroller AssetsIn Geoff) [(Address cOMG)] + +Test "Exit one of two market from the back" + NewComptroller + ListedCToken ZRX cZRX + ListedCToken OMG cOMG + EnterMarkets Geoff cZRX cOMG + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG)] + ExitMarket Geoff cOMG + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX)] + +Test "Exit multiple markets" + NewComptroller + ListedCToken ZRX cZRX + ListedCToken OMG cOMG + ListedCToken BAT cBAT + ListedCToken REP cREP + ListedCToken DAI cDAI + EnterMarkets Geoff cZRX cOMG cBAT cREP cDAI + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG) (Address cBAT) (Address cREP) (Address cDAI)] + ExitMarket Geoff cZRX + Assert Equal (Comptroller AssetsIn Geoff) [(Address cDAI) (Address cOMG) (Address cBAT) (Address cREP)] + ExitMarket Geoff cREP + Assert Equal (Comptroller AssetsIn Geoff) [(Address cDAI) (Address cOMG) (Address cBAT)] + ExitMarket Geoff cOMG + Assert Equal (Comptroller AssetsIn Geoff) [(Address cDAI) (Address cBAT)] + ExitMarket Geoff cDAI + Assert Equal (Comptroller AssetsIn Geoff) [(Address cBAT)] + ExitMarket Geoff cBAT + Assert Equal (Comptroller AssetsIn Geoff) [] + +Test "Realistic Market Scenario" + PricedComptroller + ListedCToken ZRX cZRX + SetPriceCF cZRX 0.002 0.4 + ListedEtherToken cETH + Comptroller SetCollateralFactor cEth 0.8 + ListedCToken BAT cBAT + SetPriceCF cBAT 0.0015 0.3 + -- Mint some cZRX and cETH + Prep Geoff 1250e18 ZRX cZRX + Mint Geoff 1250e18 cZRX -- Liquidity -> 0.4 * 0.002 * 1250e18 = 1.0e18 + SendMintEth Geoff 2.5e18 cETH -- Liqiuidity -> 0.8 * 1.0 * 2.5e18 = 2.0e18 + -- Check liquidity is zero when not in any markets + Assert Equal (Comptroller Liquidity Geoff) Zero + -- Enter ZRX and check liquidity + EnterMarkets Geoff cZRX + Assert Equal (Comptroller Liquidity Geoff) 1.0e18 + -- Try to borrow BAT but fail + HoldInvariants + Borrow Geoff 1.0e27 cBAT + Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION MARKET_NOT_ENTERED + -- Enter BAT for borrowing + EnterMarkets Geoff cBAT + -- Fail to borrow BAT due to liquidity + Give cBAT 1000e18 BAT + HoldInvariants + Borrow Geoff 1000e18 cBAT -- 1000e18 * 0.0015 = 1.5e18 required liquidity + -- But since we're only in ZRX, we only have 1.0e18 liquidity + Assert Failure COMPTROLLER_REJECTION BORROW_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY + -- Enter cETH and check liquidity + EnterMarkets Geoff cETH + Assert Equal (Comptroller Liquidity Geoff) 3.0e18 -- Sum of cETH and cZRX liquidity from above + -- Borrow previous BAT amount given liquidity + Borrow Geoff 1000e18 cBAT + Assert Equal (Comptroller Liquidity Geoff) 1.5e18 -- Less the borrow amount's toll + -- Try to exit a eth market but fail due to given borrow requiring eth as collateral + HoldInvariants + ExitMarket Geoff cETH + Assert Failure REJECTION EXIT_MARKET_REJECTION INSUFFICIENT_LIQUIDITY -- Liquidity check fails + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cBAT) (Address cETH)] + -- Repay some borrow and exit market OMG + Allow Geoff cBAT + RepayBorrow Geoff 500e18 cBAT + Assert Equal (Comptroller Liquidity Geoff) 2.25e18 -- With 0.75e18 repaid + ExitMarket Geoff cETH + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cBAT)] + Assert Equal (Comptroller Liquidity Geoff) 0.25e18 -- Less Eth's 2.0e18 collateral weight + -- Try and exit cBAT (firist without, then after, repaying) + HoldInvariants + ExitMarket Geoff cBAT + Assert Failure NONZERO_BORROW_BALANCE EXIT_MARKET_BALANCE_OWED + RepayBorrow Geoff Max cBAT + ExitMarket Geoff cBAT + Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX)] + Assert Equal (Comptroller Liquidity Geoff) 1.0e18 -- Back to just cZRX + -- Exit cZRX + ExitMarket Geoff cZRX + Assert Equal (Comptroller AssetsIn Geoff) [] + Assert Equal (Comptroller Liquidity Geoff) 0e18 -- Back to nothing diff --git a/spec/scenario/Excel.scen.old b/spec/scenario/Excel.scen.old new file mode 100644 index 000000000..f2cb486cc --- /dev/null +++ b/spec/scenario/Excel.scen.old @@ -0,0 +1,119 @@ +-- Auto-generated tests from Excel + +Test "Excel Scenario 1 https://docs.google.com/spreadsheets/d/14kRju5M3t0wL-OPSNPV-j1raXgArb0IdsL7hMqKQuyI/edit#gid=1178589286" + -- Excel Base Setup + SetOriginationFee "0" + SetCollateralRatio "1.1" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) WhitepaperRate SimplePolicyHook + AddToken OMG + SupportMarket OMG (FixedPrice 0.05) WhitepaperRate SimplePolicyHook + Approve Bank Ether "1e30" + Approve Bank OMG "1e30" + Approve Geoff Ether "1e30" + Approve Geoff OMG "1e30" + Approve Torrey Ether "1e30" + Approve Torrey OMG "1e30" + Approve Robert Ether "1e30" + Approve Robert OMG "1e30" + Faucet Bank Ether "1e30" + Faucet Bank OMG "1e30" + Faucet Geoff Ether "1e30" + Faucet Geoff OMG "1e30" + Faucet Torrey Ether "1e30" + Faucet Torrey OMG "1e30" + Faucet Robert Ether "1e30" + Faucet Robert OMG "1e30" + -- + -- Scenario 1 + Supply Bank Ether "1000.00000000e18" + Assert Success + Assert Equal (SupplyBalance Bank Ether) (Precisely "1000.00000000e18") + Supply Bank OMG "3000.00000000e18" + Assert Success + Assert Equal (SupplyBalance Bank OMG) (Precisely "3000.00000000e18") + FastForward 20 Blocks + Supply Geoff Ether "200.00000000e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Precisely "200.00000000e18") + FastForward 10 Blocks + EnterMarkets Geoff OMG + Borrow Geoff OMG "2500.00000000e18" + Assert Success + Assert Equal (BorrowBalance Geoff OMG) (Precisely "2500.00000000e18") + FastForward 10 Blocks + Supply Torrey OMG "2500.00000000e18" + Assert Success + Assert Equal (SupplyBalance Torrey OMG) (Precisely "2500.00000000e18") + FastForward 10 Blocks + EnterMarkets Torrey Ether + Borrow Torrey Ether "97.00000000e18" + Assert Success + Assert Equal (BorrowBalance Torrey Ether) (Precisely "97.00000000e18") + FastForward 10 Blocks + Withdraw Bank Ether "780.00000000e18" + Assert Success + Assert Equal (SupplyBalance Bank Ether) (Precisely "220.00002988e18") + FastForward 10 Blocks + Withdraw Bank OMG "2000.00000000e18" + Assert Success + Assert Equal (SupplyBalance Bank OMG) (Precisely "1000.00900609e18") + FastForward 10 Blocks + Supply Robert OMG "5000.00000000e18" + Assert Success + Assert Equal (SupplyBalance Robert OMG) (Precisely "5000.00000000e18") + FastForward 10 Blocks + EnterMarkets Robert Ether + Borrow Robert Ether "115.00000000e18" + Assert Success + Assert Equal (BorrowBalance Robert Ether) (Precisely "115.00000000e18") + FastForward 10 Blocks + PayBorrow Geoff OMG "2000.00000000e18" + Assert Success + Assert Equal (BorrowBalance Geoff OMG) (Precisely "500.02288785e18") + FastForward 10 Blocks + Withdraw Geoff Ether "30.00000000e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Precisely "170.00033682e18") + FastForward 40 Blocks + Withdraw Robert OMG "1000.00000000e18" + Assert Success + Assert Equal (SupplyBalance Robert OMG) (Precisely "4000.00277737e18") + +Test "Excel Scenario 2 https://docs.google.com/spreadsheets/d/14kRju5M3t0wL-OPSNPV-j1raXgArb0IdsL7hMqKQuyI/edit#gid=585013245" + -- Excel Base Setup + SetOriginationFee "0" + SetCollateralRatio "1.1" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) WhitepaperRate SimplePolicyHook + AddToken OMG + SupportMarket OMG (FixedPrice 0.05) WhitepaperRate SimplePolicyHook + Approve Bank Ether "1e30" + Approve Bank OMG "1e30" + Approve Geoff Ether "1e30" + Approve Geoff OMG "1e30" + Approve Torrey Ether "1e30" + Approve Torrey OMG "1e30" + Approve Robert Ether "1e30" + Approve Robert OMG "1e30" + Faucet Bank Ether "1e30" + Faucet Bank OMG "1e30" + Faucet Geoff Ether "1e30" + Faucet Geoff OMG "1e30" + Faucet Torrey Ether "1e30" + Faucet Torrey OMG "1e30" + Faucet Robert Ether "1e30" + Faucet Robert OMG "1e30" + -- + -- Scenario 2 + Supply Geoff Ether "1000.00000000e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Precisely "1000.00000000e18") + EnterMarkets Geoff Ether + Borrow Geoff Ether "310.00000000e18" + Assert Success + Assert Equal (BorrowBalance Geoff Ether) (Precisely "310.00000000e18") + FastForward 40 Blocks + Supply Geoff Ether "0.00000000e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Precisely "1000.00100590e18") diff --git a/spec/scenario/ExchangeRate.scen b/spec/scenario/ExchangeRate.scen new file mode 100644 index 000000000..2db30838b --- /dev/null +++ b/spec/scenario/ExchangeRate.scen @@ -0,0 +1,73 @@ + +Test "Initial Exchange Rate" + NewComptroller + NewCToken ZRX cZRX initialExchangeRate:2e9 + Assert Equal (CToken cZRX ExchangeRateStored) (Exp 2e9) + +Test "Initial Exchange Rate with Mint" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:5e9 + -- Check initial exchange holds + Invariant Remains (CToken cZRX ExchangeRateStored) (Exp 5e9) + -- Mint some tokens and verify invariant still holds + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + -- Also, verify token was minted at given exchange rate + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 10e9) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 10e9) + -- Let's mint again and verify it's still good. + Prep Torrey Some ZRX cZRX + Mint Torrey 50e18 cZRX + -- Also, verify token was minted at given exchange rate + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 20e9) + Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 10e9) + +Test "ZRX: Exch. Rate:2e9, Cash(51e18) + Borrows(2.0e18) - Reserves(0.5e18) / Tokens(2.5e10)" + NewComptroller + -- Decimals You=18, Decimals Us=8 -> 2e9 Exchange Rate + ListedCToken ZRX cZRX initialExchangeRate:2e9 decimals:8 + Assert Equal (CToken cZRX ExchangeRateStored) (Exp 2e9) + -- Mint 50.0 ZRX at given exchange rate + Prep Geoff Some ZRX cZRX + Assert Equal (Erc20 cZRX TotalSupply) Zero + Mint Geoff 50e18 cZRX + -- 50e18 / 2e9 = 2.5e10 + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2.5e10) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2.5e10) + -- Set cash + Erc20 ZRX Faucet cZRX 1.0e18 + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 51.0e18) + -- Mock total borrows + CToken cZRX Mock totalBorrows 2.0e18 + Assert Equal (CToken cZRX TotalBorrows) (Exactly 2.0e18) + -- Mock total reserves + CToken cZRX Mock totalReserves 0.5e18 + Assert Equal (CToken cZRX Reserves) (Exactly 0.5e18) + -- Okay, we're all set, let's check the exchange rate + -- (51+2-0.5)e18/2.5e10 = 52.5e18/2.5e10 = 21e8 -> 21e26 (Exp) + Assert Equal (CToken cZRX ExchangeRateStored) (Exp 2.1e9) + +Test "USDC: Exch. Rate:2e-3, Cash(51e18) + Borrows(2.0e18) - Reserves(0.5e18) / Tokens(2.5e10)" + NewComptroller + -- Decimals You=6, Decimals Us=8 -> 2e-3 Exchange Rate + ListedCToken USDC cUSDC initialExchangeRate:2e-3 decimals:8 + Assert Equal (CToken cUSDC ExchangeRateStored) (Exp 2e-3) + -- Mint 50.0 USDC at given exchange rate + Prep Geoff Little USDC cUSDC + Assert Equal (Erc20 cUSDC TotalSupply) (Exactly 0.0) + Mint Geoff 50e6 cUSDC + -- 5.0e7 / 2e-3 = 2.5e10 + Assert Equal (Erc20 cUSDC TotalSupply) (Exactly 2.5e10) + Assert Equal (Erc20 cUSDC TokenBalance Geoff) (Exactly 2.5e10) + -- Set cash + Erc20 USDC Faucet cUSDC 2.0e6 + Assert Equal (Erc20 USDC TokenBalance cUSDC) (Exactly 52.0e6) + -- Mock total borrows + CToken cUSDC Mock totalBorrows 5.0e6 + Assert Equal (CToken cUSDC TotalBorrows) (Exactly 5.0e6) + -- Mock total reserves + CToken cUSDC Mock totalReserves 1.5e6 + Assert Equal (CToken cUSDC Reserves) (Exactly 1.5e6) + -- Okay, we're all set, let's check the exchange rate + -- (52+5-1.5)e6/2.5e10 = 55.5e6/2.5e10 = 2.22e-3 -> 2.22e15 (Exp) + Assert Equal (CToken cUSDC ExchangeRateStored) (Exp 2.22e-3) diff --git a/spec/scenario/HypotheticalAccountLiquidity.scen b/spec/scenario/HypotheticalAccountLiquidity.scen new file mode 100644 index 000000000..0028795fc --- /dev/null +++ b/spec/scenario/HypotheticalAccountLiquidity.scen @@ -0,0 +1,49 @@ + +Test "Calculates hypothetical account liquidity" + -- Note, this comes a bit from `EnterExitMarkets` Scenario + PricedComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + SetPriceCF cZRX 0.002 0.4 + ListedEtherToken cETH initialExchangeRate:1e9 + Comptroller SetCollateralFactor cEth 0.8 + ListedCToken BAT cBAT initialExchangeRate:1e9 + SetPriceCF cBAT 0.0015 0.3 + ListedCToken OMG cOMG initialExchangeRate:1e9 + NewCToken REP cREP + -- Mint some cZRX and cETH + Prep Geoff 1250e18 ZRX cZRX + Mint Geoff 1250e18 cZRX -- Liquidity -> 0.4 * 0.002 * 1250e18 = 1.0e18 + SendMintEth Geoff 2.5e18 cETH -- Liqiuidity -> 0.8 * 1.0 * 2.5e18 = 2.0e18 + -- Check liquidity is zero when not in any markets + Assert Equal (Comptroller Liquidity Geoff) Zero + -- Enter ZRX and check liquidity + EnterMarkets Geoff cZRX + Assert Equal (Comptroller Liquidity Geoff) 1.0e18 + -- Now let's look at some hypotheticals + Assert Equal (Comptroller Hypothetical Geoff Redeems 1000e9 cZRX) 0.2e18 -- 0.4 * 0.002 * -1000e18 = -0.8e18 + Assert Equal (Comptroller Hypothetical Geoff Borrows 1000e18 cZRX) -1e18 -- 0.002 * -1000e18 = -2e18 + -- Note, if you're not in an asset, this function returns no effect + Assert Equal (Comptroller Hypothetical Geoff Redeems 0.002e9 cETH) 1.0e18 -- 0.8 * 1000.0 * -0.002e18 = -1.6e18 + Assert Equal (Comptroller Hypothetical Geoff Borrows 0.002e18 cETH) 1.0e18 -- 1000.0 * -0.002e18 = -2e18 + EnterMarkets Geoff cETH + Assert Equal (Comptroller Liquidity Geoff) 3.0e18 + Assert Equal (Comptroller Hypothetical Geoff Redeems 1000e9 cZRX) 2.2e18 -- 0.4 * 0.002 * -1000e18 = -0.8e18 + Assert Equal (Comptroller Hypothetical Geoff Borrows 1000e18 cZRX) 1e18 -- 0.002 * -1000e18 = -2e18 + Assert Equal (Comptroller Hypothetical Geoff Redeems 2e9 cETH) 1.4e18 -- 0.8 * 1.0 * -2e18 = -1.6e18 + Assert Equal (Comptroller Hypothetical Geoff Borrows 2e18 cETH) 1.0e18 -- 1.0 * -2e18 = -2e18 + EnterMarkets Geoff cBAT + Assert Equal (Comptroller Hypothetical Geoff Redeems 1000e9 cBAT) 2.55e18 -- 0.3 * 0.0015 * -1000e18 = -0.45e18e18 + Assert Equal (Comptroller Hypothetical Geoff Borrows 1000e18 cBAT) 1.5e18 -- 0.0015 * -1000e18 = -1.5e18 + EnterMarkets Geoff cOMG + -- Fails if the given asset doesn't have a price + Assert ReadError (Comptroller Hypothetical Geoff Redeems 1e20 cOMG) "Failed to compute account hypothetical liquidity: error code = 13" + Assert ReadError (Comptroller Hypothetical Geoff Borrows 1e20 cOMG) "Failed to compute account hypothetical liquidity: error code = 13" + PriceOracle SetPrice cOMG 0.01 + -- Has a price and now is listed + Assert Equal (Comptroller Hypothetical Geoff Redeems 100e9 cOMG) 3.0e18 -- No collateral factor + Assert Equal (Comptroller Hypothetical Geoff Borrows 100e18 cOMG) 2.0e18 -- 0.01 * -100e18 = -1e18 + -- For a token has no price and isn't listed + -- Note: we can't actually enter the unlisted market without some harness function + -- we could consider testing this, but it would be out of the scope of scenarios + Assert Equal (Comptroller Hypothetical Geoff Redeems 100e18 cREP) 3.0e18 -- No effect + Assert Equal (Comptroller Hypothetical Geoff Borrows 100e18 cREP) 3.0e18 -- No effect diff --git a/spec/scenario/Liquidate.scen b/spec/scenario/Liquidate.scen new file mode 100644 index 000000000..e47f60f7d --- /dev/null +++ b/spec/scenario/Liquidate.scen @@ -0,0 +1,520 @@ + +Macro NewBorrow borrowAmount borrowRate user=Geoff collateralPrice=1.0 borrowPrice=1.0 mintAmount=100e18 collateralTokenType=Standard borrowTokenType=Standard + PricedComptroller + Comptroller LiquidationIncentive 1.1 + NewCToken ZRX cZRX 0.0005 2e9 8 collateralTokenType + NewCToken BAT cBAT borrowRate 2e9 8 borrowTokenType -- note: cannot use macros with named args right now + Give cBAT 10e18 BAT -- Faucet some bat to borrow + PriceOracle SetPrice cZRX collateralPrice + Support cZRX collateralFactor:0.5 + PriceOracle SetPrice cBAT borrowPrice + Support cBAT collateralFactor:0 + SimpleBorrow user borrowAmount mintAmount + +Macro SimpleBorrow user borrowAmount mintAmount + Prep user mintAmount ZRX cZRX + Mint user mintAmount cZRX + EnterMarkets user cZRX cBAT + Borrow user borrowAmount cBAT + +Test "Insufficient shortfall" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 98000 Blocks -- 1e18 * (1 + 98000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 50e18 + Assert Equal (CToken cBAT TotalBorrows) 50e18 + -- Check user liquidity and verify equals 0 + Assert Equal (Comptroller Liquidity Geoff) 0e18 + -- At exactly zero, should not be able to liquidate + Prep Torrey 10e18 BAT cBAT + AllowFailures + Liquidate Torrey "->" Geoff 10e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION INSUFFICIENT_SHORTFALL + +Test "Cannot self-liquidate" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Assert Equal (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Geoff 10e18 BAT cBAT + AllowFailures + Liquidate Geoff "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure INVALID_ACCOUNT_PAIR LIQUIDATE_LIQUIDATOR_IS_BORROWER + +Test "Liqidate beyond max close" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Assert Equal (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + AllowFailures + Liquidate Torrey "->" Geoff 10e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION TOO_MUCH_REPAY + +Test "Proper liquidation with 1:1 price ratio" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices are 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a lot of blocks at a 0.05% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Assert Equal (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 -- recheck + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 2e18 BAT cBAT + -- + -- Let's check how values start before liqudation + -- Note: we're going to be some-what exhausive in what we check + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 0e18 -- all was minted + Invariant Remains (Erc20 ZRX TokenBalance Torrey) 0e18 -- didn't have any beforehand + Invariant Remains (Erc20 ZRX TokenBalance cZRX) 100e18 -- from minting + Assert Equal (Erc20 cZRX TokenBalance Geoff) 50e9 -- from minting + Assert Equal (Erc20 cZRX TokenBalance Torrey) 0e9 -- never had any + Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- original amount borrowed + Assert Equal (Erc20 BAT TokenBalance Torrey) 2e18 -- from prep above + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 -- had 10e18, lent 1e18 to geoff + Invariant Remains (Erc20 cBAT TokenBalance Geoff) 0e9 -- never had any (has underlying) + Invariant Remains (Erc20 cBAT TokenBalance Torrey) 0e9 -- never had any + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 -- all that interest + Assert Equal (CToken cBAT TotalBorrows) 51e18 -- all those borrowers + -- Do the liquidation + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + -- + -- And see what they are now + Assert Equal (Erc20 cZRX TokenBalance Geoff) 48.9e9 -- 1:1 -> 2e18 x 1.1 ÷ 2e19 [exchange rate] = 1.1e9 -> Torrey + Assert Equal (Erc20 cZRX TokenBalance Torrey) 1.1e9 -- never had any + Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 -- repaid + Assert Equal (Erc20 BAT TokenBalance cBAT) 11e18 -- had 10e18, lent 1e18 to geoff, repaid 2 + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 49e18 -- less closed amount + Assert Equal (CToken cBAT TotalBorrows) 49e18 -- + -- Prices are 1:1 and collateral factor is 0.5 + -- User now has 48.9 outstanding supply (yielding 48.9e18 borrowing capacity) + -- The user also has a 49e18 borrow outstanding. + -- Thus the liquidity is (48.9-49)e18 or -0.1e18. + Assert Equal (Comptroller Liquidity Geoff) -0.1e18 + +Test "Proper liquidation with 2:1 price ratio" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 borrowPrice:2.0 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices are 2:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a lot blocks at a 0.05% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Assert Equal (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -52e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 2.0 * 51e18 ) ) / 1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 2e18 BAT cBAT + -- + -- Let's check how values start before liqudation + -- Note: we're going to be some-what exhausive in what we check + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 0e18 -- all was minted + Invariant Remains (Erc20 ZRX TokenBalance Torrey) 0e18 -- never had any + Invariant Remains (Erc20 ZRX TokenBalance cZRX) 100e18 -- from minting + Assert Equal (Erc20 cZRX TokenBalance Geoff) 50e9 -- from minting + Assert Equal (Erc20 cZRX TokenBalance Torrey) 0e9 -- never had any + Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- original amount borrowed + Assert Equal (Erc20 BAT TokenBalance Torrey) 2e18 -- from prep above + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 -- had 10e18, lent 1e18 to geoff + Invariant Remains (Erc20 cBAT TokenBalance Geoff) 0e9 -- never had any (has underlying) + Invariant Remains (Erc20 cBAT TokenBalance Torrey) 0e9 -- never had any + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 -- all that interest + Assert Equal (CToken cBAT TotalBorrows) 51e18 -- all those borrowers + -- Do the liquidation + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX -- should now take twice as much collateral + -- + -- And see what they are now + Assert Equal (Erc20 cZRX TokenBalance Geoff) 47.8e9 -- 2:1 -> 2 x 2e18 x 1.1 ÷ 2e19 [exchange rate] = 2.2e9 -> Torrey + Assert Equal (Erc20 cZRX TokenBalance Torrey) 2.2e9 -- didn't have any beforehand + Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 -- repaid + Assert Equal (Erc20 BAT TokenBalance cBAT) 11e18 -- had 10e18, lent 1e18 to geoff, repaid 2 + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 49e18 -- less closed amount + Assert Equal (CToken cBAT TotalBorrows) 49e18 -- + -- Prices are 2:1 and collateral factor is 0.5 + -- User now has 47.8 outstanding supply (yielding 48.9e18 borrowing capacity due + -- to the offsetting collateral factor and exchange rates). + -- The user also has a 49e18 borrow outstanding which is weighted 2:1. + -- Thus the liquidity is (47.8-(2*49))e18 or -50.2e18. + Assert Equal (Comptroller Liquidity Geoff) -50.2e18 + +Test "Liquidate exactly zero" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Invariant Remains (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + AllowFailures + Liquidate Torrey "->" Geoff 0e18 cBAT "Seizing" cZRX + Assert Failure INVALID_CLOSE_AMOUNT_REQUESTED LIQUIDATE_CLOSE_AMOUNT_IS_ZERO + +Test "When price oracle for collateral token is zero" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + PriceOracle SetPrice cZRX 0 + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION PRICE_ERROR + +Test "When price oracle for collateral token is whack" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + PriceOracle SetPrice cZRX Max + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION MATH_ERROR + +Test "When price oracle for borrow token is zero" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + PriceOracle SetPrice cBAT 0 + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION PRICE_ERROR + +Test "When price oracle for borrow token is whack" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + PriceOracle SetPrice cBAT Max + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION MATH_ERROR + +Test "When repay borrow fails" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Invariant Remains (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT allowanceAmount:0.1e18 + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure TOKEN_INSUFFICIENT_ALLOWANCE REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE + + +Test "Proper liquidation of paused WBTC as collateral" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 collateralTokenType:WBTC + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices are 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a lot of blocks at a 0.05% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Assert Equal (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Assert Equal (Comptroller Liquidity Geoff) -1e18 -- recheck + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 2e18 BAT cBAT + -- + -- Let's check how values start before liqudation + -- Note: we're going to be some-what exhausive in what we check + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 0e18 -- all was minted + Invariant Remains (Erc20 ZRX TokenBalance Torrey) 0e18 -- didn't have any beforehand + Invariant Remains (Erc20 ZRX TokenBalance cZRX) 100e18 -- from minting + Assert Equal (Erc20 cZRX TokenBalance Geoff) 50e9 -- from minting + Assert Equal (Erc20 cZRX TokenBalance Torrey) 0e9 -- never had any + Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- original amount borrowed + Assert Equal (Erc20 BAT TokenBalance Torrey) 2e18 -- from prep above + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 -- had 10e18, lent 1e18 to geoff + Invariant Remains (Erc20 cBAT TokenBalance Geoff) 0e9 -- never had any (has underlying) + Invariant Remains (Erc20 cBAT TokenBalance Torrey) 0e9 -- never had any + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 51e18 -- all that interest + Assert Equal (CToken cBAT TotalBorrows) 51e18 -- all those borrowers + -- Pause "WBTC" + Erc20 ZRX Pause -- Actually a WBTC token + -- Do the liquidation + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + -- + -- And see what they are now + Assert Equal (Erc20 cZRX TokenBalance Geoff) 48.9e9 -- 1:1 -> 2e18 x 1.1 ÷ 2e19 [exchange rate] = 1.1e9 -> Torrey + Assert Equal (Erc20 cZRX TokenBalance Torrey) 1.1e9 -- never had any + Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 -- repaid + Assert Equal (Erc20 BAT TokenBalance cBAT) 11e18 -- had 10e18, lent 1e18 to geoff, repaid 2 + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 49e18 -- less closed amount + Assert Equal (CToken cBAT TotalBorrows) 49e18 -- + -- Prices are 1:1 and collateral factor is 0.5 + -- User now has 48.9 outstanding supply (yielding 48.9e18 borrowing capacity) + -- The user also has a 49e18 borrow outstanding. + -- Thus the liquidity is (48.9-49)e18 or -0.1e18. + Assert Equal (Comptroller Liquidity Geoff) -0.1e18 + + +Test "When WBTC token as borrowed is paused, cannot liquidate" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 borrowTokenType:WBTC + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Check user liquidity and verify < 0 + Invariant Remains (Comptroller Liquidity Geoff) -1e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + AllowFailures + Erc20 BAT Pause -- Actually a WBTC token + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Revert + + +Test "When seize not allowed due to unlisted collateral" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + Comptroller UnList cZRX -- Mock unlist collateral + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + +Test "When seize not allowed due to unlisted borrow" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + Comptroller UnList cBAT -- Mock unlist borrow + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + +Test "When seize not allowed due to mismatched comptrollers" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + -- Change the comptroller of cZRX + NewComptroller + From Root (CToken cZRX SetComptroller (Unitroller Address)) + FastForward 100000 Blocks -- To match other comptroller + -- + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Revert "revert token seizure failed" + +Test "When there's insufficient collateral" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 borrowPrice:0.001 mintAmount:1e18 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrows) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Prices is 1:1 and collateral factor is 0.5 + -- thus supplies 100e18 cZRX which gives the user 50e18 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 1e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 51e18 + Invariant Remains (CToken cBAT TotalBorrows) 51e18 + PriceOracle SetPrice cBAT 1.0 -- move price back to 1.0, which will put the account *very underwater* + -- Check user liquidity and verify < 0 + Invariant Remains (Comptroller Liquidity Geoff) -50.5e18 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + AllowFailures + Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cZRX + Assert Failure TOKEN_INSUFFICIENT_BALANCE LIQUIDATE_SEIZE_TOO_MUCH diff --git a/spec/scenario/Liquidate.scen.old b/spec/scenario/Liquidate.scen.old new file mode 100644 index 000000000..6e8168ab6 --- /dev/null +++ b/spec/scenario/Liquidate.scen.old @@ -0,0 +1,142 @@ +-- Liquidate Tests + +Test "Supply OMG, Borrow Ether, OMG price crashes, Liquidate Ether" + AddToken OMG + SupportMarket OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff OMG "2.1e18" + Faucet Geoff OMG "2.1e18" + Supply Geoff OMG "2.1e18" + Assert Success + Assert Equal (SupplyBalance Geoff OMG) (Exactly "2.1e18") + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Torrey Ether "5.0e18" + Faucet Torrey Ether "5.0e18" + Supply Torrey Ether "2.0e18" + Assert Equal (BalanceSheetSupply OMG) (Exactly "2.1e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "0.0e18") + EnterMarkets Geoff Ether + Borrow Geoff Ether "1e18" + Assert Success + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (TokenBalance Geoff Ether) (Exactly "1e18") -- does not include origination fee + -- + -- Ether total supply unchanged + Assert Equal (BalanceSheetSupply Ether) (Exactly "2.0e18") + -- + -- Crash OMG price and liquidate + SetMarketPriceOracle OMG (FixedPrice "0.5") -- Max liquidate at this price should be maxClose = 1E for all the supply + Liquidate Torrey Geoff Ether "1e18" OMG + Assert Success + Assert Equal (BalanceSheetBorrow Ether) (Exactly "0.05e18") -- borrow was paid by liquidator + Assert Equal (BorrowBalance Geoff Ether) (Exactly "0.05e18") -- target user should have liquidated amount closed on borrow + Assert Equal (BalanceSheetSupply OMG) (Exactly "2.1e18") + Assert Equal (SupplyBalance Geoff OMG) (Exactly "0e18") -- Collateral was the limit in this scenario + Assert Equal (TokenBalance Torrey Ether) (Exactly "2.0e18") -- liquidator token balance should be reduced + Assert Equal (TokenBalance Torrey OMG) (Exactly "0e18") + Assert Equal (SupplyBalance Torrey OMG) (Exactly "2.1e18") -- Liquidator now has seized collateral + +Test "Supply OMG, Borrow Ether, gain interest, OMG price crashes, Liquidate Ether" + AddToken OMG + SupportMarket OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff OMG "2.1e18" + Faucet Geoff OMG "2.1e18" + Supply Geoff OMG "2.1e18" + Assert Success + Assert Equal (SupplyBalance Geoff OMG) (Exactly "2.1e18") + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Torrey Ether "20.0e18" + Faucet Torrey Ether "20.0e18" + Supply Torrey Ether "10.0e18" + Assert Equal (BalanceSheetSupply OMG) (Exactly "2.1e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "0.0e18") + EnterMarkets Geoff Ether + Borrow Geoff Ether "1e18" + Assert Success + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.05e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "1e18") -- does not include origination fee + FastForward 2 Blocks + -- + -- Crash OMG price and liquidate + SetMarketPriceOracle OMG (FixedPrice "0.8") -- Max liquidate at this price should be maxClose ~ 1.98947 E to meet collateral ratio + Liquidate Torrey Geoff Ether "2e18" OMG + Assert Failure INVALID_CLOSE_AMOUNT_REQUESTED LIQUIDATE_CLOSE_AMOUNT_TOO_HIGH + Liquidate Torrey Geoff Ether "1.5e18" OMG + Assert Success + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.125e18") -- (1.05) * ( 1 + 2 * .75 ) - 1.5 + Assert Equal (BalanceSheetSupply OMG) (Exactly "4.2e18") + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.125e18") + Assert Equal (SupplyBalance Geoff OMG) (Exactly "2.23125e18") -- (2.1) * (1 + 2 * .5) - 1.96875 [amountSeize] + Assert Equal (TokenBalance Torrey Ether) (Exactly "8.5e18") + Assert Equal (SupplyBalance Torrey Ether) (Exactly "20e18") -- (10) * (1 + 2 * .5) + Assert Equal (TokenBalance Torrey OMG) (Exactly "0e18") + Assert Equal (SupplyBalance Torrey OMG) (Exactly "1.96875e18") + +Test "Can't liquidate when contract is borrow asset is paused" + AddToken OMG + SupportMarket OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff OMG "2.1e18" + Faucet Geoff OMG "2.1e18" + Supply Geoff OMG "2.1e18" + Assert Success + Assert Equal (SupplyBalance Geoff OMG) (Exactly "2.1e18") + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Torrey Ether "5.0e18" + Faucet Torrey Ether "5.0e18" + Supply Torrey Ether "2.0e18" + Assert Equal (BalanceSheetSupply OMG) (Exactly "2.1e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "0.0e18") + EnterMarkets Geoff Ether + Borrow Geoff Ether "1e18" + Assert Success + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (TokenBalance Geoff Ether) (Exactly "1e18") -- does not include origination fee + -- + -- Ether total supply unchanged + Assert Equal (BalanceSheetSupply Ether) (Exactly "2.0e18") + -- + -- Crash OMG price and liquidate + SetMarketPriceOracle OMG (FixedPrice "0.5") -- Max liquidate at this price should be maxClose = 1E for all the supply + PolicyHook Ether (SetPaused True) + Liquidate Torrey Geoff Ether "1e18" OMG + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_POLICY_HOOK_ASSET_BORROW_REJECTION 1 + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.05e18") -- unchanged + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.05e18") -- unchanged + +Test "Can't liquidate when contract is collateral asset is paused" + AddToken OMG + SupportMarket OMG (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff OMG "2.1e18" + Faucet Geoff OMG "2.1e18" + Supply Geoff OMG "2.1e18" + Assert Success + Assert Equal (SupplyBalance Geoff OMG) (Exactly "2.1e18") + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Torrey Ether "5.0e18" + Faucet Torrey Ether "5.0e18" + Supply Torrey Ether "2.0e18" + Assert Equal (BalanceSheetSupply OMG) (Exactly "2.1e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "0.0e18") + EnterMarkets Geoff OMG Ether + Borrow Geoff Ether "1e18" + Assert Success + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.05e18") -- includes origination fee + Assert Equal (TokenBalance Geoff Ether) (Exactly "1e18") -- does not include origination fee + -- + -- Ether total supply unchanged + Assert Equal (BalanceSheetSupply Ether) (Exactly "2.0e18") + -- + -- Crash OMG price and liquidate + SetMarketPriceOracle OMG (FixedPrice "0.5") -- Max liquidate at this price should be maxClose = 1E for all the supply + PolicyHook OMG (SetPaused True) + Liquidate Torrey Geoff Ether "1e18" OMG + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_POLICY_HOOK_ASSET_COLLATERAL_REJECTION 1 + Assert Equal (BalanceSheetBorrow Ether) (Exactly "1.05e18") -- unchanged + Assert Equal (BorrowBalance Geoff Ether) (Exactly "1.05e18") -- unchanged diff --git a/spec/scenario/LiquidateEthBorrow.scen b/spec/scenario/LiquidateEthBorrow.scen new file mode 100644 index 000000000..dd4657dbe --- /dev/null +++ b/spec/scenario/LiquidateEthBorrow.scen @@ -0,0 +1,138 @@ +Macro NewBorrow borrowAmount borrowRate user=Geoff + PricedComptroller 0.5 20 + Comptroller LiquidationIncentive 1.1 + ListedCToken BAT cBAT + ListedEtherToken cETH initialExchangeRate:0.05e9 + PriceOracle SetPrice cBAT 0.001 + SetCollateralFactor cBAT collateralFactor:0.5 + Donate cETH 0.001e18 + SimpleBorrow user borrowAmount + +Macro SimpleBorrow user borrowAmount + Prep user 100e18 BAT cBAT + Mint user 100e18 cBAT + EnterMarkets user cETH cBAT + Assert Equal (Comptroller Liquidity Geoff) 0.05e18 + Expect Changes (EtherBalance user) +0.001e18 + Expect Changes (EtherBalance cETH) -0.001e18 + BorrowEth user borrowAmount cETH + +Test "Insufficient shortfall" + NewBorrow borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrows) 0.001e18 + -- Prices is 1:1000 and collateral factor is 0.5 + -- thus supplies 100.0e18 cBAT which gives the user (0.5 * 100.0e18 * 1.0e-3)=0.05e18 + -- capacity of Eth. User only borrowed 0.001e18, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 98000 Blocks -- 0.001e18 * (1 + 98000 * 0.0005) + AccrueInterest cETH -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cETH BorrowBalanceStored Geoff) 0.05e18 + Assert Equal (CToken cETH TotalBorrows) 0.05e18 + -- Check user liquidity and verify equals 0 + -- At exactly zero, should not be able to liquidate + AllowFailures + Invariant Remains (Comptroller Liquidity Geoff) 0e18 + Invariant Static (EtherBalance Geoff) + Invariant Static (EtherBalance Torrey) + LiquidateEthBorrow Torrey "->" Geoff 10e18 cETH "Seizing" cBAT + Assert RevertFailure COMPTROLLER_REJECTION "revert liquidateBorrow failed" + +Test "Cannot self-liquidate" + NewBorrow borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrows) 0.001e18 + -- Prices is 1:1000 and collateral factor is 0.5 + -- thus supplies 100.0e18 cBAT which gives the user (0.5 * 100.0e18 * 1.0e-3)=0.05e18 + -- capacity of Eth. User only borrowed 0.001e18, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 0.001e18 * (1 + 100000 * 0.0005) + AccrueInterest cETH -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cETH BorrowBalanceStored Geoff) 0.051e18 + Assert Equal (CToken cETH TotalBorrows) 0.051e18 + -- Check user liquidity and verify < 0 + -- ( 0.5 * 100e18 * 1e-3 ) - ( 0.051e18 * 1.0 ) = -0.001e18 + Assert Equal (Comptroller Liquidity Geoff) -0.001e18 + -- Okay, so we should be able to liquidate, so let's do that. + AllowFailures + Invariant Remains (Comptroller Liquidity Geoff) -0.001e18 + Invariant Static (EtherBalance Geoff) + LiquidateEthBorrow Geoff "->" Geoff 0.002e18 cETH "Seizing" cBAT + Assert RevertFailure INVALID_ACCOUNT_PAIR "revert liquidateBorrow failed" + +Test "Liqidate beyond max close" + NewBorrow borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrows) 0.001e18 + -- Prices is 1:1000 and collateral factor is 0.5 + -- thus supplies 100.0e18 cBAT which gives the user (0.5 * 100.0e18 * 1.0e-3)=0.05e18 + -- capacity of Eth. User only borrowed 0.001e18, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 0.001e18 * (1 + 100000 * 0.0005) + AccrueInterest cETH -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cETH BorrowBalanceStored Geoff) 0.051e18 + Assert Equal (CToken cETH TotalBorrows) 0.051e18 + -- Check user liquidity and verify < 0 + -- ( 0.5 * 100e18 * 1e-3 ) - ( 0.051e18 * 1.0 ) = -0.001e18 + Assert Equal (Comptroller Liquidity Geoff) -0.001e18 + -- Okay, so we should be able to liquidate, so let's do that. + AllowFailures + Invariant Remains (Comptroller Liquidity Geoff) -0.001e18 + Invariant Static (EtherBalance Geoff) + Invariant Static (EtherBalance Torrey) + LiquidateEthBorrow Torrey "->" Geoff 0.04e18 cETH "Seizing" cBAT + Assert RevertFailure COMPTROLLER_REJECTION "revert liquidateBorrow failed" + +Test "Proper liquidation" + NewBorrow borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrows) 0.001e18 + -- Prices is 1:1000 and collateral factor is 0.5 + -- thus supplies 100.0e18 cBAT which gives the user (0.5 * 100.0e18 * 1.0e-3)=0.05e18 + -- capacity of Eth. User only borrowed 0.001e18, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 0.001e18 * (1 + 100000 * 0.0005) + AccrueInterest cETH -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cETH BorrowBalanceStored Geoff) 0.051e18 + Assert Equal (CToken cETH TotalBorrows) 0.051e18 + -- Check user liquidity and verify < 0 + -- ( 0.5 * 100e18 * 1e-3 ) - ( 0.051e18 * 1.0 ) = -0.001e18 + Assert Equal (Comptroller Liquidity Geoff) -0.001e18 + -- Okay, so we should be able to liquidate, so let's do that. + -- + -- Let's check how values start before liqudation + -- Note: we're going to be some-what exhausive in what we check + Invariant Static (EtherBalance Geoff) -- ether balance stays the same for borrower + Expect Changes (EtherBalance Torrey) -0.02e18 -- for the repay behalf + Expect Changes (EtherBalance cETH) +0.02e18 -- receives repay + Assert Equal (Erc20 cBAT TokenBalance Geoff) 500e8 -- from minting (100e18 / 2e9) + Expect Changes (Erc20 cBAT TokenBalance Geoff) -110e8 -- from seize loss + Assert Equal (Erc20 cBAT TokenBalance Torrey) 0e9 -- never had any + Expect Changes (Erc20 cBAT TokenBalance Torrey) +110e8 -- from seize gain + Invariant Remains (Erc20 cETH TokenBalance Geoff) 0e8 -- never had any (has underlying) + Invariant Remains (Erc20 cETH TokenBalance Torrey) 0e8 -- never had any + Assert Equal (CToken cETH BorrowBalanceStored Geoff) 0.051e18 -- all that interest + Assert Equal (CToken cETH TotalBorrows) 0.051e18 -- all those borrowers + Assert Equal (Comptroller Liquidity Geoff) -0.001e18 -- underwater + -- + -- Do the liquidation + LiquidateEthBorrow Torrey "->" Geoff 0.02e18 cETH "Seizing" cBAT + -- + -- And see what they are now + Assert Equal (Erc20 cBAT TokenBalance Torrey) 110e8 -- 0.02e18 * (1/1.0e-3) * 1.1 / 2e9 [exchange rate] = 110e8 -> Torrey + Assert Equal (Erc20 cBAT TokenBalance Geoff) 390e8 + Assert Equal (CToken cETH BorrowBalanceStored Geoff) 0.031e18 -- less closed amount + Assert Equal (CToken cETH TotalBorrows) 0.031e18 -- + -- TODO:! + -- User now has 390e18 cBAT outstanding supply + -- capacity. The user also has a 0.031e18 borrow cETH outstanding. + -- ( 0.5 * 390e8 * 2e9 * 0.001 ) - ( 0.031e18 * 1.0 ) = 0.008e18 + Assert Equal (Comptroller Liquidity Geoff) 0.008e18 diff --git a/spec/scenario/LiquidateEthCollateral.scen b/spec/scenario/LiquidateEthCollateral.scen new file mode 100644 index 000000000..cad8400fb --- /dev/null +++ b/spec/scenario/LiquidateEthCollateral.scen @@ -0,0 +1,140 @@ +Macro NewBorrow borrowAmount user=Geoff + PricedComptroller 0.1 20 + Comptroller LiquidationIncentive 1.1 + ListedCToken BAT cBAT borrowRate:0.0005 + ListedEtherToken cETH initialExchangeRate:0.05e9 + PriceOracle SetPrice cBAT 0.001 + Give cBAT 10e18 BAT + Comptroller SetCollateralFactor cETH 0.5 + SimpleBorrow user borrowAmount + +Macro SimpleBorrow user borrowAmount + CallMintEth user 0.001e18 cETH + EnterMarkets user cETH cBAT + Borrow user borrowAmount cBAT + +Test "Insufficient shortfall" + NewBorrow borrowAmount:0.01e18 + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.01e18 + Assert Equal (CToken cBAT TotalBorrows) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9.99e18 + -- Prices is 1:1.0e-3 and collateral factor is 0.5 + -- thus supplies 1e15 cETH which gives the user (0.5 x 1.0e15 ÷ 1.0e-3)=0.5 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 98000 Blocks -- 0.01e18 * (1 + 98000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 0.5e18 + Assert Equal (CToken cBAT TotalBorrows) 0.5e18 + -- Check user liquidity and verify equals 0 + Assert Equal (Comptroller Liquidity Geoff) 0e18 + -- At exactly zero, should not be able to liquidate + Prep Torrey 10e18 BAT cBAT + AllowFailures + Liquidate Torrey "->" Geoff 10e18 cBAT "Seizing" cETH + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION INSUFFICIENT_SHORTFALL + +Test "Cannot self-liquidate" + NewBorrow borrowAmount:0.01e18 + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.01e18 + Assert Equal (CToken cBAT TotalBorrows) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9.99e18 + -- Prices is 1:1.0e-3 and collateral factor is 0.5 + -- thus supplies 1e15 cETH which gives the user (0.5 x 1.0e15 ÷ 1.0e-3)=0.5 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 0.01e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 0.51e18 + Assert Equal (CToken cBAT TotalBorrows) 0.51e18 + -- Check user liquidity and verify < 0 + -- ( 0.5 * 1.0e15 ) - ( 0.51e18 * 1.0e-3 ) = -1e13 + Assert Equal (Comptroller Liquidity Geoff) -1e13 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Geoff 10e18 BAT cBAT + AllowFailures + Liquidate Geoff "->" Geoff 0.02e18 cBAT "Seizing" cETH + Assert Failure INVALID_ACCOUNT_PAIR LIQUIDATE_LIQUIDATOR_IS_BORROWER + +Test "Liqidate beyond max close" + NewBorrow borrowAmount:0.01e18 + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.01e18 + Assert Equal (CToken cBAT TotalBorrows) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9.99e18 + -- Prices is 1:1.0e-3 and collateral factor is 0.5 + -- thus supplies 1e15 cETH which gives the user (0.5 x 1.0e15 ÷ 1.0e-3)=0.5 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 0.01e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 0.51e18 + Assert Equal (CToken cBAT TotalBorrows) 0.51e18 + -- Check user liquidity and verify < 0 + -- ( 0.5 * 1.0e15 ) - ( 0.51e18 * 1.0e-3 ) = -1e13 + Assert Equal (Comptroller Liquidity Geoff) -1e13 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 10e18 BAT cBAT + AllowFailures + Liquidate Torrey "->" Geoff 0.2e18 cBAT "Seizing" cETH + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_COMPTROLLER_REJECTION TOO_MUCH_REPAY + +Test "Proper liquidation" + NewBorrow borrowAmount:0.01e18 + Assert Equal (CToken cBAT BorrowBalance Geoff) 0.01e18 + Assert Equal (CToken cBAT TotalBorrows) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 0.01e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9.99e18 + -- Prices is 1:1.0e-3 and collateral factor is 0.5 + -- thus supplies 1e15 cETH which gives the user (0.5 x 1.0e15 ÷ 1.0e-3)=0.5 + -- capacity of BAT. User only borrowed 1BAT, but after + -- a few blocks at a 50% interest rate, he'll be + -- underwater. + FastForward 100000 Blocks -- 0.01e18 * (1 + 100000 * 0.0005) + AccrueInterest cBAT -- Note: we have to accrue interest + -- since it's not automatic for liquidity + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 0.51e18 + Assert Equal (CToken cBAT TotalBorrows) 0.51e18 + -- Check user liquidity and verify < 0 + -- ( 0.5 * 1.0e15 ) - ( 0.51e18 * 1.0e-3 ) = -1e13 + Assert Equal (Comptroller Liquidity Geoff) -1e13 + -- Okay, so we should be able to liquidate, so let's do that. + Prep Torrey 0.02e18 BAT cBAT + -- + -- Let's check how values start before liqudation + -- Note: we're going to be some-what exhausive in what we check + Invariant Static (EtherBalance Geoff) -- ether balance stays the same + Invariant Static (EtherBalance Torrey) -- + Invariant Static (EtherBalance cETH) -- + Assert Equal (Erc20 cETH TokenBalance Geoff) 0.2e8 -- from minting (0.001e18 / 0.05e9) + Assert Equal (Erc20 cETH TokenBalance Torrey) 0e9 -- never had any + Invariant Remains (Erc20 BAT TokenBalance Geoff) 0.01e18 -- original amount borrowed + Assert Equal (Erc20 BAT TokenBalance Torrey) 0.02e18 -- from prep above + Assert Equal (Erc20 BAT TokenBalance cBAT) 9.99e18 -- had 10e18, lent 0.01e18 to geoff + Invariant Remains (Erc20 cBAT TokenBalance Geoff) 0e8 -- never had any (has underlying) + Invariant Remains (Erc20 cBAT TokenBalance Torrey) 0e8 -- never had any + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 0.51e18 -- all that interest + Assert Equal (CToken cBAT TotalBorrows) 0.51e18 -- all those borrowers + Assert Equal (Comptroller Liquidity Geoff) -1e13 -- underwater + -- Do the liquidation + LiquidateEthColl Torrey "->" Geoff 0.02e18 cBAT "Seizing" cETH + -- + -- And see what they are now + Assert Equal (Erc20 cETH TokenBalance Torrey) 0.0044e8 -- 0.02e18 * (1.0e-3/1) * 1.1 / 0.05e9 [exchange rate] = 0.0044e8 -> Torrey + Assert Equal (Erc20 cETH TokenBalance Geoff) 0.1956e8 + Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 -- repaid + Assert Equal (Erc20 BAT TokenBalance cBAT) 10.01e18 -- had 10e18, lent 0.01e18 to geoff, repaid 0.02 + Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 0.49e18 -- less closed amount + Assert Equal (CToken cBAT TotalBorrows) 0.49e18 -- + -- User now has 0.1956 cETH outstanding supply + -- capacity. The user also has a 0.49e18 borrow BAT outstanding. + -- ( 0.5 * 0.1956e8 * 0.05e9 * 1.0 ) - ( 0.49e18 * 1.0e-3 ) = 0.09731e18 + Assert Equal (Comptroller Liquidity Geoff) -0.000001e18 diff --git a/spec/scenario/Mint.scen b/spec/scenario/Mint.scen new file mode 100644 index 000000000..e00130923 --- /dev/null +++ b/spec/scenario/Mint.scen @@ -0,0 +1,90 @@ +-- Mint Tests + +Test "Mint 1 cZRX" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) + -- Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 1.0e18) + +Test "Mint with insufficient allowance" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 49e18 ZRX cZRX + AllowFailures + Mint Geoff 50e18 cZRX + Assert Failure TOKEN_INSUFFICIENT_ALLOWANCE MINT_TRANSFER_IN_NOT_POSSIBLE + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e9) + +Test "Mint with insufficient balance" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 49e18 ZRX cZRX allowanceAmount:50e18 + AllowFailures + Mint Geoff 50e18 cZRX + Assert Failure TOKEN_INSUFFICIENT_BALANCE MINT_TRANSFER_IN_NOT_POSSIBLE + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e9) + +Test "Mint two ZRX after minting two ZRX, and then I mint two more" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 4e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 4e9) + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 6e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 6e9) + +Test "Two users Mint" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Prep Torrey Some ZRX cZRX + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) + Mint Torrey 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) + Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 2e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 4e9) + +Test "Mint accrues no interest without borrows" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Prep Torrey Some ZRX cZRX + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) + FastForward 1000 Blocks + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) + Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) + +Test "Mint transfer in fails" + NewComptroller + ListedCToken EVL cEVL tokenType:Evil + Prep Geoff Some EVL cEVL + Prep Torrey Some EVL cEVL + Invariant Static (Erc20 cEVL TokenBalance Geoff) + Invariant Static (Erc20 cEVL TotalSupply) + Invariant Static (Erc20 EVL TotalSupply) + AllowFailures + Mint Geoff 2e18 cEVL + Assert Failure TOKEN_TRANSFER_IN_FAILED MINT_TRANSFER_IN_FAILED + +Test "Denied by comptroller because unlisted" + NewComptroller + NewCToken ZRX cZRX + Prep Geoff Some ZRX cZRX + Prep Torrey Some ZRX cZRX + Invariant Static (Erc20 cZRX TokenBalance Geoff) + Invariant Static (Erc20 cZRX TotalSupply) + Invariant Static (Erc20 ZRX TotalSupply) + AllowFailures + Mint Geoff 2e18 cZRX + Assert Failure COMPTROLLER_REJECTION MINT_COMPTROLLER_REJECTION MARKET_NOT_LISTED diff --git a/spec/scenario/MintEth.scen b/spec/scenario/MintEth.scen new file mode 100644 index 000000000..922c7ea82 --- /dev/null +++ b/spec/scenario/MintEth.scen @@ -0,0 +1,66 @@ +-- Mint Tests + +GasTest "Send Mint 1 cETH" + NewComptroller + ListedEtherTokenMinted cETH initialExchangeRate:0.005e9 + Expect Changes (EtherBalance Geoff) -0.005e18 + Expect Changes (CToken cETH UnderlyingBalance Geoff) +0.005e18 + SendMintEth Geoff 0.005e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert LastGas LessThan 90e3 + +GasTest "Call Mint 1 cETH" + NewComptroller + ListedEtherTokenMinted cETH initialExchangeRate:0.005e9 + Expect Changes (EtherBalance Geoff) -0.005e18 + Expect Changes (CToken cETH UnderlyingBalance Geoff) +0.005e18 + CallMintEth Geoff 0.005e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert LastGas LessThan 90e3 + +Test "Mint with insufficient eth balance" + NewComptroller + ListedEtherTokenMinted cETH initialExchangeRate:0.005e9 + AllowFailures + Invariant Remains (CToken cETH UnderlyingBalance Geoff) 0e18 + Invariant Remains (Erc20 cETH TokenBalance Geoff) 0e8 + Invariant Static (EtherBalance Geoff) + CallMintEth Geoff 1e30 cETH + Assert Error "Returned error: sender doesn't have enough funds to send tx" + +Test "Mint two Eth after minting two Eth, and then I mint two more" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + Expect Changes (EtherBalance Geoff) -0.002e18 + CallMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TotalSupply) 4e8 + Expect Changes (EtherBalance Geoff) -0.002e18 + SendMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 8e8 + Assert Equal (Erc20 cETH TotalSupply) 8e8 + Expect Changes (EtherBalance Geoff) -0.002e18 + CallMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 12e8 + Assert Equal (Erc20 cETH TotalSupply) 12e8 + +Test "Two users Mint" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TotalSupply) 4e8 + CallMintEth Torrey 0.004e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TokenBalance Torrey) 8e8 + Assert Equal (Erc20 cETH TotalSupply) 12e8 + +Test "Mint accrues no interest without borrows" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TotalSupply) 4e8 + FastForward 1000 Blocks + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TotalSupply) 4e8 diff --git a/spec/scenario/MintWBTC.scen b/spec/scenario/MintWBTC.scen new file mode 100644 index 000000000..89159cdf4 --- /dev/null +++ b/spec/scenario/MintWBTC.scen @@ -0,0 +1,91 @@ +-- Mint Tests + +Test "Mint 1 cWBTC" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Mint Geoff 10e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 50e8) + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) (Exactly 10e8) + +Test "Mint WBTC with insufficient allowance" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff 4.9e8 WBTC cWBTC + AllowFailures + Mint Geoff 5e8 cWBTC + Assert Failure TOKEN_INSUFFICIENT_ALLOWANCE MINT_TRANSFER_IN_NOT_POSSIBLE + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 0e8) + +Test "Mint WBTC with insufficient balance" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff 4.9e8 WBTC cWBTC allowanceAmount:5e8 + AllowFailures + Mint Geoff 5e8 cWBTC + Assert Failure TOKEN_INSUFFICIENT_BALANCE MINT_TRANSFER_IN_NOT_POSSIBLE + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 0e8) + +Test "Mint two WBTC after minting two WBTC, and then I mint two more" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 20e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 20e8) + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 30e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 30e8) + +Test "Two users Mint WBTC" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Prep Torrey Some WBTC cWBTC + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) + Mint Torrey 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) + Assert Equal (Erc20 cWBTC TokenBalance Torrey) (Exactly 10e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 20e8) + +Test "Mint WBTC accrues no interest without borrows" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Prep Torrey Some WBTC cWBTC + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) + FastForward 1000 Blocks + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) + Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) + +Test "Mint WBTC transfer in fails due to paused" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Prep Torrey Some WBTC cWBTC + Invariant Static (Erc20 cWBTC TokenBalance Geoff) + Invariant Static (Erc20 cWBTC TotalSupply) + Invariant Static (Erc20 WBTC TotalSupply) + Erc20 WBTC Pause + AllowFailures + Mint Geoff 2e8 cWBTC + Assert Revert + +Test "Denied by comptroller because WBTC unlisted" + NewComptroller + NewCToken WBTC cWBTC tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Prep Torrey Some WBTC cWBTC + Invariant Static (Erc20 cWBTC TokenBalance Geoff) + Invariant Static (Erc20 cWBTC TotalSupply) + Invariant Static (Erc20 WBTC TotalSupply) + AllowFailures + Mint Geoff 2e8 cWBTC + Assert Failure COMPTROLLER_REJECTION MINT_COMPTROLLER_REJECTION MARKET_NOT_LISTED diff --git a/spec/scenario/ReEntry.scen b/spec/scenario/ReEntry.scen new file mode 100644 index 000000000..1152a1174 --- /dev/null +++ b/spec/scenario/ReEntry.scen @@ -0,0 +1,13 @@ +-- Mint Tests + +Test "ReEntry Mint" + NewComptroller + Erc20 Deploy ReEntrant PHREAK PHREAK "transferFrom" "mint(uint256)" "0" + InterestRateModel Deploy Fixed Std 0.0001 + CToken Deploy cPHREAK cPHREAK (Erc20 PHREAK Address) (Comptroller Address) (InterestRateModel Std Address) 1e9 8 + Comptroller SupportMarket cPHREAK + Prep Geoff Some PHREAK cPHREAK + AllowFailures + Mint Geoff 50e18 cPHREAK + Assert Revert "revert re-entered" + Assert Equal (Erc20 cPHREAK TokenBalance Geoff) Zero diff --git a/spec/scenario/Redeem.scen b/spec/scenario/Redeem.scen new file mode 100644 index 000000000..2dd24ec25 --- /dev/null +++ b/spec/scenario/Redeem.scen @@ -0,0 +1,227 @@ +-- Redeem Tests + +Test "Mint then Redeem All" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Redeem Geoff 500e8 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) Zero + Assert Equal (Erc20 ZRX TokenBalance Geoff) 70e18 + +Test "Mint, Enter and then Redeem All" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + EnterMarkets Geoff cZRX + Redeem Geoff 500e8 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) Zero + Assert Equal (Erc20 ZRX TokenBalance Geoff) 70e18 + +Test "Mint then Redeem Part" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Redeem Geoff 250e8 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 250e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 45e18 + +Test "Mint then Redeem Too Much" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check and hold static + Invariant Static (CToken cZRX ExchangeRateStored) + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Now redeem after some time + FastForward 2 Blocks + AllowFailures + Redeem Geoff 501e8 cZRX + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + +Test "Mint then Redeem Zero" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Redeem Geoff 0e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + +Test "Mint then redeem with interest - no reserves" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Invariant Remains (CToken cZRX Reserves) Zero + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cZRX ExchangeRate) 1.1e9 + -- Now redeem all with interest + Redeem Geoff 500e8 cZRX + Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 + Assert Equal (Erc20 ZRX TokenBalance cZRX) 0e18 + Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + +Test "Mint then redeem part with interest - no reserves" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Invariant Remains (CToken cZRX Reserves) Zero + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cZRX ExchangeRate) 1.1e9 + -- Now redeem all with interest + Redeem Geoff 499e8 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 1e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.11e18 + Assert Equal (CToken cZRX ExchangeRate) 1.1e9 + +Test "Mint then redeem with reserves and interest" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX Reserves) 1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 54e18 + -- 55e18 + 0e18 - 1e18 / 500 + Assert Equal (CToken cZRX ExchangeRate) 1.08e9 + -- Now redeem all with interest + Redeem Geoff 500e8 cZRX + Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 + Assert Equal (Erc20 ZRX TokenBalance cZRX) 1e18 + Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 + Assert Equal (CToken cZRX Reserves) 1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + +Test "Two users Mint, one redeems" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Prep Torrey Some ZRX cZRX + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cZRX TotalSupply) 20e8 + Mint Torrey 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cZRX TokenBalance Torrey) 20e8 + Assert Equal (Erc20 cZRX TotalSupply) 40e8 + Redeem Torrey 10e8 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cZRX TokenBalance Torrey) 10e8 + Assert Equal (Erc20 cZRX TotalSupply) 30e8 + +Test "Redeem transfer out fails" + NewComptroller + ListedCToken EVL cEVL initialExchangeRate:1e9 tokenType:Evil + Erc20 EVL SetFail False + Prep Geoff 70e18 EVL cEVL + Mint Geoff 50e18 cEVL + -- Check current affairs + Invariant Remains (Erc20 cEVL TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 EVL TokenBalance Geoff) 20e18 + Invariant Static (CToken cEVL ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Erc20 EVL SetFail True + AllowFailures + Redeem Geoff 500e8 cEVL + Assert Revert "revert redeem transfer out failed" + +Test "Mint, Enter, then Redeem Too Much (collateral factor: 0)" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check and hold static + Invariant Static (CToken cZRX ExchangeRateStored) + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Now redeem after some time + FastForward 2 Blocks + EnterMarkets Geoff cZRX + AllowFailures + Redeem Geoff 501e8 cZRX + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + +Test "Mint, Enter, then Redeem Too Much (collateral factor: 0.1)" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Comptroller SetCollateralFactor cZRX 0.1 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check and hold static + Invariant Static (CToken cZRX ExchangeRateStored) + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Now redeem after some time + FastForward 2 Blocks + EnterMarkets Geoff cZRX + AllowFailures + Redeem Geoff 501e8 cZRX + Assert Failure COMPTROLLER_REJECTION REDEEM_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY diff --git a/spec/scenario/RedeemEth.scen b/spec/scenario/RedeemEth.scen new file mode 100644 index 000000000..3985fb686 --- /dev/null +++ b/spec/scenario/RedeemEth.scen @@ -0,0 +1,156 @@ +-- Redeem Tests + +Test "Mint then Redeem All" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + -- Check current affairs + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 + Invariant Static (CToken cETH ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Expect Changes (EtherBalance Geoff) +0.005e18 + RedeemEth Geoff 10e8 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) Zero + Assert Equal (CToken cETH UnderlyingBalance Geoff) Zero + +Test "Mint then Redeem Part" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + -- Check current affairs + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 + Invariant Static (CToken cETH ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Expect Changes (EtherBalance Geoff) +0.001e18 + RedeemEth Geoff 2e8 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 8e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.004e18 + +Test "Mint then Redeem Too Much" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + AllowFailures + -- Check and hold static + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 + Invariant Static (EtherBalance Geoff) + -- Now redeem after some time + FastForward 2 Blocks + RedeemEth Geoff 11e8 cETH + -- TODO: This should really be REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, but based on + -- the order of subtractions, total supply comes before account supply. + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" -- TODO: This error is wrong + +Test "Mint then Redeem Zero" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + -- Check and hold static + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 + Invariant Static (EtherBalance Geoff) + -- Now redeem after some time + FastForward 2 Blocks + RedeemEth Geoff 0e9 cETH + +Pending "Mint then redeem with interest - no reserves" + Invariant Success + NewComptroller + ListedCToken ZRX cETH initialExchangeRate:1e9 + Invariant Remains (CToken cETH Reserves) Zero + Prep Geoff 50e18 ZRX cETH + Mint Geoff 50e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cETH ExchangeRate) 1.1e9 + -- Now redeem all with interest + Redeem Geoff 500e8 cETH + Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 + Assert Equal (Erc20 ZRX TokenBalance cETH) 0e18 + Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + +Pending "Mint then redeem part with interest - no reserves" + Invariant Success + NewComptroller + ListedCToken ZRX cETH initialExchangeRate:1e9 + Invariant Remains (CToken cETH Reserves) Zero + Prep Geoff 50e18 ZRX cETH + Mint Geoff 50e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cETH ExchangeRate) 1.1e9 + -- Now redeem all with interest + Redeem Geoff 499e8 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 1e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.11e18 + Assert Equal (CToken cETH ExchangeRate) 1.1e9 + +Pending "Mint then redeem with reserves and interest" + Invariant Success + NewComptroller + ListedCToken ZRX cETH initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cETH + Mint Geoff 50e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH Reserves) 1e18 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 54e18 + -- 55e18 + 0e18 - 1e18 / 500 + Assert Equal (CToken cETH ExchangeRate) 1.08e9 + -- Now redeem all with interest + Redeem Geoff 500e8 cETH + Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 + Assert Equal (Erc20 ZRX TokenBalance cETH) 1e18 + Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 + Assert Equal (CToken cETH Reserves) 1e18 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + +Test "Two users Mint, one redeems" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TotalSupply) 4e8 + CallMintEth Torrey 0.004e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TokenBalance Torrey) 8e8 + Assert Equal (Erc20 cETH TotalSupply) 12e8 + RedeemEth Torrey 3e8 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TokenBalance Torrey) 5e8 + Assert Equal (Erc20 cETH TotalSupply) 9e8 diff --git a/spec/scenario/RedeemUnderlying.scen b/spec/scenario/RedeemUnderlying.scen new file mode 100644 index 000000000..79143fbb4 --- /dev/null +++ b/spec/scenario/RedeemUnderlying.scen @@ -0,0 +1,182 @@ +-- Redeem Tests + +Test "Mint then Redeem All" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) Zero + Assert Equal (Erc20 ZRX TokenBalance Geoff) 70e18 + +Test "Mint then Redeem Part" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 25e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 250e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 45e18 + +Test "Mint then Redeem Too Much" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check and hold static + Invariant Static (CToken cZRX ExchangeRateStored) + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Now redeem after some time + FastForward 2 Blocks + AllowFailures + RedeemUnderlying Geoff 50.1e18 cZRX + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + +Test "Mint then Redeem Zero" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + -- Check current affairs + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 0e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 + +Test "Mint then redeem with interest - no reserves" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Invariant Remains (CToken cZRX Reserves) Zero + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cZRX ExchangeRate) 1.1e9 + -- Now redeem all with interest + -- Exchange rate is now 55e18 ÷ 50e9 = 1.1e9 + -- 500e9 * 1.1e9 = 55e18 + RedeemUnderlying Geoff 55e18 cZRX + Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 + Assert Equal (Erc20 ZRX TokenBalance cZRX) 0e18 + Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + +Test "Mint then redeem part with interest - no reserves" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Invariant Remains (CToken cZRX Reserves) Zero + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cZRX ExchangeRate) 1.1e9 + -- Now redeem all with interest + -- Exchange rate is now 55e18 ÷ 50e9 = 1.1e9 + -- 499e9 * 1.1e9 = 54.89e18 + RedeemUnderlying Geoff 54.89e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 1e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.11e18 + Assert Equal (CToken cZRX ExchangeRate) 1.1e9 + +Test "Mint then redeem with reserves and interest" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 + Assert Equal (CToken cZRX Reserves) 1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 54e18 + -- 55e18 + 0e18 - 1e18 / 500 + Assert Equal (CToken cZRX ExchangeRate) 1.08e9 + -- Now redeem all with interest + -- Exchange rate is 1.08e9 + -- 500e8 * 1.08e9 = 54e18 + RedeemUnderlying Geoff 54e18 cZRX + Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 + Assert Equal (Erc20 ZRX TokenBalance cZRX) 1e18 + Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 + Assert Equal (CToken cZRX Reserves) 1e18 + Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cZRX ExchangeRate) 1e9 + +Test "Two users Mint, one redeems" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Prep Torrey Some ZRX cZRX + Mint Geoff 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cZRX TotalSupply) 20e8 + Mint Torrey 2e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cZRX TokenBalance Torrey) 20e8 + Assert Equal (Erc20 cZRX TotalSupply) 40e8 + RedeemUnderlying Torrey 1e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cZRX TokenBalance Torrey) 10e8 + Assert Equal (Erc20 cZRX TotalSupply) 30e8 + +Test "Mint then Redeem 1 wei of underlying" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 70e18 ZRX cZRX + Mint Geoff 50e18 cZRX + AllowFailures + -- Check current affairs + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 + -- Any other good invariants? + Invariant Static (CToken cZRX ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 1 cZRX + Assert Revert "revert redeemTokens zero" diff --git a/spec/scenario/RedeemUnderlyingEth.scen b/spec/scenario/RedeemUnderlyingEth.scen new file mode 100644 index 000000000..0c9ed5ef9 --- /dev/null +++ b/spec/scenario/RedeemUnderlyingEth.scen @@ -0,0 +1,171 @@ +-- Redeem Tests + +Test "Mint then Redeem All" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + -- Check current affairs + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 + Invariant Static (CToken cETH ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Expect Changes (EtherBalance Geoff) +0.005e18 + RedeemUnderlyingEth Geoff 0.005e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) Zero + Assert Equal (CToken cETH UnderlyingBalance Geoff) Zero + +Test "Mint then Redeem Part" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + -- Check current affairs + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 + Invariant Static (CToken cETH ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Expect Changes (EtherBalance Geoff) +0.001e18 + RedeemUnderlyingEth Geoff 0.001e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 8e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.004e18 + +Test "Mint then Redeem Too Much" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + AllowFailures + -- Check and hold static + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 + Invariant Static (EtherBalance Geoff) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlyingEth Geoff 0.0055e18 cETH + -- TODO: This should really be REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, but based on + -- the order of subtractions, total supply comes before account supply. + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" -- TODO: This error is wrong + +Test "Mint then Redeem Zero" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + -- Check and hold static + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 + Invariant Static (EtherBalance Geoff) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlyingEth Geoff 0e18 cETH + +Pending "Mint then redeem with interest - no reserves" + Invariant Success + NewComptroller + ListedCToken ZRX cETH initialExchangeRate:1e9 + Invariant Remains (CToken cETH Reserves) Zero + Prep Geoff 50e18 ZRX cETH + Mint Geoff 50e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cETH ExchangeRate) 1.1e9 + -- Now redeem all with interest + Redeem Geoff 500e8 cETH + Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 + Assert Equal (Erc20 ZRX TokenBalance cETH) 0e18 + Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + +Pending "Mint then redeem part with interest - no reserves" + Invariant Success + NewComptroller + ListedCToken ZRX cETH initialExchangeRate:1e9 + Invariant Remains (CToken cETH Reserves) Zero + Prep Geoff 50e18 ZRX cETH + Mint Geoff 50e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 + Assert Equal (CToken cETH ExchangeRate) 1.1e9 + -- Now redeem all with interest + Redeem Geoff 499e8 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 1e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.11e18 + Assert Equal (CToken cETH ExchangeRate) 1.1e9 + +Pending "Mint then redeem with reserves and interest" + Invariant Success + NewComptroller + ListedCToken ZRX cETH initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cETH + Mint Geoff 50e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 + Assert Equal (CToken cETH Reserves) 1e18 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 54e18 + -- 55e18 + 0e18 - 1e18 / 500 + Assert Equal (CToken cETH ExchangeRate) 1.08e9 + -- Now redeem all with interest + Redeem Geoff 500e8 cETH + Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 + Assert Equal (Erc20 ZRX TokenBalance cETH) 1e18 + Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 + Assert Equal (CToken cETH Reserves) 1e18 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 + Assert Equal (CToken cETH ExchangeRate) 1e9 + +Test "Two users Mint, one redeems" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.002e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TotalSupply) 4e8 + CallMintEth Torrey 0.004e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TokenBalance Torrey) 8e8 + Assert Equal (Erc20 cETH TotalSupply) 12e8 + RedeemUnderlyingEth Torrey 0.0015e18 cETH + Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 + Assert Equal (Erc20 cETH TokenBalance Torrey) 5e8 + Assert Equal (Erc20 cETH TotalSupply) 9e8 + +Test "Mint then redeem 1 wei" + NewComptroller + ListedEtherToken cETH initialExchangeRate:0.005e9 + CallMintEth Geoff 0.005e18 cETH + AllowFailures + -- Check current affairs + Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 + Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 + Invariant Static (CToken cETH ExchangeRateStored) + Invariant Static (EtherBalance Geoff) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlyingEth Geoff 1 cETH + Assert Revert "revert redeemTokens zero" diff --git a/spec/scenario/RedeemUnderlyingWBTC.scen b/spec/scenario/RedeemUnderlyingWBTC.scen new file mode 100644 index 000000000..02b7c4652 --- /dev/null +++ b/spec/scenario/RedeemUnderlyingWBTC.scen @@ -0,0 +1,183 @@ +-- Redeem Tests + +Test "Mint then Redeem All" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) Zero + Assert Equal (Erc20 WBTC TokenBalance Geoff) 70e8 + +Test "Mint then Redeem Part" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 25e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 250e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 45e8 + +Test "Mint then Redeem Too Much" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check and hold static + Invariant Static (CToken cWBTC ExchangeRateStored) + Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Now redeem after some time + FastForward 2 Blocks + AllowFailures + RedeemUnderlying Geoff 50.1e8 cWBTC + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + +Test "Mint then Redeem Zero" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 0e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + +Test "Mint then redeem with interest - no reserves" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Invariant Remains (CToken cWBTC Reserves) Zero + Prep Geoff 50e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e8 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.11 + -- Now redeem all with interest + -- Exchange rate is now 55e8 ÷ 50e-1 = 1.1e-1 + -- 500e-1 * 1.1e-1 = 55e8 + RedeemUnderlying Geoff 55e8 cWBTC + Assert Equal (Erc20 WBTC TokenBalance Geoff) 55e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 0e8 + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + +Test "Mint then redeem part with interest - no reserves" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Invariant Remains (CToken cWBTC Reserves) Zero + Prep Geoff 50e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e8 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.11 + -- Now redeem all with interest + -- Exchange rate is now 55e8 ÷ 50e-1 = 1.1e-1 + -- 499e-1 * 1.1e-1 = 54.89e8 + RedeemUnderlying Geoff 54.89e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 1e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0.11e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.11 + +Test "Mint then redeem with reserves and interest" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 50e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e8 of interest for the protocol + -- The reserves should get 20% of this, or 1e8, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC Reserves) 1e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 54e8 + -- 55e8 + 0e8 - 1e8 / 500 + Assert Equal (CToken cWBTC ExchangeRate) 0.108 + -- Now redeem all with interest + -- Exchange rate is 1.08e-1 + -- 500e8 * 1.08e-1 = 54e8 + RedeemUnderlying Geoff 54e8 cWBTC + Assert Equal (Erc20 WBTC TokenBalance Geoff) 54e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 1e8 + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 + Assert Equal (CToken cWBTC Reserves) 1e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + +Test "Two users Mint, one redeems" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Prep Torrey Some WBTC cWBTC + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cWBTC TotalSupply) 20e8 + Mint Torrey 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cWBTC TokenBalance Torrey) 20e8 + Assert Equal (Erc20 cWBTC TotalSupply) 40e8 + RedeemUnderlying Torrey 1e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cWBTC TokenBalance Torrey) 10e8 + Assert Equal (Erc20 cWBTC TotalSupply) 30e8 + +Test "Mint then Redeem 1 wei of underlying is allowed for 1:1 assets" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + RedeemUnderlying Geoff 1 cWBTC + -- After affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 49999999990 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 2000000001 diff --git a/spec/scenario/RedeemWBTC.scen b/spec/scenario/RedeemWBTC.scen new file mode 100644 index 000000000..e6c415b90 --- /dev/null +++ b/spec/scenario/RedeemWBTC.scen @@ -0,0 +1,226 @@ +-- Redeem Tests + +Test "Mint WBTC then Redeem All" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Redeem Geoff 500e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) Zero + Assert Equal (Erc20 WBTC TokenBalance Geoff) 70e8 + +Test "Mint WBTC, Enter and then Redeem All" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + EnterMarkets Geoff cWBTC + Redeem Geoff 500e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) Zero + Assert Equal (Erc20 WBTC TokenBalance Geoff) 70e8 + +Test "Mint WBTC then Redeem Part" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Redeem Geoff 250e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 250e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 45e8 + +Test "Mint WBTC then Redeem Too Much" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check and hold static + Invariant Static (CToken cWBTC ExchangeRateStored) + Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Now redeem after some time + FastForward 2 Blocks + AllowFailures + Redeem Geoff 501e8 cWBTC + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + +Test "Mint WBTC then Redeem Zero" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Any other good invariants? + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Redeem Geoff 0e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 + +Test "Mint WBTC then redeem with interest - no reserves" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Invariant Remains (CToken cWBTC Reserves) Zero + Prep Geoff 50e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e8 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.11 + -- Now redeem all with interest + Redeem Geoff 500e8 cWBTC + Assert Equal (Erc20 WBTC TokenBalance Geoff) 55e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 0e8 + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + +Test "Mint WBTC then redeem part with interest - no reserves" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Invariant Remains (CToken cWBTC Reserves) Zero + Prep Geoff 50e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.0001 blocks:5000 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e8 of interest for the protocol + -- This is due pro-rata to all holders, but we just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.11 + -- Now redeem all with interest + Redeem Geoff 499e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 1e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0.11e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.11 + +Test "Mint WBTC then redeem with reserves and interest" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 50e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e8 of interest for the protocol + -- The reserves should get 20% of this, or 1e8, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 + Assert Equal (CToken cWBTC Reserves) 1e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 54e8 + -- 55e8 + 0e8 - 1e8 / 500 + Assert Equal (CToken cWBTC ExchangeRate) 0.108 + -- Now redeem all with interest + Redeem Geoff 500e8 cWBTC + Assert Equal (Erc20 WBTC TokenBalance Geoff) 54e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 1e8 + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 + Assert Equal (CToken cWBTC Reserves) 1e8 + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 + Assert Equal (CToken cWBTC ExchangeRate) 0.1 + +Test "Two users Mint WBTC, one redeems" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Prep Torrey Some WBTC cWBTC + Mint Geoff 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cWBTC TotalSupply) 20e8 + Mint Torrey 2e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cWBTC TokenBalance Torrey) 20e8 + Assert Equal (Erc20 cWBTC TotalSupply) 40e8 + Redeem Torrey 10e8 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 + Assert Equal (Erc20 cWBTC TokenBalance Torrey) 10e8 + Assert Equal (Erc20 cWBTC TotalSupply) 30e8 + +Test "Redeem WBTC transfer out fails" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check current affairs + Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 + Invariant Static (CToken cWBTC ExchangeRateStored) + -- Now redeem after some time + FastForward 2 Blocks + Erc20 WBTC Pause + AllowFailures + Redeem Geoff 500e8 cWBTC + Assert Revert + +Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0)" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check and hold static + Invariant Static (CToken cWBTC ExchangeRateStored) + Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Now redeem after some time + FastForward 2 Blocks + EnterMarkets Geoff cWBTC + AllowFailures + Redeem Geoff 501e8 cWBTC + Assert Failure MATH_ERROR REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED "3" + +Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0.1)" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Comptroller SetCollateralFactor cWBTC 0.1 + Prep Geoff 70e8 WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Check and hold static + Invariant Static (CToken cWBTC ExchangeRateStored) + Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 + Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 + -- Now redeem after some time + FastForward 2 Blocks + EnterMarkets Geoff cWBTC + AllowFailures + Redeem Geoff 501e8 cWBTC + Assert Failure COMPTROLLER_REJECTION REDEEM_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY diff --git a/spec/scenario/ReduceReserves.scen b/spec/scenario/ReduceReserves.scen new file mode 100644 index 000000000..670cdba6d --- /dev/null +++ b/spec/scenario/ReduceReserves.scen @@ -0,0 +1,136 @@ + +Test "Reduce all reserves and verify effects" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX Reserves) (Exactly 1e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) + -- (55.0e18+0.0e18-1.0e18)/500.0e8 + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) + -- Now, let's pull out all of our reserves (1e18) + ReduceReserves 1e18 cZRX + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 54e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 1e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX Reserves) (Exactly 0e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) + -- (54.0e18+0.0e18-0.0e18)/500.0e8 + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) + +Test "Reduce partial reserves and verify effects" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX Reserves) (Exactly 1e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) + -- (55.0e18+0.0e18-1.0e18)/500.0e8 + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) + -- Now, let's pull out all of our reserves (1e18) + ReduceReserves 0.5e18 cZRX + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 54.5e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0.5e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX Reserves) (Exactly 0.5e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) + -- (54.5e18+0.5e18-0.0e18)/500.0e8 + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) + +Test "Redeem all and then reduce all reserves" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff 50e18 ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cZRX Reserves) (Exactly 1e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) + -- (55.0e18+0.0e18-1.0e18)/500.0e8 + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) + -- Now let's redeem all + Redeem Geoff 500e8 cZRX + -- Check our values + Assert Equal (Erc20 ZRX TokenBalance Geoff) (Exactly 54e18) + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 1e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e8) + Assert Equal (CToken cZRX Reserves) (Exactly 1e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 0e18) + -- 0 tokens implies initial exchange rate + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) + -- Then now, let's pull out all of our reserves (1e18) + ReduceReserves 1e18 cZRX + Assert Equal (Erc20 ZRX TokenBalance Geoff) (Exactly 54e18) + Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 0e18) + Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 1e18) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e8) + Assert Equal (CToken cZRX Reserves) (Exactly 0e18) + Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 0e18) + -- 0 tokens implies initial exchange rate + Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) + +Test "Reduce reserves WBTC when paused" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:1e9 tokenType:WBTC + Prep Geoff 50e18 WBTC cWBTC + Mint Geoff 50e18 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 500e8) + Assert Equal (CToken cWBTC UnderlyingBalance Geoff) (Exactly 50e18) + Assert Equal (CToken cWBTC ExchangeRate) (Exactly 1e9) + -- Get some brah to borrow then repay + BorrowAndRepayWithInterest WBTC cWBTC 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 + -- We've accrued 10% interest for 5 blocks, or 50% of the amount, + -- thus, we should have accrued 5e18 of interest for the protocol + -- The reserves should get 20% of this, or 1e18, and the rest + -- is due pro-rata to all holders. We just have one, so + -- let's check that account is given correct new balance. + Invariant Remains (Erc20 WBTC TokenBalance cWBTC) (Exactly 55e18) + Invariant Remains (Erc20 WBTC TokenBalance Root) (Exactly 0e18) + Invariant Remains (Erc20 cWBTC TokenBalance Geoff) (Exactly 500e8) + Invariant Remains (CToken cWBTC Reserves) (Exactly 1e18) + Invariant Remains (CToken cWBTC UnderlyingBalance Geoff) (Exactly 54e18) + -- (55.0e18+0.0e18-1.0e18)/500.0e8 + Invariant Remains (CToken cWBTC ExchangeRate) (Exactly 1.08e9) + -- Now, let's pull out all of our reserves (1e18) + Erc20 WBTC Pause + AllowFailures + ReduceReserves 1e18 cWBTC + Assert Revert diff --git a/spec/scenario/RepayBorrow.scen b/spec/scenario/RepayBorrow.scen new file mode 100644 index 000000000..c90ecb35b --- /dev/null +++ b/spec/scenario/RepayBorrow.scen @@ -0,0 +1,173 @@ +-- Tests for repaying borrows + +Macro NewBorrow borrowAmount borrowRate + NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset + NewCToken ZRX cZRX + NewCToken BAT cBAT borrowRate -- note: cannot use macros with named args right now + Give cBAT 10e18 BAT -- Faucet some bat to borrow + Support cZRX collateralFactor:0.5 + Support cBAT collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cBAT + Borrow Geoff borrowAmount cBAT + +Test "Borrow, hold a few blocks, and repay part" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay one full token + From Geoff (Erc20 BAT Approve cBAT 1.0e18) + RepayBorrow Geoff 1.0e18 cBAT + Assert Equal (CToken cBAT BorrowBalance Geoff) 1.5e18 + -- Let's check the overall numbers + Assert Equal (Erc20 BAT TokenBalance Geoff) Zero + Assert Equal (Erc20 BAT TokenBalance cBAT) 10e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1.5e18 + FastForward 2000 Blocks -- 1.5e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 3e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 3e18 + +Test "Borrow, hold a few blocks, and repay full" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay fully + Give Geoff 1.5e18 BAT -- Geoff had the 1.0e18 borrowed BAT + From Geoff (Erc20 BAT Approve cBAT 2.5e18) + RepayBorrow Geoff 2.5e18 cBAT + Assert Equal (CToken cBAT BorrowBalance Geoff) 0e18 + -- Let's check the overall numbers + Assert Equal (Erc20 BAT TokenBalance Geoff) 0e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 11.5e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 0e18 + FastForward 2000 Blocks -- 0e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 0e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 0e18 + +Test "Borrow, hold a few blocks, and repay too much" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay fully + AllowFailures + Prep Geoff 10e18 BAT cBAT + Expect Changes (Erc20 BAT TokenBalance Geoff) Zero + Expect Changes (Erc20 BAT TokenBalance cBAT) Zero + RepayBorrow Geoff 10e18 cBAT + Assert Failure MATH_ERROR REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED "3" + -- Let's check the overall numbers + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 + +Test "Borrow, and get a negative total cash situation" + Invariant Success + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Let's zoom way forward into the future + FastForward 98000 Blocks -- 1e18 * (1 + 98000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 50e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 50e18 + -- Now let's repay one full token + From Geoff (Erc20 BAT Approve cBAT 1.0e18) + RepayBorrow Geoff 1.0e18 cBAT + Assert Equal (CToken cBAT BorrowBalance Geoff) 49e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 49e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 0e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 10e18 + +Test "Borrow, hold a few blocks, and repay behalf part" + Invariant Success + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay one full token from another user + Prep Torrey 1.0e18 BAT cBAT + RepayBorrowBehalf Torrey Geoff 1.0e18 cBAT + Assert Equal (CToken cBAT BorrowBalance Torrey) Zero + Assert Equal (CToken cBAT BorrowBalance Geoff) 1.5e18 + -- Let's check the overall numbers + Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 + Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 + Assert Equal (Erc20 BAT TokenBalance cBAT) 10e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1.5e18 + FastForward 2000 Blocks -- 1.5e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Torrey) Zero + Assert Equal (CToken cBAT BorrowBalance Geoff) 3e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 3e18 + +Test "Prohibit repay by comptroller rejection due to mock unlist" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay fully + AllowFailures + Prep Geoff 10e18 BAT cBAT + Expect Changes (Erc20 BAT TokenBalance Geoff) Zero + Expect Changes (Erc20 BAT TokenBalance cBAT) Zero + Comptroller UnList cZRX -- Mock unlist ZRX + RepayBorrow Geoff 2.5e18 cZRX + Assert Failure COMPTROLLER_REJECTION REPAY_BORROW_COMPTROLLER_REJECTION MARKET_NOT_LISTED + -- Let's check the overall numbers + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 + +Test "Repay fails with insufficient allowance" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay fully + AllowFailures + Prep Geoff 100e18 BAT cBAT allowanceAmount:1.5e18 + Expect Changes (Erc20 BAT TokenBalance Geoff) Zero + Expect Changes (Erc20 BAT TokenBalance cBAT) Zero + RepayBorrow Geoff 2.5e18 cBAT + Assert Failure TOKEN_INSUFFICIENT_ALLOWANCE REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE + -- Let's check the overall numbers + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 + +Test "Repay fails with insufficient balance" + NewBorrow borrowAmount:1e18 borrowRate:0.0005 + Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + -- Now let's repay fully + AllowFailures + Prep Geoff 0e18 BAT cBAT allowanceAmount:2.5e18 + Expect Changes (Erc20 BAT TokenBalance Geoff) Zero + Expect Changes (Erc20 BAT TokenBalance cBAT) Zero + RepayBorrow Geoff 2.5e18 cBAT + Assert Failure TOKEN_INSUFFICIENT_BALANCE REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE + -- Let's check the overall numbers + Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 + Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 diff --git a/spec/scenario/RepayBorrowEth.scen b/spec/scenario/RepayBorrowEth.scen new file mode 100644 index 000000000..767466af2 --- /dev/null +++ b/spec/scenario/RepayBorrowEth.scen @@ -0,0 +1,206 @@ +-- Tests for repaying borrows + +Macro SetupBorrow borrowRate + NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset + ListedCToken ZRX cZRX borrowRate + ListedEtherToken cETH borrowRate 0.005e9 + SetCollateralFactor cZRX collateralFactor:0.5 + SetCollateralFactor cETH collateralFactor:0.5 + Donate cETH 0.003e18 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cETH + +Macro NewBorrowEth borrowAmount borrowRate + SetupBorrow borrowRate + Borrow Geoff borrowAmount cETH + +Test "Borrow, hold a few blocks, and repay part" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay one full token + Expect Changes (EtherBalance Geoff) -0.001e18 + Expect Changes (EtherBalance cETH) +0.001e18 + RepayBorrowEth Geoff 0.001e18 cETH + ---- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0015e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0015e18 + FastForward 2000 Blocks -- 0.0015e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.003e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.003e18 + +Test "Borrow, hold a few blocks, and repay part via maximillion" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Maximillion Deploy cETH + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay one full token + Expect Changes (EtherBalance Geoff) -0.001e18 + Expect Changes (EtherBalance cETH) +0.001e18 + RepayBorrowEthMax Geoff 0.001e18 cETH + ---- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0015e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0015e18 + FastForward 2000 Blocks -- 0.0015e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.003e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.003e18 + +Test "Don't borrow and then do repay" + SetupBorrow borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + -- Now let's repay one full token + Expect Changes (EtherBalance Geoff) Zero + Expect Changes (EtherBalance cETH) Zero + RepayBorrowEth Geoff 0 cETH + ---- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + +Test "Don't borrow and repay part via maximillion" + SetupBorrow borrowRate:0.0005 + Maximillion Deploy cETH + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + -- Now let's repay one full token + Expect Changes (EtherBalance Geoff) Zero + Expect Changes (EtherBalance cETH) Zero + RepayBorrowEthMax Geoff 0.001e18 cETH + ---- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + +Test "Borrow, hold a few blocks, and repay full" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay fully + Expect Changes (EtherBalance Geoff) -0.0025e18 + Expect Changes (EtherBalance cETH) +0.0025e18 + RepayBorrowEth Geoff 0.0025e18 cETH + -- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + FastForward 2000 Blocks -- 0e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + +Test "Borrow, hold a few blocks, and repay full via maximillion" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Maximillion Deploy cETH + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay fully + Expect Changes (EtherBalance Geoff) -0.0025e18 + Expect Changes (EtherBalance cETH) +0.0025e18 + RepayBorrowEthMax Geoff 0.0025e18 cETH + -- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + FastForward 2000 Blocks -- 0e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + +Test "Borrow, hold a few blocks, and repay too much" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay fully + Expect Changes (EtherBalance Geoff) Zero + Expect Changes (EtherBalance cETH) Zero + -- TODO: This currently drains the sent-eth + AllowFailures + RepayBorrowEth Geoff 1.0e18 cETH + Assert Revert "revert repayBorrow failed" + -- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0025e18 + +Test "Borrow, hold a few blocks, and repay too much via maximillion" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Maximillion Deploy cETH + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay fully + Expect Changes (EtherBalance Geoff) -0.0025e18 + Expect Changes (EtherBalance cETH) +0.0025e18 + RepayBorrowEthMax Geoff 1.0e18 cETH + -- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + FastForward 2000 Blocks -- 0e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) Zero + Assert Equal (CToken cETH TotalBorrowsCurrent) Zero + +Test "Borrow, and get a negative total cash situation" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Let's zoom way forward into the future + FastForward 98000 Blocks -- 0.001e18 * (1 + 98000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.05e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.05e18 + -- Now let's repay one bit + RepayBorrowEth Geoff 0.001e18 cETH + Assert Equal (CToken cETH BorrowBalance Geoff) 0.049e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.049e18 + +Test "Borrow, hold a few blocks, and repay behalf part" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay one full token from another user + RepayBorrowEthBehalf Torrey Geoff 0.001e18 cETH + Assert Equal (CToken cETH BorrowBalance Torrey) Zero + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0015e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0015e18 + FastForward 2000 Blocks -- 0.0015e18 * (1 + 2000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Torrey) Zero + Assert Equal (CToken cETH BorrowBalance Geoff) 0.003e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.003e18 + +Test "Prohibit repay by comptroller hook" + NewBorrowEth borrowAmount:0.001e18 borrowRate:0.0005 + Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + -- Now let's repay one full token + Expect Changes (EtherBalance Geoff) Zero + Expect Changes (EtherBalance cETH) Zero + Comptroller UnList cETH -- Mock unlist cETH + AllowFailures + RepayBorrowEth Geoff 0.001e18 cETH + Assert RevertFailure COMPTROLLER_REJECTION "revert repayBorrow failed" + ---- Let's check the overall numbers + Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 + Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0025e18 diff --git a/spec/scenario/RepayBorrowWBTC.scen b/spec/scenario/RepayBorrowWBTC.scen new file mode 100644 index 000000000..b9381c12d --- /dev/null +++ b/spec/scenario/RepayBorrowWBTC.scen @@ -0,0 +1,189 @@ +-- Tests for repaying borrows + +Macro NewBorrow borrowAmount borrowRate + NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset + NewCToken ZRX cZRX + NewCToken WBTC cWBTC borrowRate 0.1 8 WBTC -- note: cannot use macros with named args right now + Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow + Support cZRX collateralFactor:0.5 + Support cWBTC collateralFactor:0.5 + Prep Geoff Some ZRX cZRX + Mint Geoff 100e18 cZRX + EnterMarkets Geoff cZRX cWBTC + Borrow Geoff borrowAmount cWBTC + +Test "Borrow WBTC, hold a few blocks, and repay part" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay one full token + From Geoff (Erc20 WBTC Approve cWBTC 1.0e8) + RepayBorrow Geoff 1e8 cWBTC + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1.5e8 + -- Let's check the overall numbers + Assert Equal (Erc20 WBTC TokenBalance Geoff) Zero + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 10e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1.5e8 + FastForward 2000 Blocks -- 1.5e8 * (1 + 2000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 3e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 3e8 + +Test "Borrow, hold a few blocks, and repay full" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e8 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay fully + Give Geoff 1.5e8 WBTC -- Geoff had the 1.0e8 borrowed WBTC + From Geoff (Erc20 WBTC Approve cWBTC 2.5e8) + RepayBorrow Geoff 2.5e8 cWBTC + Assert Equal (CToken cWBTC BorrowBalance Geoff) 0e8 + -- Let's check the overall numbers + Assert Equal (Erc20 WBTC TokenBalance Geoff) 0e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 11.5e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 0e8 + FastForward 2000 Blocks -- 0e8 * (1 + 2000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 0e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 0e8 + +Test "Borrow, hold a few blocks, and repay too much" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e8 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay fully + AllowFailures + Prep Geoff 10e8 WBTC cWBTC + Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero + Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero + RepayBorrow Geoff 10e8 cWBTC + Assert Failure MATH_ERROR REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED "3" + -- Let's check the overall numbers + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 + +Test "Borrow, and get a negative total cash situation" + Invariant Success + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 + -- Let's zoom way forward into the future + FastForward 98000 Blocks -- 1e8 * (1 + 98000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 50e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 50e8 + -- Now let's repay one full token + From Geoff (Erc20 WBTC Approve cWBTC 1.0e8) + RepayBorrow Geoff 1.0e8 cWBTC + Assert Equal (CToken cWBTC BorrowBalance Geoff) 49e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 49e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 0e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 10e8 + +Test "Borrow, hold a few blocks, and repay behalf part" + Invariant Success + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e8 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay one full token from another user + Prep Torrey 1.0e8 WBTC cWBTC + RepayBorrowBehalf Torrey Geoff 1.0e8 cWBTC + Assert Equal (CToken cWBTC BorrowBalance Torrey) Zero + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1.5e8 + -- Let's check the overall numbers + Assert Equal (Erc20 WBTC TokenBalance Torrey) 0e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 10e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1.5e8 + FastForward 2000 Blocks -- 1.5e8 * (1 + 2000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Torrey) Zero + Assert Equal (CToken cWBTC BorrowBalance Geoff) 3e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 3e8 + +Test "Prohibit repay by comptroller rejection due to mock unlist" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e8 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay fully + AllowFailures + Prep Geoff 10e8 WBTC cWBTC + Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero + Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero + Comptroller UnList cZRX -- Mock unlist ZRX + RepayBorrow Geoff 2.5e8 cZRX + Assert Failure COMPTROLLER_REJECTION REPAY_BORROW_COMPTROLLER_REJECTION MARKET_NOT_LISTED + -- Let's check the overall numbers + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 + +Test "Borrow WBTC, can't repay when paused" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 + Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 1e18 * (1 + 3000 * 0.0005) + Invariant Remains (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay one full token + From Geoff (Erc20 WBTC Approve cWBTC 1.0e8) + Erc20 WBTC Pause + AllowFailures + RepayBorrow Geoff 1e8 cWBTC + Assert Revert + +Test "Repay fails with insufficient allowance" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e8 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay fully + AllowFailures + Prep Geoff 100e8 WBTC cWBTC allowanceAmount:1.5e8 + Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero + Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero + RepayBorrow Geoff 2.5e8 cWBTC + Assert Failure TOKEN_INSUFFICIENT_ALLOWANCE REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE + -- Let's check the overall numbers + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 + +Test "Repay fails with insufficient balance" + NewBorrow borrowAmount:1e8 borrowRate:0.0005 + Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 + -- Now let's add some blocks and see what happs + FastForward 3000 Blocks -- 0.001e8 * (1 + 3000 * 0.0005) + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + -- Now let's repay fully + AllowFailures + Prep Geoff 0e8 WBTC cWBTC allowanceAmount:2.5e8 + Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero + Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero + RepayBorrow Geoff 2.5e8 cWBTC + Assert Failure TOKEN_INSUFFICIENT_BALANCE REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE + -- Let's check the overall numbers + Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 + Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 diff --git a/spec/scenario/Seize.scen b/spec/scenario/Seize.scen new file mode 100644 index 000000000..ac7aa3c87 --- /dev/null +++ b/spec/scenario/Seize.scen @@ -0,0 +1,50 @@ + +Test "Fail to seize calling directly" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + ListedCToken BAT cBAT initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 50e9 + AllowFailures + Seize 1e9 cZRX caller:Geoff liquidator:Geoff borrower:Torrey + -- The caller must be from another cToken market, thus this fails + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_SEIZE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + +Test "Seize tokens with a paused WBTC cToken-- like normal" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + Erc20 WBTC Pause + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 50e9 + AllowFailures + Seize 1e9 cWBTC caller:Geoff liquidator:Geoff borrower:Torrey + -- The caller must be from another cToken market, thus this fails + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_SEIZE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + +Test "Not able to seize tokens with a malicious unlisted cToken" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + NewCToken EVL cEVL initialExchangeRate:1e9 cTokenType:CEvil + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + Invariant Remains (Erc20 cZRX TokenBalance Geoff) 50e9 + Invariant Static (Erc20 cZRX TokenBalance Geoff) + Invariant Static (Erc20 cZRX TokenBalance Torrey) + AllowFailures + EvilSeize cEVL 1e9 cZRX seizer:Geoff seizee:Torrey + -- The caller must be from another cToken market, thus this fails + Assert Failure COMPTROLLER_REJECTION LIQUIDATE_SEIZE_COMPTROLLER_REJECTION MARKET_NOT_LISTED + +Test "Able to seize tokens with a malicious listed cToken" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + ListedCToken EVL cEVL initialExchangeRate:1e9 cTokenType:CEvil + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) 50e9 + Expect Changes (Erc20 cZRX TokenBalance Geoff) -1e9 + Expect Changes (Erc20 cZRX TokenBalance Torrey) +1e9 + EvilSeize cEVL 1e9 cZRX seizer:Torrey seizee:Geoff diff --git a/spec/scenario/SetComptroller.scen b/spec/scenario/SetComptroller.scen new file mode 100644 index 000000000..e3a7f89d0 --- /dev/null +++ b/spec/scenario/SetComptroller.scen @@ -0,0 +1,26 @@ +-- Sets for `_setComptroller` Admin Function + +Test "Set Comptroller" + NewComptroller + NewCToken ZRX cZRX + Assert Equal (CToken cZRX Comptroller) (Unitroller Address) + ComptrollerImpl Deploy Scenario NewComptroller + From Root (CToken cZRX SetComptroller (ComptrollerImpl NewComptroller Address)) + -- TODO: Fix log assertion + -- Assert Log "NewComptroller" ("oldComptroller" (Unitroller Address)) ("newComptroller" (ComptrollerImpl NewComptroller Address)) + Assert Equal (CToken cZRX Comptroller) (ComptrollerImpl NewComptroller Address) + +Test "Fail when is not a comptroller" + NewComptroller + NewCToken ZRX cZRX + Invariant Remains (CToken cZRX Comptroller) (Unitroller Address) + AllowFailures + From Root (CToken cZRX SetComptroller (PriceOracle Address)) + Assert Revert + +Test "Fail to set comptroller as not admin" + NewComptroller + NewCToken ZRX cZRX + AllowFailures + From Geoff (CToken cZRX SetComptroller (PriceOracle Address)) + Assert Failure UNAUTHORIZED SET_COMPTROLLER_OWNER_CHECK diff --git a/spec/scenario/Supply.scen.old b/spec/scenario/Supply.scen.old new file mode 100644 index 000000000..5ef9eedee --- /dev/null +++ b/spec/scenario/Supply.scen.old @@ -0,0 +1,59 @@ +-- Supply Tests + +Test "Geoff supplies Ether and we check 2 future balances and then supply again" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff Ether "10.0e18" + Faucet Geoff Ether "10.0e18" + Supply Geoff Ether "3e18" + Assert Success + FastForward 2 Blocks + Assert Equal (SupplyBalance Geoff Ether) (Exactly "6.0e18") -- 3 * ( 1 + 2 * .5 ) + FastForward 2 Blocks + Assert Equal (SupplyBalance Geoff Ether) (Exactly "9.0e18") -- 3 * ( 1 + 4 * .5 ) + Supply Geoff Ether "1e18" + Assert Equal (SupplyBalance Geoff Ether) (Exactly "10.0e18") -- 3 * ( 1 + 4 * .5 ) + 1 + FastForward 2 Blocks + Assert Equal (SupplyBalance Geoff Ether) (Exactly "20.0e18") -- 10 * ( 1 + 2 * .5 ) + +Test "Geoff supplies Ether, Torrey supplies Ether and then Geoff supplies more Ether" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff Ether "10.0e18" + Faucet Geoff Ether "10.0e18" + Approve Torrey Ether "5.0e18" + Faucet Torrey Ether "5.0e18" + Supply Geoff Ether "1e18" + Assert Success + FastForward 2 Blocks + Assert Equal (SupplyBalance Geoff Ether) (Exactly "2.0e18") + Supply Torrey Ether "3e18" + Assert Success + FastForward 2 Blocks + Assert Equal (SupplyBalance Torrey Ether) (Exactly "6.0e18") + Assert Equal (SupplyBalance Geoff Ether) (Exactly "4.0e18") + Supply Geoff Ether "1e18" + Assert Equal (SupplyBalance Geoff Ether) (Exactly "5.0e18") + +Test "Can't supply an 'initial' asset" + AddToken Dragon + Approve Geoff Dragon "10.0e18" + Faucet Geoff Dragon "10.0e18" + Supply Geoff Dragon "1e18" + Assert Failure MARKET_NOT_LISTED SUPPLY_MARKET_NOT_LISTED + +Test "Can't supply when contract is paused" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff Ether 1.0e18 + Faucet Geoff Ether 0.4e18 + PolicyHook Ether (SetPaused True) + Supply Geoff Ether 0.3e18 + Assert Failure COMPTROLLER_REJECTION SUPPLY_COMPTROLLER_REJECTION 1 + Assert Equal (SupplyBalance Geoff Ether) (Exactly "0e18") + +Test "With always paused policy hook, can't supply when contract is paused" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) AlwaysPausedPolicyHook + Supply Geoff Ether 0.3e18 + Assert Failure COMPTROLLER_REJECTION SUPPLY_COMPTROLLER_REJECTION 99 diff --git a/spec/scenario/TokenTransfer.scen b/spec/scenario/TokenTransfer.scen new file mode 100644 index 000000000..1c5b01d4b --- /dev/null +++ b/spec/scenario/TokenTransfer.scen @@ -0,0 +1,86 @@ + +Test "Simple cToken Transfer" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + -- Just to be sure, check initial balances + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) + Assert Equal (Erc20 cZRX TokenBalance Torrey) Zero + -- Just transfer + Transfer Geoff Torrey 10e9 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e9) + Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 10e9) + +Test "Simple cToken Transfer When Underlying Paused" + NewComptroller + ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC + Prep Geoff Some WBTC cWBTC + Mint Geoff 50e8 cWBTC + -- Just to be sure, check initial balances + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 50e9) + Assert Equal (Erc20 cWBTC TokenBalance Torrey) Zero + -- Just transfer + Erc20 WBTC Pause + Transfer Geoff Torrey 10e9 cWBTC + Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 40e9) + Assert Equal (Erc20 cWBTC TokenBalance Torrey) (Exactly 10e9) + +Test "Simple cToken Transfer 1:1 Rate" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e0 + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + -- Just to be sure, check initial balances + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e18) + Assert Equal (Erc20 cZRX TokenBalance Torrey) Zero + -- Just transfer + Transfer Geoff Torrey 10e18 cZRX + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e18) + Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 10e18) + +Test "Simple cToken Transfer Not Allowed by Comptroller" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e0 + Comptroller SetCollateralFactor cZRX 0.1 + EnterMarkets Geoff cZRX + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + -- Just to be sure, check initial balances + Invariant Remains (Erc20 cZRX TokenBalance Geoff) (Exactly 50e18) + Invariant Remains (Erc20 cZRX TokenBalance Torrey) Zero + -- Just transfer + AllowFailures + Transfer Geoff Torrey 60e18 cZRX + Assert Failure COMPTROLLER_REJECTION TRANSFER_COMPTROLLER_REJECTION INSUFFICIENT_LIQUIDITY + +Test "Simple cToken Transfer From" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + -- Just to be sure, check initial balances + Invariant Remains (Erc20 cZRX TokenBalance Torrey) Zero + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) + Assert Equal (Erc20 cZRX TokenBalance Coburn) Zero + -- Add approval + From Geoff (Erc20 cZRX Approve Torrey 25e9) + Assert Equal (Erc20 cZRX Allowance Geoff Torrey) (Exactly 25e9) + -- Perform transfer from + From Torrey (Erc20 cZRX TransferFrom Geoff Coburn 10e9) + Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e9) + Assert Equal (Erc20 cZRX TokenBalance Coburn) (Exactly 10e9) + Assert Equal (Erc20 cZRX Allowance Geoff Torrey) (Exactly 15e9) + +Test "cToken Transfer From Not Allowed" + NewComptroller + ListedCToken ZRX cZRX initialExchangeRate:1e9 + Prep Geoff Some ZRX cZRX + Mint Geoff 50e18 cZRX + -- + Invariant Remains (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) + Invariant Remains (Erc20 cZRX TokenBalance Torrey) (Exactly 0e9) + AllowFailures + Erc20 cZRX TransferFrom Geoff Torrey 10e9 + Assert Failure MATH_ERROR TRANSFER_NOT_ALLOWED + diff --git a/spec/scenario/Unitroller.scen b/spec/scenario/Unitroller.scen new file mode 100644 index 000000000..941d0299b --- /dev/null +++ b/spec/scenario/Unitroller.scen @@ -0,0 +1,59 @@ + +Test "Standard Upgrade" + Unitroller Deploy + PriceOracle Deploy Fixed 1.0 + ComptrollerImpl Deploy Scenario ScenComptroller + Unitroller SetPendingImpl ScenComptroller + ComptrollerImpl ScenComptroller Become (PriceOracle Address) 0.2 20 + Assert Equal (Comptroller CloseFactor) 0.2 + Assert Equal (Comptroller MaxAssets) 20 + Assert Equal (Comptroller Implementation) (Address ScenComptroller) + +Test "Once become, can become again" + Unitroller Deploy + PriceOracle Deploy Fixed 1.0 + ComptrollerImpl Deploy Scenario ScenComptroller + Unitroller SetPendingImpl ScenComptroller + ComptrollerImpl ScenComptroller Become (PriceOracle Address) 0.2 20 + Assert Equal (Comptroller CloseFactor) 0.2 + Assert Equal (Comptroller MaxAssets) 20 + Assert Equal (Comptroller Implementation) (Address ScenComptroller) + ComptrollerImpl Deploy Scenario ScenComptroller2 + Unitroller SetPendingImpl ScenComptroller2 + ComptrollerImpl ScenComptroller2 Become (PriceOracle Address) 0.4 40 + Assert Equal (Comptroller CloseFactor) 0.4 + Assert Equal (Comptroller MaxAssets) 40 + Assert Equal (Comptroller Implementation) (Address ScenComptroller2) + +Test "Recome has default values" + Unitroller Deploy + PriceOracle Deploy Fixed 1.0 + ComptrollerImpl Deploy Scenario ScenComptroller + Unitroller SetPendingImpl ScenComptroller + ComptrollerImpl ScenComptroller Recome + Assert Equal (Comptroller CloseFactor) 0.0 + Assert Equal (Comptroller MaxAssets) 0 + Assert Equal (Comptroller Implementation) (Address ScenComptroller) + +Test "Bork and unbork" + Unitroller Deploy + PriceOracle Deploy Fixed 1.0 + ComptrollerImpl Deploy Scenario ScenComptroller + -- Set a normal impl + Unitroller SetPendingImpl ScenComptroller + ComptrollerImpl ScenComptroller Become (PriceOracle Address) 0.2 20 + Assert Equal (Comptroller CloseFactor) 0.2 + Assert Equal (Comptroller MaxAssets) 20 + Assert Equal (Comptroller Implementation) (Address ScenComptroller) + -- Now move to a borked one that's bad + ComptrollerImpl Deploy Borked MyBork + Unitroller SetPendingImpl MyBork + ComptrollerImpl MyBork Become (PriceOracle Address) 0.4 40 + Assert ReadRevert (Comptroller CloseFactor) "revert" + Assert Equal (Comptroller Implementation) (Address MyBork) + -- Now change back to the first good one + Unitroller SetPendingImpl ScenComptroller + ComptrollerImpl ScenComptroller Recome + Assert Equal (Comptroller CloseFactor) 0.2 + Assert Equal (Comptroller MaxAssets) 20 + Assert Equal (Comptroller Implementation) (Address ScenComptroller) diff --git a/spec/scenario/Withdraw.scen.old b/spec/scenario/Withdraw.scen.old new file mode 100644 index 000000000..d6058ce4d --- /dev/null +++ b/spec/scenario/Withdraw.scen.old @@ -0,0 +1,48 @@ +-- Withdraw Tests + +Test "Supply Ether 5 then Withdraw MAX in the same block" + AddToken Ether -- baseline sanity check for withdraw max + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff Ether "6.0e18" + Faucet Geoff Ether "6.0e18" + Supply Geoff Ether "5.0e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Exactly "5.0e18") + Assert Equal (BorrowBalance Geoff Ether) (Exactly "0e18") + Assert Equal (MaxBorrow Geoff) (Exactly "2.5e18") + Withdraw Geoff Ether "MAX" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Exactly "0.0e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "6e18") + +Test "Supply Ether 5 then Withdraw MAX (6) after accruing some interest" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff Ether "6.0e18" + Faucet Geoff Ether "6.0e18" + Supply Geoff Ether "5.0e18" -- We need more Ether in the system to simulate protocol gaining borrow interest to pay Geoff + Approve Torrey Ether "10.0e18" + Faucet Torrey Ether "10.0e18" + Supply Torrey Ether "10.0e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Exactly "5.0e18") + FastForward 2 Blocks + Assert Equal (SupplyBalance Geoff Ether) (Exactly "10.0e18") + Withdraw Geoff Ether "MAX" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Exactly "0.0e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "11e18") + +Test "Withdraw Ether 1 when contract paused" + AddToken Ether + SupportMarket Ether (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Approve Geoff Ether "1.0e18" + Faucet Geoff Ether "1.0e18" + Supply Geoff Ether "1.0e18" + Assert Success + Assert Equal (SupplyBalance Geoff Ether) (Exactly "1.0e18") + PolicyHook Ether (SetPaused True) + Withdraw Geoff Ether "1.0e18" + Assert Failure COMPTROLLER_REJECTION WITHDRAW_COMPTROLLER_REJECTION 1 + Assert Equal (SupplyBalance Geoff Ether) (Exactly "1e18") + Assert Equal (TokenBalance Geoff Ether) (Exactly "0e18") diff --git a/spec/scenario/admin/setMarketPolicyHook.scen.old b/spec/scenario/admin/setMarketPolicyHook.scen.old new file mode 100644 index 000000000..8af26633b --- /dev/null +++ b/spec/scenario/admin/setMarketPolicyHook.scen.old @@ -0,0 +1,41 @@ + +-- Tests for MoneyMarket's `_setMarketPolicyHook(address,address)` function + +Macro ListAsset asset + SupportMarket asset (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Assert Success + +Test "emits log on failure due to non-admin caller" + AddToken Ether + Invariant Static (GetMarketPolicyHook Ether) + From Geoff (SetMarketPolicyHook Ether SimplePolicyHook) + Assert Failure UNAUTHORIZED SET_POLICY_HOOK_OWNER_CHECK + +Test "emits log on failure due to not-listed market" + AddToken Ether + Invariant Static (GetMarketPolicyHook Ether) + SetMarketPolicyHook Ether SimplePolicyHook + Assert Failure MARKET_NOT_LISTED SET_POLICY_HOOK_MARKET_NOT_LISTED + +Test "emits log on failure due to being a bad policy hook" + AddToken Ether + ListAsset Ether + Invariant Static (GetMarketPolicyHook Ether) + SetMarketPolicyHook Ether FakePolicyHook + Assert Failure BAD_INPUT SET_POLICY_HOOK_IS_NOT_POLICY_HOOK + +Test "reverts due to not being a policy hook" + AddToken Ether + ListAsset Ether + Invariant Static (GetMarketPolicyHook Ether) + SetMarketPolicyHook Ether NotPolicyHook + Assert Revert + +Test "successfully sets policy hook" + AddToken Ether + ListAsset Ether + SetMarketPolicyHook Ether SimplePolicyHook + Assert Success + Assert Equal (GetMarketPolicyHook Ether) LastContract + Assert Log "PolicyHookChanged" \ + ("asset" (Address Ether)) ("oldPolicyHook" Anything) ("newPolicyHook" (LastContract)) diff --git a/spec/scenario/admin/setMarketPriceOracle.scen.old b/spec/scenario/admin/setMarketPriceOracle.scen.old new file mode 100644 index 000000000..01ba45d6a --- /dev/null +++ b/spec/scenario/admin/setMarketPriceOracle.scen.old @@ -0,0 +1,38 @@ + +-- Tests for MoneyMarket's `_setMarketPriceOracle(address,address)` function + +Macro ListAsset asset + SupportMarket asset (FixedPrice 1.0) (FixedRate 0.5 0.75) SimplePolicyHook + Assert Success + +Test "is initially unset" + AddToken Ether + Assert Equal (GetMarketPriceOracle Ether) (Exactly 0) + +Test "fails if not called by admin" + AddToken Ether + Invariant Static (GetMarketPriceOracle Ether) + From Geoff (SetMarketPriceOracle Ether Simple) + Assert Failure UNAUTHORIZED SET_ORACLE_OWNER_CHECK + +Test "fails if market not listed" + AddToken Ether + Invariant Static (GetMarketPriceOracle Ether) + SetMarketPriceOracle Ether Simple + Assert Failure MARKET_NOT_LISTED SET_ORACLE_MARKET_NOT_LISTED + +Test "reverts if new address is not really an oracle" + AddToken Ether + ListAsset Ether + Invariant Static (GetMarketPriceOracle Ether) + SetMarketPriceOracle Ether NotPriceOracle + Assert Revert + +Test "successfully set by admin" + AddToken Ether + ListAsset Ether + SetMarketPriceOracle Ether Simple + Assert Success + Assert Equal (GetMarketPriceOracle Ether) LastContract + Assert Log "NewMarketOracle" \ + ("asset" (Address Ether)) ("oldPriceOracle" Anything) ("newPriceOracle" (LastContract)) diff --git a/test/CarefulMathTest.sol b/test/CarefulMathTest.sol new file mode 100644 index 000000000..a9ff3291e --- /dev/null +++ b/test/CarefulMathTest.sol @@ -0,0 +1,167 @@ +pragma solidity ^0.5.8; + +import "truffle/Assert.sol"; +import "../contracts/CarefulMath.sol"; + +contract CarefulMathTest is CarefulMath { + + function testStandardAddition() public { + (MathError err, uint val) = addUInt(5, 6); + + assertNoError(err); + Assert.equal(11, val, "should compute addition correctly"); + } + + function testAddZeroLeft() public { + (MathError err, uint val) = addUInt(0, 6); + + assertNoError(err); + Assert.equal(6, val, "should compute addition correctly"); + } + + function testAddZeroRight() public { + (MathError err, uint val) = addUInt(6, 0); + + assertNoError(err); + Assert.equal(6, val, "should compute addition correctly"); + } + + function testAdditiveOverflow() public { + (MathError err, uint val) = addUInt(5, uint(-1)); + + assertError(MathError.INTEGER_OVERFLOW, err, "should have error INTEGER_OVERFLOW"); + Assert.equal(0, val, "should have default value"); + } + + function testStandardSubtraction() public { + (MathError err, uint val) = subUInt(1000, 250); + + assertNoError(err); + Assert.equal(750, val, "should compute subtraction correctly"); + } + + function testSubtractZero() public { + (MathError err, uint val) = subUInt(1000, 0); + + assertNoError(err); + Assert.equal(1000, val, "should compute subtraction correctly"); + } + + function testSubtractFromZero() public { + (MathError err, uint val) = subUInt(0, 1000); + + assertError(MathError.INTEGER_UNDERFLOW, err, "should have error INTEGER_UNDERFLOW"); + Assert.equal(0, val, "should compute subtraction correctly"); + } + + function testSubtractiveUnderflow() public { + (MathError err, uint val) = subUInt(250, 1000); + + assertError(MathError.INTEGER_UNDERFLOW, err, "should have error INTEGER_UNDERFLOW"); + Assert.equal(0, val, "should compute subtraction correctly"); + } + + function testStandardMultiplication() public { + (MathError err, uint val) = mulUInt(100, 7); + + assertNoError(err); + Assert.equal(700, val, "should compute multiplication correctly"); + } + + function testStandardMultiplicationByZeroLeft() public { + (MathError err, uint val) = mulUInt(0, 100); + + assertNoError(err); + Assert.equal(0, val, "should compute multiplication correctly"); + } + + function testStandardMultiplicationByZeroRight() public { + (MathError err, uint val) = mulUInt(100, 0); + + assertNoError(err); + Assert.equal(0, val, "should compute multiplication correctly"); + } + + function testMultiplicativeOverflow() public { + (MathError err, uint val) = mulUInt(uint(-1), 3); + + assertError(MathError.INTEGER_OVERFLOW, err, "should have error INTEGER_OVERFLOW"); + Assert.equal(0, val, "should have default value"); + } + + function testLargeNumberIdentityMultiplication() public { + (MathError err, uint val) = mulUInt(uint(-1), 1); + + assertNoError(err); + Assert.equal(uint(-1), val, "should compute multiplication correctly"); + } + + function testStandardDivision() public { + (MathError err, uint val) = divUInt(100, 5); + + assertNoError(err); + Assert.equal(20, val, "should compute division correctly"); + } + + function testDivisionWithTruncation() public { + (MathError err, uint val) = divUInt(100, 33); + + assertNoError(err); + Assert.equal(3, val, "should compute division correctly"); + } + + function testDivisionOfZero() public { + (MathError err, uint val) = divUInt(0, 8); + + assertNoError(err); + Assert.equal(0, val, "should compute division correctly"); + } + + function testDivisionByZero() public { + (MathError err, uint val) = divUInt(8, 0); + + assertError(MathError.DIVISION_BY_ZERO, err, "should have error DIVISION_BY_ZERO"); + Assert.equal(0, val, "should have default value"); + } + + function testLargeNumberIdentityDivision() public { + (MathError err, uint val) = divUInt(uint(-1), 1); + + assertNoError(err); + Assert.equal(uint(-1), val, "should compute multiplication correctly"); + } + + + function testAddThenSub() public { + (MathError err, uint val) = addThenSubUInt(1, 3, 2); + + assertNoError(err); + Assert.equal(2, val, "should perform operations in the stated order"); // 1 - 2 before adding 3 would underflow + } + + function testAddThenSubOverflow() public { + (MathError err, uint val) = addThenSubUInt(2**256 - 1, 2**256 - 1, 5); + assertError(MathError.INTEGER_OVERFLOW, err, "should have error INTEGER_OVERFLOW"); + + Assert.equal(0, val, "should have default value"); + } + + function testAddThenSubUnderflow() public { + (MathError err, uint val) = addThenSubUInt(1, 2, 5); + assertError(MathError.INTEGER_UNDERFLOW, err, "should have error INTEGER_UNDERFLOW"); + + Assert.equal(0, val, "should have default value"); + } + + function assertError(MathError expected, MathError given, string memory message) internal { + Assert.equal(uint(expected), uint(given), message); + } + + function assertNoError(MathError err) internal { + assertError(MathError.NO_ERROR, err, "should have error NO_ERROR"); + } + + function assertZero(uint value, string memory message) internal { + Assert.equal(0, value, message); + } +} \ No newline at end of file diff --git a/test/Comptroller/accountLiquidityTest.js b/test/Comptroller/accountLiquidityTest.js new file mode 100644 index 000000000..3390d9472 --- /dev/null +++ b/test/Comptroller/accountLiquidityTest.js @@ -0,0 +1,117 @@ +const {call, send} = require('../Utils/MochaTruffle'); +const { + makeComptroller, + makeCToken, + enterMarkets, + quickMint +} = require('../Utils/Compound'); + +contract('Comptroller', ([root, ...accounts]) => { + describe('liquidity', () => { + it("fails if a price has not been set", async () => { + const cToken = await makeCToken({supportMarket: true}); + await enterMarkets([cToken], accounts[1]); + assert.hasTrollError(await call(cToken.comptroller, 'getAccountLiquidity', [accounts[1]]), 'PRICE_ERROR'); + }); + + it("allows a borrow up to collateralFactor, but not more", async () => { + const collateralFactor = 0.5, underlyingPrice = 1, user = accounts[1], amount = 1e6; + const cToken = await makeCToken({supportMarket: true, collateralFactor, underlyingPrice}); + + let error, liquidity, shortfall; + + // not in market yet, hypothetical borrow should have no effect + ({1: liquidity, 2: shortfall} = await call(cToken.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken._address, 0, amount])); + assert.equal(liquidity, 0); + assert.equal(shortfall, 0); + + await enterMarkets([cToken], user); + await quickMint(cToken, user, amount); + + // total account liquidity after supplying `amount` + ({1: liquidity, 2: shortfall} = await call(cToken.comptroller, 'getAccountLiquidity', [user])); + assert.equal(liquidity, amount * collateralFactor); + assert.equal(shortfall, 0); + + // hypothetically borrow `amount`, should shortfall over collateralFactor + ({1: liquidity, 2: shortfall} = await call(cToken.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken._address, 0, amount])); + assert.equal(liquidity, 0); + assert.equal(shortfall, amount * (1 - collateralFactor)); + + // hypothetically redeem `amount`, should be back to even + ({1: liquidity, 2: shortfall} = await call(cToken.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken._address, amount, 0])); + assert.equal(liquidity, 0); + assert.equal(shortfall, 0); + }); + + it("allows entering 3 markets, supplying to 2 and borrowing up to collateralFactor in the 3rd", async () => { + const amount1 = 1e6, amount2 = 1e3, user = accounts[1]; + const cf1 = 0.5, cf2 = 0.666, cf3 = 0, up1 = 3, up2 = 2.718, up3 = 1; + const c1 = amount1 * cf1 * up1, c2 = amount2 * cf2 * up2, collateral = Math.floor(c1 + c2); + const cToken1 = await makeCToken({supportMarket: true, collateralFactor: cf1, underlyingPrice: up1}); + const cToken2 = await makeCToken({supportMarket: true, comptroller: cToken1.comptroller, collateralFactor: cf2, underlyingPrice: up2}); + const cToken3 = await makeCToken({supportMarket: true, comptroller: cToken1.comptroller, collateralFactor: cf3, underlyingPrice: up3}); + + await enterMarkets([cToken1, cToken2, cToken3], user); + await quickMint(cToken1, user, amount1); + await quickMint(cToken2, user, amount2); + + let error, liquidity, shortfall; + + ({0: error, 1: liquidity, 2: shortfall} = await call(cToken3.comptroller, 'getAccountLiquidity', [user])); + assert.equal(error, 0); + assert.equal(liquidity, collateral); + assert.equal(shortfall, 0); + + ({1: liquidity, 2: shortfall} = await call(cToken3.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken3._address, Math.floor(c2), 0])); + assert.equal(liquidity, collateral); + assert.equal(shortfall, 0); + + ({1: liquidity, 2: shortfall} = await call(cToken3.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken3._address, 0, Math.floor(c2)])); + assert.equal(liquidity, c1); + assert.equal(shortfall, 0); + + ({1: liquidity, 2: shortfall} = await call(cToken3.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken3._address, 0, collateral + c1])); + assert.equal(liquidity, 0); + assert.equal(shortfall, c1); + + ({1: liquidity, 2: shortfall} = await call(cToken1.comptroller, 'getHypotheticalAccountLiquidity', [user, cToken1._address, amount1, 0])); + assert.equal(liquidity, Math.floor(c2)); + assert.equal(shortfall, 0); + }); + }); + + describe("getAccountLiquidity", async () => { + it("returns 0 if not 'in' any markets", async () => { + const comptroller = await makeComptroller(); + const {0: error, 1: liquidity, 2: shortfall} = await call(comptroller, 'getAccountLiquidity', [accounts[0]]); + assert.equal(0, error, "error should be zero"); + assert.equal(0, liquidity, "liquidity should be zero"); + assert.equal(0, shortfall, "shortfall should be zero"); + }); + }); + + describe("getHypotheticalAccountLiquidity", async () => { + it("returns 0 if not 'in' any markets", async () => { + const cToken = await makeCToken(); + const {0: error, 1: liquidity, 2: shortfall} = await call(cToken.comptroller, 'getHypotheticalAccountLiquidity', [accounts[0], cToken._address, 0, 0]); + assert.equal(0, error, "error should be zero"); + assert.equal(0, liquidity, "liquidity should be zero"); + assert.equal(0, shortfall, "shortfall should be zero"); + }); + + it("returns collateral factor times dollar amount of tokens minted in a single market", async () => { + const collateralFactor = 0.5, exchangeRate = 1, underlyingPrice = 1; + const cToken = await makeCToken({supportMarket: true, collateralFactor, exchangeRate, underlyingPrice}); + const from = accounts[0], balance = 1e7, amount = 1e6; + await enterMarkets([cToken], from); + await send(cToken.underlying, 'harnessSetBalance', [from, balance], {from}); + await send(cToken.underlying, 'approve', [cToken._address, balance], {from}); + await send(cToken, 'mint', [amount], {from}); + const {0: error, 1: liquidity, 2: shortfall} = await call(cToken.comptroller, 'getHypotheticalAccountLiquidity', [from, cToken._address, 0, 0]); + assert.equal(0, error, "error should be zero"); + assert.equal(liquidity, amount * collateralFactor * exchangeRate * underlyingPrice, "liquidity should be 5e5"); + assert.equal(shortfall, 0, "shortfall should be zero"); + }); + }); +}); \ No newline at end of file diff --git a/test/Comptroller/adminTest.js b/test/Comptroller/adminTest.js new file mode 100644 index 000000000..adfaba7a8 --- /dev/null +++ b/test/Comptroller/adminTest.js @@ -0,0 +1,110 @@ +const {address, getContract, call, send} = require('../Utils/MochaTruffle'); + +const Unitroller = getContract('Unitroller'); + +contract('admin / _setPendingAdmin / _acceptAdmin', function([root, ...accounts]) { + let comptroller; + beforeEach(async () => { + comptroller = await Unitroller.deploy().send({from: root}); + }); + + describe('admin()', async () => { + it('should return correct admin', async () => { + assert.equal(await call(comptroller, 'admin'), root); + }); + }); + + describe('pendingAdmin()', async () => { + it('should return correct pending admin', async () => { + assert.addressZero(await call(comptroller, 'pendingAdmin')) + }); + }); + + describe('_setPendingAdmin()', async () => { + it('should only be callable by admin', async () => { + assert.hasTrollFailure( + await send(comptroller, '_setPendingAdmin', [accounts[0]], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_PENDING_ADMIN_OWNER_CHECK' + ); + + // Check admin stays the same + assert.equal(await call(comptroller, 'admin'), root); + assert.addressZero(await call(comptroller, 'pendingAdmin')); + }); + + it('should properly set pending admin', async () => { + assert.success(await send(comptroller, '_setPendingAdmin', [accounts[0]])); + + // Check admin stays the same + assert.equal(await call(comptroller, 'admin'), root); + assert.equal(await call(comptroller, 'pendingAdmin'), accounts[0]); + }); + + it('should properly set pending admin twice', async () => { + assert.success(await send(comptroller, '_setPendingAdmin', [accounts[0]])); + assert.success(await send(comptroller, '_setPendingAdmin', [accounts[1]])); + + // Check admin stays the same + assert.equal(await call(comptroller, 'admin'), root); + assert.equal(await call(comptroller, 'pendingAdmin'), accounts[1]); + }); + + it('should emit event', async () => { + const result = await send(comptroller, '_setPendingAdmin', [accounts[0]]); + assert.hasLog(result, 'NewPendingAdmin', { + oldPendingAdmin: address(0), + newPendingAdmin: accounts[0], + }); + }); + }); + + describe('_acceptAdmin()', async () => { + it('should fail when pending admin is zero', async () => { + assert.hasTrollFailure( + await send(comptroller, '_acceptAdmin'), + 'UNAUTHORIZED', + 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK' + ); + + // Check admin stays the same + assert.equal(await call(comptroller, 'admin'), root); + assert.addressZero(await call(comptroller, 'pendingAdmin')); + }); + + it('should fail when called by another account (e.g. root)', async () => { + assert.success(await send(comptroller, '_setPendingAdmin', [accounts[0]])); + assert.hasTrollFailure( + await send(comptroller, '_acceptAdmin'), + 'UNAUTHORIZED', + 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK' + ); + + // Check admin stays the same + assert.equal(await call(comptroller, 'admin'), root); + assert.equal(await call(comptroller, 'pendingAdmin'), accounts[0]); + }); + + it('should succeed and set admin and clear pending admin', async () => { + assert.success(await send(comptroller, '_setPendingAdmin', [accounts[0]])); + assert.success(await send(comptroller, '_acceptAdmin', [], {from: accounts[0]})); + + // Check admin stays the same + assert.equal(await call(comptroller, 'admin'), accounts[0]); + assert.addressZero(await call(comptroller, 'pendingAdmin')); + }); + + it('should emit log on success', async () => { + assert.success(await send(comptroller, '_setPendingAdmin', [accounts[0]])); + const result = await send(comptroller, '_acceptAdmin', [], {from: accounts[0]}); + assert.hasLog(result, 'NewAdmin', { + oldAdmin: root, + newAdmin: accounts[0], + }); + assert.hasLog(result, 'NewPendingAdmin', { + oldPendingAdmin: accounts[0], + newPendingAdmin: address(0), + }); + }); + }); +}); diff --git a/test/Comptroller/assetsListTest.js b/test/Comptroller/assetsListTest.js new file mode 100644 index 000000000..7e5c0c92f --- /dev/null +++ b/test/Comptroller/assetsListTest.js @@ -0,0 +1,186 @@ +const {both, call, send} = require('../Utils/MochaTruffle'); +const { + makeComptroller, + makeCToken +} = require('../Utils/Compound'); + +contract('assetListTest', function([root, customer, ...accounts]) { + let comptroller; + let allTokens, OMG, ZRX, BAT, REP, DAI, SKT; + + beforeEach(async () => { + comptroller = await makeComptroller({maxAssets: 10}); + allTokens = [OMG, ZRX, BAT, REP, DAI, SKT] = await Promise.all( + ['OMG', 'ZRX', 'BAT', 'REP', 'DAI', 'sketch'] + .map(async (name) => makeCToken({comptroller, name, symbol: name, supportMarket: name != 'sketch', underlyingPrice: 0.5})) + ); + }); + + describe('_setMaxAssets', async () => { + it("fails if called by a non-admin", async () => { + assert.hasTrollFailure( + await send(comptroller, '_setMaxAssets', [15], {from: customer}), + 'UNAUTHORIZED', + 'SET_MAX_ASSETS_OWNER_CHECK' + ); + assert.equal(await call(comptroller, 'maxAssets'), 10); + }); + + it("succeeds if called by an admin", async() => { + assert.hasLog( + await send(comptroller, '_setMaxAssets', [15]), + 'NewMaxAssets', { + oldMaxAssets: "10", + newMaxAssets: "15" + }); + assert.equal(await call(comptroller, 'maxAssets'), 15); + }); + }); + + async function checkMarkets(expectedTokens) { + for (let token of allTokens) { + const isExpected = expectedTokens.some(e => e.symbol == token.symbol); + assert.equal(await call(comptroller, 'checkMembership', [customer, token._address]), isExpected, `expected ${token.symbol} ${isExpected}`); + } + } + + async function enterAndCheckMarkets(enterTokens, expectedTokens, expectedErrors = null) { + const {reply, receipt} = await both(comptroller, 'enterMarkets', [enterTokens.map(t => t._address)], {from: customer}); + const assetsIn = await call(comptroller, 'getAssetsIn', [customer]); + assert.each('hasTrollError', reply, expectedErrors || enterTokens.map(_ => 'NO_ERROR')); + assert.trollSuccess(receipt); + assert.deepEqual(assetsIn, expectedTokens.map(t => t._address), 'should match expected markets'); + await checkMarkets(expectedTokens); + return receipt; + }; + + async function exitAndCheckMarkets(exitToken, expectedTokens, expectedError = 'NO_ERROR') { + const {reply, receipt} = await both(comptroller, 'exitMarket', [exitToken._address], {from: customer}); + const assetsIn = await call(comptroller, 'getAssetsIn', [customer]); + assert.hasTrollError(reply, expectedError); + //assert.trollSuccess(receipt); XXX enterMarkets cannot fail, but exitMarket can - kind of confusing + assert.deepEqual(assetsIn, expectedTokens.map(t => t._address), 'should match expected markets'); + await checkMarkets(expectedTokens); + return receipt; + }; + + describe('enterMarkets', async () => { + it("properly emits events", async () => { + const result1 = await enterAndCheckMarkets([OMG], [OMG]); + const result2 = await enterAndCheckMarkets([OMG], [OMG]); + assert.hasLog( + result1, + 'MarketEntered', { + cToken: OMG._address, + account: customer + }); + assert.deepEqual(result2.events, {}, "should have no events"); + }); + + it("adds to the asset list only once", async () => { + await enterAndCheckMarkets([OMG], [OMG]); + await enterAndCheckMarkets([OMG], [OMG]); + await enterAndCheckMarkets([ZRX, BAT, OMG], [OMG, ZRX, BAT]); + await enterAndCheckMarkets([ZRX, OMG], [OMG, ZRX, BAT]); + await enterAndCheckMarkets([ZRX], [OMG, ZRX, BAT]); + await enterAndCheckMarkets([OMG], [OMG, ZRX, BAT]); + await enterAndCheckMarkets([ZRX], [OMG, ZRX, BAT]); + await enterAndCheckMarkets([BAT], [OMG, ZRX, BAT]); + }); + + it("the market must be listed for add to succeed", async () => { + await enterAndCheckMarkets([SKT], [], ['MARKET_NOT_LISTED']); + await send(comptroller, '_supportMarket', [SKT._address]); + await enterAndCheckMarkets([SKT], [SKT]); + }); + + it("returns a list of codes mapping to user's ultimate membership in given addresses", async () => { + await enterAndCheckMarkets([OMG, ZRX, BAT], [OMG, ZRX, BAT], ['NO_ERROR', 'NO_ERROR', 'NO_ERROR'], "success if can enter markets"); + await enterAndCheckMarkets([OMG, SKT], [OMG, ZRX, BAT], ['NO_ERROR', 'MARKET_NOT_LISTED'], "error for unlisted markets"); + }); + + it("can enter one + asset cap reached", async () => { + await send(comptroller, '_setMaxAssets', [1]); + await enterAndCheckMarkets([ZRX, OMG], [ZRX], ['NO_ERROR', 'TOO_MANY_ASSETS'], "error if asset cap reached"); + }); + + it("reaches asset cap + already in asset", async () => { + await send(comptroller, '_setMaxAssets', [1]); + await enterAndCheckMarkets([ZRX], [ZRX]); + await enterAndCheckMarkets([OMG, ZRX], [ZRX], ['TOO_MANY_ASSETS', 'NO_ERROR'], "error if already in asset"); + }); + + describe('reaching the asset cap', async () => { + beforeEach(async () => { + await send(comptroller, '_setMaxAssets', [3]); + await enterAndCheckMarkets([OMG, ZRX, BAT], [OMG, ZRX, BAT]); + }); + + it("does not grow if user exactly at asset cap", async () => { + await send(comptroller, '_setMaxAssets', [3]); + await enterAndCheckMarkets([REP], [OMG, ZRX, BAT], ['TOO_MANY_ASSETS']); + await send(comptroller, '_setMaxAssets', [4]); + await enterAndCheckMarkets([REP], [OMG, ZRX, BAT, REP]); + await enterAndCheckMarkets([DAI], [OMG, ZRX, BAT, REP], ['TOO_MANY_ASSETS']); + }); + + it("does not grow if user is well beyond asset cap", async () => { + await send(comptroller, '_setMaxAssets', [1]); + await enterAndCheckMarkets([REP], [OMG, ZRX, BAT], ['TOO_MANY_ASSETS']); + }); + }); + }); + + describe('exitMarket', async () => { + it("doesn't let you exit if you have a borrow balance", async () => { + await enterAndCheckMarkets([OMG], [OMG]); + await send(OMG, 'harnessSetAccountBorrows', [customer, 1, 1]); + await exitAndCheckMarkets(OMG, [OMG], 'NONZERO_BORROW_BALANCE'); + }); + + it("rejects unless redeem allowed", async () => { + await enterAndCheckMarkets([OMG, BAT], [OMG, BAT]); + await send(BAT, 'harnessSetAccountBorrows', [customer, 1, 1]); + + // BAT has a negative balance and there's no supply, thus account should be underwater + await exitAndCheckMarkets(OMG, [OMG, BAT], 'REJECTION'); + }); + + it("accepts when you're not in the market already", async () => { + await enterAndCheckMarkets([OMG, BAT], [OMG, BAT]); + + // Not in ZRX, should exit fine + await exitAndCheckMarkets(ZRX, [OMG, BAT], 'NO_ERROR'); + }); + + it("properly removes when there's only one asset", async () => { + await enterAndCheckMarkets([OMG], [OMG]); + await exitAndCheckMarkets(OMG, [], 'NO_ERROR'); + }); + + it("properly removes when there's only two assets, removing the first", async () => { + await enterAndCheckMarkets([OMG, BAT], [OMG, BAT]); + await exitAndCheckMarkets(OMG, [BAT], 'NO_ERROR'); + }); + + it("properly removes when there's only two assets, removing the second", async () => { + await enterAndCheckMarkets([OMG, BAT], [OMG, BAT]); + await exitAndCheckMarkets(BAT, [OMG], 'NO_ERROR'); + }); + + it("properly removes when there's only three assets, removing the first", async () => { + await enterAndCheckMarkets([OMG, BAT, ZRX], [OMG, BAT, ZRX]); + await exitAndCheckMarkets(OMG, [ZRX, BAT], 'NO_ERROR'); + }); + + it("properly removes when there's only three assets, removing the second", async () => { + await enterAndCheckMarkets([OMG, BAT, ZRX], [OMG, BAT, ZRX]); + await exitAndCheckMarkets(BAT, [OMG, ZRX], 'NO_ERROR'); + }); + + it("properly removes when there's only three assets, removing the third", async () => { + await enterAndCheckMarkets([OMG, BAT, ZRX], [OMG, BAT, ZRX]); + await exitAndCheckMarkets(ZRX, [OMG, BAT], 'NO_ERROR'); + }); + }); +}); diff --git a/test/Comptroller/comptrollerTest.js b/test/Comptroller/comptrollerTest.js new file mode 100644 index 000000000..b183b58ba --- /dev/null +++ b/test/Comptroller/comptrollerTest.js @@ -0,0 +1,250 @@ +const { + etherMantissa, + both, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeComptroller, + makePriceOracle, + makeCToken, + makeToken +} = require('../Utils/Compound'); + +contract('Comptroller', ([root, ...accounts]) => { + describe('constructor', () => { + it("on success it sets admin to creator and pendingAdmin is unset", async () => { + const comptroller = await makeComptroller(); + assert.equal(root, await call(comptroller, 'admin')); + assert.equal(0, await call(comptroller, 'pendingAdmin')); + }); + + it("on success it sets closeFactor and maxAssets as specified", async () => { + const comptroller = await makeComptroller(); + assert.equal(.051e18, await call(comptroller, 'closeFactorMantissa')); + assert.equal(10, await call(comptroller, 'maxAssets')); + }); + + it("reverts on invalid closeFactor", async () => { + await assert.revert(makeComptroller({closeFactor: 1}), 'revert set close factor error'); + }); + + it("allows small and large maxAssets", async () => { + const comptroller = await makeComptroller({maxAssets: 0}); + assert.equal(0, await call(comptroller, 'maxAssets')); + + // 5000 is an arbitrary number larger than what we expect to ever actually use + await send(comptroller, '_setMaxAssets', [5000]); + assert.equal(5000, await call(comptroller, 'maxAssets')); + }); + }); + + describe('_setLiquidationIncentive', async () => { + const initialIncentive = etherMantissa(1.0); + const validIncentive = etherMantissa(1.1); + const tooSmallIncentive = etherMantissa(0.99999); + const tooLargeIncentive = etherMantissa(1.50000001); + + let comptroller; + before(async () => { + comptroller = await makeComptroller(); + }); + + it("fails if called by non-admin", async () => { + const {reply, receipt} = await both(comptroller, '_setLiquidationIncentive', [initialIncentive], {from: accounts[0]}); + assert.hasTrollError(reply, 'UNAUTHORIZED'); + assert.hasTrollFailure( + receipt, + 'UNAUTHORIZED', + 'SET_LIQUIDATION_INCENTIVE_OWNER_CHECK' + ); + assert.equal(await call(comptroller, 'liquidationIncentiveMantissa'), initialIncentive); + }); + + it("fails if incentive is less than min", async () => { + const {reply, receipt} = await both(comptroller, '_setLiquidationIncentive', [tooSmallIncentive]); + assert.hasTrollError(reply, 'INVALID_LIQUIDATION_INCENTIVE'); + assert.hasTrollFailure( + receipt, + 'INVALID_LIQUIDATION_INCENTIVE', + 'SET_LIQUIDATION_INCENTIVE_VALIDATION' + ); + assert.equal(await call(comptroller, 'liquidationIncentiveMantissa'), initialIncentive); + }); + + it("fails if incentive is greater than max", async () => { + const {reply, receipt} = await both(comptroller, '_setLiquidationIncentive', [tooLargeIncentive]); + assert.hasTrollError(reply, 'INVALID_LIQUIDATION_INCENTIVE'); + assert.hasTrollFailure( + receipt, + 'INVALID_LIQUIDATION_INCENTIVE', + 'SET_LIQUIDATION_INCENTIVE_VALIDATION' + ); + assert.equal(await call(comptroller, 'liquidationIncentiveMantissa'), initialIncentive); + }); + + it("accepts a valid incentive and emits a NewLiquidationIncentive event", async () => { + const {reply, receipt} = await both(comptroller, '_setLiquidationIncentive', [validIncentive]); + assert.hasTrollError(reply, 'NO_ERROR'); + assert.hasLog(receipt, 'NewLiquidationIncentive', { + oldLiquidationIncentiveMantissa: initialIncentive.toString(), + newLiquidationIncentiveMantissa: validIncentive.toString() + }); + assert.equal(await call(comptroller, 'liquidationIncentiveMantissa'), validIncentive); + }); + }); + + describe('_setPriceOracle', async () => { + let comptroller, oldOracle, newOracle; + before(async () => { + comptroller = await makeComptroller(); + oldOracle = comptroller.priceOracle; + newOracle = await makePriceOracle(); + }); + + it("fails if called by non-admin", async () => { + assert.hasTrollFailure( + await send(comptroller, '_setPriceOracle', [newOracle._address], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_PRICE_ORACLE_OWNER_CHECK' + ); + assert.equal(await comptroller.methods.oracle().call(), oldOracle._address); + }); + + it.skip("reverts if passed a contract that doesn't implement isPriceOracle", async () => { + await assert.revert(send(comptroller, '_setPriceOracle', [comptroller._address])); + assert.equal(await call(comptroller, 'oracle'), oldOracle._address); + }); + + it.skip("reverts if passed a contract that implements isPriceOracle as false", async () => { + await send(newOracle, 'setIsPriceOracle', [false]); // Note: not yet implemented + await assert.revert(send(notOracle, '_setPriceOracle', [comptroller._address]), "revert oracle method isPriceOracle returned false"); + assert.equal(await call(comptroller, 'oracle'), oldOracle._address); + }); + + it("accepts a valid price oracle and emits a NewPriceOracle event", async () => { + const result = await send(comptroller, '_setPriceOracle', [newOracle._address]); + assert.success(result); + assert.hasLog(result, 'NewPriceOracle', { + oldPriceOracle: oldOracle._address, + newPriceOracle: newOracle._address + }); + assert.equal(await call(comptroller, 'oracle'), newOracle._address); + }); + }); + + describe('_setCollateralFactor', async () => { + const half = etherMantissa(0.5), one = etherMantissa(1); + + it("fails if not called by admin", async () => { + const cToken = await makeCToken(); + assert.hasTrollFailure( + await send(cToken.comptroller, '_setCollateralFactor', [cToken._address, half], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_COLLATERAL_FACTOR_OWNER_CHECK' + ); + }); + + it("fails if asset is not listed", async () => { + const cToken = await makeCToken(); + assert.hasTrollFailure( + await send(cToken.comptroller, '_setCollateralFactor', [cToken._address, half]), + 'MARKET_NOT_LISTED', + 'SET_COLLATERAL_FACTOR_NO_EXISTS' + ); + }); + + it("fails if factor is too high", async () => { + const cToken = await makeCToken({supportMarket: true}); + assert.hasTrollFailure( + await send(cToken.comptroller, '_setCollateralFactor', [cToken._address, one]), + 'INVALID_COLLATERAL_FACTOR', + 'SET_COLLATERAL_FACTOR_VALIDATION' + ); + }); + + it("fails if factor is set without an underlying price", async () => { + const cToken = await makeCToken({supportMarket: true}); + assert.hasTrollFailure( + await send(cToken.comptroller, '_setCollateralFactor', [cToken._address, half]), + 'PRICE_ERROR', + 'SET_COLLATERAL_FACTOR_WITHOUT_PRICE' + ); + }); + + it("succeeds and sets market", async () => { + const cToken = await makeCToken({supportMarket: true, underlyingPrice: 1}); + const result = await send(cToken.comptroller, '_setCollateralFactor', [cToken._address, half]); + assert.hasLog(result, 'NewCollateralFactor', { + cToken: cToken._address, + oldCollateralFactorMantissa: '0', + newCollateralFactorMantissa: half.toString() + }); + }); + }); + + describe('_supportMarket', async () => { + it("fails if not called by admin", async () => { + const cToken = await makeCToken(root); + assert.hasTrollFailure( + await send(cToken.comptroller, '_supportMarket', [cToken._address], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SUPPORT_MARKET_OWNER_CHECK' + ); + }); + + it("fails if asset is not a CToken", async () => { + const comptroller = await makeComptroller() + const asset = await makeToken(root); + await assert.revert(send(comptroller, '_supportMarket', [asset._address])); + }); + + it("succeeds and sets market", async () => { + const cToken = await makeCToken(); + const result = await send(cToken.comptroller, '_supportMarket', [cToken._address]); + assert.hasLog(result, 'MarketListed', {cToken: cToken._address}); + }); + + it("cannot list a market a second time", async () => { + const cToken = await makeCToken(); + const result1 = await send(cToken.comptroller, '_supportMarket', [cToken._address]); + const result2 = await send(cToken.comptroller, '_supportMarket', [cToken._address]); + assert.hasLog(result1, 'MarketListed', {cToken: cToken._address}); + assert.hasTrollFailure( + result2, + 'MARKET_ALREADY_LISTED', + 'SUPPORT_MARKET_EXISTS' + ); + }); + + it("can list two different markets", async () => { + const cToken1 = await makeCToken(); + const cToken2 = await makeCToken({comptroller: cToken1.comptroller}); + const result1 = await send(cToken1.comptroller, '_supportMarket', [cToken1._address]); + const result2 = await send(cToken1.comptroller, '_supportMarket', [cToken2._address]); + assert.hasLog(result1, 'MarketListed', {cToken: cToken1._address}); + assert.hasLog(result2, 'MarketListed', {cToken: cToken2._address}); + }); + }); + + describe('redeemVerify', async () => { + it('should allow you to redeem 0 underlying for 0 tokens', async () => { + const comptroller = await makeComptroller(); + const cToken = await makeCToken({comptroller: comptroller}); + await call(comptroller, 'redeemVerify', [cToken._address, accounts[0], 0, 0]); + }); + + it('should allow you to redeem 5 underlyig for 5 tokens', async () => { + const comptroller = await makeComptroller(); + const cToken = await makeCToken({comptroller: comptroller}); + await call(comptroller, 'redeemVerify', [cToken._address, accounts[0], 5, 5]); + }); + + it('should not allow you to redeem 5 underlying for 0 tokens', async () => { + const comptroller = await makeComptroller(); + const cToken = await makeCToken({comptroller: comptroller}); + await assert.revert(call(comptroller, 'redeemVerify', [cToken._address, accounts[0], 5, 0]), "revert redeemTokens zero"); + }); + }) +}); diff --git a/test/Comptroller/liquidateCalculateAmountSeizeTest.js b/test/Comptroller/liquidateCalculateAmountSeizeTest.js new file mode 100644 index 000000000..f8c5482fc --- /dev/null +++ b/test/Comptroller/liquidateCalculateAmountSeizeTest.js @@ -0,0 +1,97 @@ +const {etherUnsigned, call, send} = require('../Utils/MochaTruffle'); +const { + makeComptroller, + makeCToken, + setOraclePrice +} = require('../Utils/Compound'); + +const borrowedPrice = 2e10; +const collateralPrice = 1e18; +const repayAmount = etherUnsigned(1e18); + +async function calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, repayAmount) { + return call(comptroller, 'liquidateCalculateSeizeTokens', [cTokenBorrowed._address, cTokenCollateral._address, repayAmount]); +} + +function rando(min, max) { + return Math.floor(Math.random() * (max - min)) + min; +} + +contract('Comptroller', function([root, ...accounts]) { + let comptroller, cTokenBorrowed, cTokenCollateral; + before(async () => { + comptroller = await makeComptroller(); + cTokenBorrowed = await makeCToken({comptroller: comptroller, underlyingPrice: 0}); + cTokenCollateral = await makeCToken({comptroller: comptroller, underlyingPrice: 0}); + }); + + beforeEach(async () => { + await setOraclePrice(cTokenBorrowed, borrowedPrice); + await setOraclePrice(cTokenCollateral, collateralPrice); + await send(cTokenCollateral, 'harnessExchangeRateDetails', [8e10, 4e10, 0]); + }); + + describe('liquidateCalculateAmountSeize', async () => { + it("fails if either asset price is 0", async () => { + await setOraclePrice(cTokenBorrowed, 0); + assert.hasTrollErrorTuple( + await calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, repayAmount), + ['PRICE_ERROR', 0] + ); + + await setOraclePrice(cTokenCollateral, 0); + assert.hasTrollErrorTuple( + await calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, repayAmount), + ['PRICE_ERROR', 0] + ); + }); + + it("fails if the repayAmount causes overflow ", async () => { + assert.hasTrollErrorTuple( + await calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, -1), + ['MATH_ERROR', 0] + ); + }); + + it("fails if the borrowed asset price causes overflow ", async () => { + await setOraclePrice(cTokenBorrowed, -1); + assert.hasTrollErrorTuple( + await calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, repayAmount), + ['MATH_ERROR', 0] + ); + }); + + it("reverts if it fails to calculate the exchange rate", async () => { + await send(cTokenCollateral, 'harnessExchangeRateDetails', [1, 0, 10]); // (1 - 10) -> underflow + await assert.revert( + send(comptroller, 'liquidateCalculateSeizeTokens', [cTokenBorrowed._address, cTokenCollateral._address, repayAmount]), + "revert exchangeRateStored: exchangeRateStoredInternal failed" + ); + }); + + [ + [1e18, 1e18, 1e18, 1e18, 1e18], + [2e18, 1e18, 1e18, 1e18, 1e18], + [2e18, 2e18, 1.42e18, 1.3e18, 2.45e18], + [2.789e18, 5.230480842e18, 771.32e18, 1.3e18, 10002.45e18], + [ 7.009232529961056e+24,2.5278726317240445e+24,2.6177112093242585e+23,1179713989619784000,7.790468414639561e+24 ], + [rando(0, 1e25), rando(0, 1e25), rando(1, 1e25), rando(1e18, 1.5e18), rando(0, 1e25)] + ].forEach((testCase) => { + it(`returns the correct value for ${testCase}`, async () => { + const [exchangeRate, borrowedPrice, collateralPrice, liquidationIncentive, repayAmount] = testCase.map(etherUnsigned); + + await setOraclePrice(cTokenCollateral, collateralPrice); + await setOraclePrice(cTokenBorrowed, borrowedPrice); + await send(comptroller, '_setLiquidationIncentive', [liquidationIncentive]); + await send(cTokenCollateral, 'harnessSetExchangeRate', [exchangeRate]); + + const seizeAmount = repayAmount.mul(liquidationIncentive).mul(borrowedPrice).div(collateralPrice); + const seizeTokens = seizeAmount.div(exchangeRate); + assert.hasTrollErrorTuple( + await calculateSeizeTokens(comptroller, cTokenBorrowed, cTokenCollateral, repayAmount), + ['NO_ERROR', (x) => assert.approximately(Number(x), Number(seizeTokens), 1e7)] + ); + }); + }); + }); +}); diff --git a/test/Comptroller/proxiedComptrollerV1Test.js b/test/Comptroller/proxiedComptrollerV1Test.js new file mode 100644 index 000000000..74b6a4d6e --- /dev/null +++ b/test/Comptroller/proxiedComptrollerV1Test.js @@ -0,0 +1,192 @@ +const { + address, + etherMantissa, + getContract, + getTestContract, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeComptroller, + makeCToken, + makePriceOracle +} = require('../Utils/Compound'); + +const Unitroller = getContract('Unitroller'); +const Comptroller = getContract('Comptroller'); + +contract('ComptrollerV1', function([root, ...accounts]) { + let unitroller; + let brains; + let oracle; + + before(async () => { + oracle = await makePriceOracle() + brains = await Comptroller.deploy().send({from: root}); + }); + + beforeEach(async () => { + unitroller = await Unitroller.deploy().send({from: root}); + }); + + let initializeBrains = async (priceOracle, closeFactor, maxAssets) => { + await send(unitroller, '_setPendingImplementation', [brains._address]); + await send(brains, '_become', [unitroller._address, priceOracle._address, closeFactor, maxAssets, false]); + return Comptroller.at(unitroller._address); + }; + + let reinitializeBrains = async () => { + await send(unitroller, '_setPendingImplementation', [brains._address]); + await send(brains, '_become', [unitroller._address, address(0), 0, 0, true]); + return Comptroller.at(unitroller._address); + }; + + describe("delegating to comptroller v1", async () => { + const closeFactor = etherMantissa(.051), maxAssets = 10; + + let unitrollerAsComptroller, cToken; + beforeEach( async () => { + unitrollerAsComptroller = await initializeBrains(oracle, etherMantissa(.06), 30); + cToken = await makeCToken({comptroller: unitrollerAsComptroller}); + }); + + describe("becoming brains sets initial state", async () => { + it("reverts if this is not the pending implementation", async () => { + await assert.revert(send(brains, '_become', [unitroller._address, oracle._address, 0, 10, false]), "revert change not authorized"); + }); + + it("on success it sets admin to caller of constructor", async () => { + assert.equal(await call(unitrollerAsComptroller, 'admin'), root); + assert.addressZero(await call(unitrollerAsComptroller, 'pendingAdmin'), "pendingAdmin should be zero for a new contract"); + }); + + it("on success it sets closeFactor and maxAssets as specified", async () => { + const comptroller = await initializeBrains(oracle, closeFactor, maxAssets); + assert.equal(await call(comptroller, 'closeFactorMantissa'), closeFactor, "closeFactor"); + assert.equal(await call(comptroller, 'maxAssets'), maxAssets, "maxAssets"); + }); + + it("on reinitialization success, it doesn't set closeFactor or maxAssets", async () => { + let comptroller = await initializeBrains(oracle, closeFactor, maxAssets); + assert.equal(await call(unitroller, 'comptrollerImplementation'), brains._address); + assert.equal(await call(comptroller, 'closeFactorMantissa',), closeFactor, "closeFactor"); + assert.equal(await call(comptroller, 'maxAssets'), maxAssets, "maxAssets"); + + // Create new brains + brains = await Comptroller.deploy().send({from: root}); + comptroller = await reinitializeBrains(); + + assert.equal(await call(unitroller, 'comptrollerImplementation'), brains._address); + assert.equal(await call(comptroller, 'closeFactorMantissa'), closeFactor, "closeFactor"); + assert.equal(await call(comptroller, 'maxAssets'), maxAssets, "maxAssets"); + }); + + it("reverts on invalid closeFactor", async () => { + await send(unitroller, '_setPendingImplementation', [brains._address]); + await assert.revert(send(brains, '_become', [unitroller._address, oracle._address, 0, maxAssets, false]), "revert set close factor error"); + }); + + it("allows 0 maxAssets", async () => { + const comptroller = await initializeBrains(oracle, closeFactor, 0); + assert.equal(await call(comptroller, 'maxAssets'), 0, "maxAssets"); + }); + + it("allows 5000 maxAssets", async () => { + // 5000 is an arbitrary number larger than what we expect to ever actually use + const comptroller = await initializeBrains(oracle, closeFactor, 5000); + assert.equal(await call(comptroller, 'maxAssets'), 5000, "maxAssets"); + }); + }); + + describe("_setCollateralFactor", async () => { + const half = etherMantissa(.5), one = etherMantissa(1); + + it("fails if not called by admin", async () => { + assert.hasTrollFailure( + await send(unitrollerAsComptroller, '_setCollateralFactor', [cToken._address, half], {from: accounts[1]}), + 'UNAUTHORIZED', + 'SET_COLLATERAL_FACTOR_OWNER_CHECK' + ); + }); + + it("fails if asset is not listed", async () => { + assert.hasTrollFailure( + await send(unitrollerAsComptroller, '_setCollateralFactor', [cToken._address, half]), + 'MARKET_NOT_LISTED', + 'SET_COLLATERAL_FACTOR_NO_EXISTS' + ); + }); + + it("fails if factor is too high", async () => { + const cToken = await makeCToken({supportMarket: true, comptroller: unitrollerAsComptroller}); + assert.hasTrollFailure( + await send(unitrollerAsComptroller, '_setCollateralFactor', [cToken._address, one]), + 'INVALID_COLLATERAL_FACTOR', + 'SET_COLLATERAL_FACTOR_VALIDATION' + ); + }); + + it("fails if factor is set without an underlying price", async () => { + const cToken = await makeCToken({supportMarket: true, comptroller: unitrollerAsComptroller}); + assert.hasTrollFailure( + await send(unitrollerAsComptroller, '_setCollateralFactor', [cToken._address, half]), + 'PRICE_ERROR', + 'SET_COLLATERAL_FACTOR_WITHOUT_PRICE' + ); + }); + + it("succeeds and sets market", async () => { + const cToken = await makeCToken({supportMarket: true, comptroller: unitrollerAsComptroller}); + await send(oracle, 'setUnderlyingPrice', [cToken._address, 1]); + assert.hasLog( + await send(unitrollerAsComptroller, '_setCollateralFactor', [cToken._address, half]), + 'NewCollateralFactor', { + cToken: cToken._address, + oldCollateralFactorMantissa: "0", + newCollateralFactorMantissa: half.toString() + }); + }); + }); + + describe("_supportMarket", async () => { + it("fails if not called by admin", async () => { + assert.hasTrollFailure( + await send(unitrollerAsComptroller, '_supportMarket', [cToken._address], {from: accounts[1]}), + 'UNAUTHORIZED', + 'SUPPORT_MARKET_OWNER_CHECK' + ); + }); + + it("fails if asset is not a CToken", async () => { + const notACToken = await makePriceOracle(); + await assert.revert(send(unitrollerAsComptroller, '_supportMarket', [notACToken._address])); + }); + + it("succeeds and sets market", async () => { + const result = await send(unitrollerAsComptroller, '_supportMarket', [cToken._address]); + assert.hasLog(result, 'MarketListed', {cToken: cToken._address}); + }); + + it("cannot list a market a second time", async () => { + const result1 = await send(unitrollerAsComptroller, '_supportMarket', [cToken._address]); + const result2 = await send(unitrollerAsComptroller, '_supportMarket', [cToken._address]); + assert.hasLog(result1, 'MarketListed', {cToken: cToken._address}); + assert.hasTrollFailure( + result2, + 'MARKET_ALREADY_LISTED', + 'SUPPORT_MARKET_EXISTS' + ); + }); + + it("can list two different markets", async () => { + const cToken1 = await makeCToken({comptroller: unitroller}); + const cToken2 = await makeCToken({comptroller: unitroller}); + const result1 = await send(unitrollerAsComptroller, '_supportMarket', [cToken1._address]); + const result2 = await send(unitrollerAsComptroller, '_supportMarket', [cToken2._address]); + assert.hasLog(result1, 'MarketListed', {cToken: cToken1._address}); + assert.hasLog(result2, 'MarketListed', {cToken: cToken2._address}); + }); + }); + }); +}); diff --git a/test/Comptroller/unitrollerTest.js b/test/Comptroller/unitrollerTest.js new file mode 100644 index 000000000..0eea6fa41 --- /dev/null +++ b/test/Comptroller/unitrollerTest.js @@ -0,0 +1,180 @@ +const { + address, + etherMantissa, + getContract, + getTestContract, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeComptroller, + makePriceOracle +} = require('../Utils/Compound'); + +const Unitroller = getContract('Unitroller'); +const Comptroller = getContract('Comptroller'); +const EchoTypesComptroller = getTestContract('EchoTypesComptroller'); + +contract('Unitroller', function([root, ...accounts]) { + let unitroller; + let brains; + let oracle; + before(async () => { + oracle = await makePriceOracle() + brains = await Comptroller.deploy().send({from: root}); + }); + + beforeEach(async () => { + unitroller = await Unitroller.deploy().send({from: root}); + }); + + let setPending = (implementation, from) => { + return send(unitroller, '_setPendingImplementation', [implementation._address], {from}); + }; + + describe("constructor", async () => { + it("sets admin to caller and addresses to 0", async () => { + assert.equal(await call(unitroller, 'admin'), root); + assert.addressZero(await call(unitroller, 'pendingAdmin')); + assert.addressZero(await call(unitroller, 'pendingComptrollerImplementation')); + assert.addressZero(await call(unitroller, 'comptrollerImplementation')); + }); + }); + + describe("_setPendingImplementation", async () => { + describe("Check caller is admin", async () => { + let result; + before(async () => { + result = await setPending(brains, accounts[1]); + }); + + it("emits a failure log", async () => { + assert.hasTrollFailure( + result, + 'UNAUTHORIZED', + 'SET_PENDING_IMPLEMENTATION_OWNER_CHECK' + ); + }); + + it("does not change pending implementation address", async () => { + assert.addressZero(await call(unitroller, 'pendingComptrollerImplementation')) + }); + }); + + describe("succeeding", async () => { + it("stores pendingComptrollerImplementation with value newPendingImplementation", async () => { + await setPending(brains, root); + assert.equal(await call(unitroller, 'pendingComptrollerImplementation'), brains._address); + }); + + it("emits NewPendingImplementation event", async () => { + assert.hasLog( + await send(unitroller, '_setPendingImplementation', [brains._address]), + 'NewPendingImplementation', { + oldPendingImplementation: address(0), + newPendingImplementation: brains._address + }); + }); + }); + }); + + describe("_acceptImplementation", async () => { + describe("Check caller is pendingComptrollerImplementation and pendingComptrollerImplementation ≠ address(0) ", async () => { + let result; + beforeEach(async () => { + await setPending(unitroller, root); + result = await send(unitroller, '_acceptImplementation'); + }); + + it("emits a failure log", async () => { + assert.hasTrollFailure( + result, + 'UNAUTHORIZED', + 'ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK' + ); + }); + + it("does not change current implementation address", async () => { + assert.notEqual(await call(unitroller, 'comptrollerImplementation'), unitroller._address); + }); + }); + + it.skip("rejects if pending impl is address(0)", async () => { + // XXX TODO? + }); + + describe("the brains must accept the responsibility of implementation", async () => { + let result; + beforeEach(async () => { + await setPending(brains, root); + result = await send(brains, '_become', [unitroller._address, oracle._address, etherMantissa(.051), 10, false]); + assert.success(result); + }); + + it("Store comptrollerImplementation with value pendingComptrollerImplementation", async () => { + assert.equal(await call(unitroller, 'comptrollerImplementation'), brains._address); + }); + + it("Unset pendingComptrollerImplementation", async () => { + assert.addressZero(await call(unitroller, 'pendingComptrollerImplementation')); + }); + + it.skip("Emit NewImplementation(oldImplementation, newImplementation)", async () => { + // TODO: + // Does our log decoder expect it to come from the same contract? + // assert.hasLog( + // result, + // "NewImplementation", + // { + // newImplementation: brains._address, + // oldImplementation: "0x0000000000000000000000000000000000000000" + // }); + }); + + it.skip("Emit NewPendingImplementation(oldPendingImplementation, 0)", async () => { + // TODO: + // Does our log decoder expect it to come from the same contract? + // Having difficulty decoding these events + // assert.hasLog( + // result, + // "NewPendingImplementation", + // { + // oldPendingImplementation: brains._address, + // newPendingImplementation: "0x0000000000000000000000000000000000000000" + // }); + }); + }); + + describe("fallback delegates to brains", async () => { + let troll; + before(async () => { + troll = await EchoTypesComptroller.deploy().send({from: root}); + unitroller = await Unitroller.deploy().send({from: root}); + await setPending(troll, root); + await send(troll, 'becomeBrains', [unitroller._address]); + troll.options.address = unitroller._address; + }); + + it("forwards reverts", async () => { + await assert.revert(call(troll, 'reverty'), "revert gotcha sucka"); + }); + + it("gets addresses", async () => { + assert.equal(await call(troll, 'addresses', [troll._address]), troll._address); + }); + + it("gets strings", async () => { + assert.equal(await call(troll, 'stringy', ["yeet"]), "yeet"); + }); + + it("gets bools", async () => { + assert.equal(await call(troll, 'booly', [true]), true); + }); + + it("gets list of ints", async () => { + assert.deepEqual(await call(troll, 'listOInts', [[1,2,3]]), ["1", "2", "3"]); + }); + }); + }); +}); diff --git a/test/Errors.js b/test/Errors.js new file mode 100644 index 000000000..615fbfb99 --- /dev/null +++ b/test/Errors.js @@ -0,0 +1,50 @@ +"use strict"; + +/* + * This module loads Error and FailureInfo enum from ErrorReporter.sol. + */ + +const path = require('path'); +const solparse = require('solparse'); + +const errorReporterPath = path.join(__dirname, '..', 'contracts', 'ErrorReporter.sol'); +const contents = solparse.parseFile(errorReporterPath); +const [ + ComptrollerErrorReporter, + TokenErrorReporter +] = contents.body.filter(k => k.type === 'ContractStatement'); + +function invert(object) { + return Object.entries(object).reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {}); +} + +function parse(reporter) { + const ErrorInv = reporter.body.find(k => k.name == 'Error').members; + const FailureInfoInv = reporter.body.find(k => k.name == 'FailureInfo').members; + const Error = invert(ErrorInv); + const FailureInfo = invert(FailureInfoInv); + return {Error, FailureInfo, ErrorInv, FailureInfoInv}; +} + +const carefulMathPath = path.join(__dirname, '..', 'contracts', 'CarefulMath.sol'); +const CarefulMath = solparse.parseFile(carefulMathPath).body.find(k => k.type === 'ContractStatement'); +const MathErrorInv = CarefulMath.body.find(k => k.name == 'MathError').members; +const MathError = invert(MathErrorInv); + +const whitePaperModelPath = path.join(__dirname, '..', 'contracts', 'WhitePaperInterestRateModel.sol'); +const whitePaperModel = solparse.parseFile(whitePaperModelPath).body.find(k => k.type === 'ContractStatement'); +const IRErrorInv = whitePaperModel.body.find(k => k.name == 'IRError').members; +const IRError = invert(IRErrorInv); + +module.exports = { + ComptrollerErr: parse(ComptrollerErrorReporter), + TokenErr: parse(TokenErrorReporter), + IRErr: { + Error: IRError, + ErrorInv: IRErrorInv + }, + MathErr: { + Error: MathError, + ErrorInv: MathErrorInv + } +}; diff --git a/test/ExponentialTest.sol b/test/ExponentialTest.sol new file mode 100644 index 000000000..65680566f --- /dev/null +++ b/test/ExponentialTest.sol @@ -0,0 +1,467 @@ +pragma solidity ^0.5.8; + +import "truffle/Assert.sol"; +import "../contracts/Exponential.sol"; + +contract ExponentialTest is Exponential { + + /** + * @dev helper that lets us create an Exp with `getExp` without cluttering our test code with error checks of the setup. + */ + function getExpFromRational(uint numerator, uint denominator) internal returns (Exp memory) { + (MathError err, Exp memory result) = getExp(numerator, denominator); + + Assert.equal(0, uint(err), "getExpFromRational failed"); + return result; + } + + function testGetExp_Simple() public { + (MathError err, Exp memory val) = getExp(50, 10000); // 50 basis points + + assertNoError(err); + Assert.equal(5000000000000000, val.mantissa, "should be 50 basis points"); + } + + function testGetExp_WithDenomOfOne() public { + (MathError err, Exp memory val) = getExp(5, 1); // The number 5.0 + + assertNoError(err); + Assert.equal(5000000000000000000, val.mantissa, "should be 5.0"); + } + + function testGetZero_Zero() public { + (MathError err, Exp memory val) = getExp(0, 10000); // 0 basis points + + assertNoError(err); + Assert.equal(0, val.mantissa, "should be 0 basis points"); + } + + function testGetExp_FailToGetDivByZero() public { + (MathError err, Exp memory val) = getExp(1, 0); + + assertError(MathError.DIVISION_BY_ZERO, err, "divide by zero"); + assertZero(val.mantissa, "default value"); + } + + function testGetExp_Overflow() public { + (MathError err, Exp memory val) = getExp(uint(-1), uint(-1)); // 1, but overflows + + assertError(MathError.INTEGER_OVERFLOW, err, "overflows max int"); + assertZero(val.mantissa, "default value"); + } + + function testAddExp_Successful() public { + (MathError err0, Exp memory val1) = getExp(50, 10000); // 50 basis points + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(60, 10000); // 60 basis points + assertNoError(err1); + + (MathError err2, Exp memory sum) = addExp(val1, val2); + assertNoError(err2); + + Assert.equal(11000000000000000, sum.mantissa, "should be 110 basis points"); + } + + function testAddExp_Overflow() public { + Exp memory val1 = Exp({mantissa: uint(-1)}); + Exp memory val2 = Exp({mantissa: uint(-1)}); + + (MathError err, Exp memory sum) = addExp(val1, val2); + + assertError(MathError.INTEGER_OVERFLOW, err, "overflowed with addition"); + assertZero(sum.mantissa, "default value"); + } + + function testSubExp_Successful() public { + (MathError err0, Exp memory val1) = getExp(50, 10000); // 50 basis points + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(60, 10000); // 60 basis points + assertNoError(err1); + + (MathError err2, Exp memory difference) = subExp(val2, val1); + assertNoError(err2); + + Assert.equal(1000000000000000, difference.mantissa, "should be 10 basis points"); + + // -1 - (-1) should actually work out to 0 + (MathError err3, Exp memory difference2) = subExp(Exp({mantissa: uint(-1)}), Exp({mantissa: uint(-1)})); + assertNoError(err3); + + Assert.equal(0, difference2.mantissa, "should be 0 basis points"); + } + + function testSubExp_Underflow() public { + (MathError err0, Exp memory val1) = getExp(5, 1); + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(7, 1); + assertNoError(err1); + + (MathError err2, Exp memory difference) = subExp(val1, val2); // 5 - 7 = underflow + + assertError(MathError.INTEGER_UNDERFLOW, err2, "underflowed with subtraction"); + assertZero(difference.mantissa, "default value"); + } + + function testMulExp_Successful() public { + + (MathError err0, Exp memory val1) = getExp(50, 100); // 1/2 + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(202, 100); // 2.02 + assertNoError(err1); + + (MathError err2, Exp memory product) = mulExp(val1, val2); + + assertNoError(err2); + Assert.equal(1010000000000000000, product.mantissa, "product should be 1.01"); + } + + function testMulExp3_Successful() public { + (MathError err0, Exp memory val1) = getExp(1, 2); + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(1, 3); + assertNoError(err1); + + (MathError err2, Exp memory val3) = getExp(1, 5); + assertNoError(err2); + + (MathError err3, Exp memory product) = mulExp3(val1, val2, val3); + assertNoError(err3); + Assert.equal(33333333333333333, product.mantissa, "product should be 1/30"); + } + + function testMulExp3_Small() public { + (MathError err0, Exp memory val1) = getExp(1, 2); + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(1, 1e18); + assertNoError(err1); + + (MathError err2, Exp memory val3) = getExp(1, 1); + assertNoError(err2); + + (MathError err3, Exp memory product) = mulExp3(val1, val2, val3); + assertNoError(err3); + Assert.equal(1, product.mantissa, "product should be 5e-19, rounded to 1e-18"); + } + + // This fails without the addition of the half scale before descaling the intermediate value + function testMulExp_RoundAtFarRight() public { + + (MathError err0, Exp memory val1) = getExp(2, 3); // 2/3 + assertNoError(err0); + + (MathError err1, Exp memory val2) = getExp(1, 10**18); // 1x10e-18 + assertNoError(err1); + + (MathError err2, Exp memory product) = mulExp(val1, val2); + + assertNoError(err2); // 2/3 * 1x10e-18 = 6.6... x 10e-19 + Assert.equal(1, product.mantissa, "product should be 6.666E-19, rounded to 1e-18"); + } + + function testMulExp_ZeroLeft() public { + + (MathError err0, Exp memory left) = getExp(0, 100); // 0 + assertNoError(err0); + + (MathError err1, Exp memory right) = getExp(202, 100); // 2.02 + assertNoError(err1); + + (MathError err2, Exp memory product) = mulExp(left, right); + + assertNoError(err2); + Assert.equal(0, product.mantissa, "product should be 0"); + } + + function testMulExp_ZeroRight() public { + + (MathError err0, Exp memory right) = getExp(0, 100); // 0 + assertNoError(err0); + + (MathError err1, Exp memory left) = getExp(202, 100); // 2.02 + assertNoError(err1); + + (MathError err2, Exp memory product) = mulExp(left, right); + + assertNoError(err2); + Assert.equal(0, product.mantissa, "product should be 0"); + } + + function testMulExp_OneLeft() public { + + (MathError err0, Exp memory left) = getExp(1, 1); // 1 + assertNoError(err0); + + (MathError err1, Exp memory right) = getExp(202, 100); // 2.02 + assertNoError(err1); + + (MathError err2, Exp memory product) = mulExp(left, right); + + assertNoError(err2); + Assert.equal(2020000000000000000, product.mantissa, "product should be 2.02"); + } + + function testMulExp_OneRight() public { + + (MathError err0, Exp memory right) = getExp(1, 1); // 1 + assertNoError(err0); + + (MathError err1, Exp memory left) = getExp(202, 100); // 2.02 + assertNoError(err1); + + (MathError err2, Exp memory product) = mulExp(left, right); + + assertNoError(err2); + Assert.equal(2020000000000000000, product.mantissa, "product should be 2.02"); + } + + function testMulExp_Overflow() public { + Exp memory val1 = Exp({mantissa: uint(-1)}); + Exp memory val2 = Exp({mantissa: uint(-1)}); + + (MathError err, Exp memory product) = mulExp(val1, val2); + + assertError(MathError.INTEGER_OVERFLOW, err, "overflowed with multiplication"); + assertZero(product.mantissa, "default value"); + } + + function testMulExp_OverflowOnAddHalfScale() public { + Exp memory bigger = Exp({mantissa: (2**256) - 1}); + Exp memory smaller = Exp({mantissa: 1}); + + MathError err; + Exp memory product; + + (err, product) = mulExp(bigger, smaller); + assertError(MathError.INTEGER_OVERFLOW, err, "should have returned MathError.INTEGER_OVERFLOW"); + + Assert.equal(0, product.mantissa, "product should be zero"); + } + + function testMulScalar_Big() public { + Exp memory val = getExpFromRational(10**58, 1); // Exp({mantissa: 10**76}); // our scaled representation of 10e59 + + Assert.equal(10**76, val.mantissa, "setup failed val.mantissa not 10e76"); + + (MathError err0, Exp memory scaled1) = mulScalar(val, 5); + assertNoError(err0); + Assert.equal(uint(5 * 10**76), scaled1.mantissa, "scalar multiplication failed- scaled1.mantissa not 50e76"); + + (MathError err1, Exp memory scaled2) = mulScalar(val, 100); + assertError(MathError.INTEGER_OVERFLOW, err1, "should have overflowed with scalar multiplication"); + Assert.equal(0, scaled2.mantissa, "should have overflowed"); + } + + function testMulScalar_Small() public { + Exp memory val = getExpFromRational(1, 10**16); // our scaled representation of 10e-16. + + Assert.equal(100, val.mantissa, "setup failed val2.mantissa not 100"); + + (MathError err0, Exp memory scaled) = mulScalar(val, 5); + assertNoError(err0); + Assert.equal(500, scaled.mantissa, "scalar multiplication failed- scaled2.mantissa not 500"); + } + + function testDivScalar_Big() public { + Exp memory val = getExpFromRational(10**58, 1); // Exp({mantissa: 10**76}); // our scaled representation of 10e59 + + Assert.equal(10**76, val.mantissa, "setup failed val.mantissa not 10e76"); + + (MathError err0, Exp memory scaled1) = divScalar(val, 5); + assertNoError(err0); + Assert.equal(uint(2 * 10**75), scaled1.mantissa, "scalar division failed- scaled1.mantissa not 2e76"); + + (MathError err1, Exp memory scaled2) = divScalar(val, 0); + assertError(MathError.DIVISION_BY_ZERO, err1, "should have caused division by zero"); + Assert.equal(0, scaled2.mantissa, "should be nilish"); + } + + function testDivScalar_Small() public { + Exp memory val = getExpFromRational(1, 10**16); // our scaled representation of 10e-16. + + Assert.equal(100, val.mantissa, "setup failed val.mantissa not 100"); + + (MathError err0, Exp memory scaled) = divScalar(val, 5); + assertNoError(err0); + Assert.equal(20, scaled.mantissa, "scalar division failed- scaled.mantissa not 20"); + } + + function testTruncate() public { + Assert.equal(10**58, truncate(getExpFromRational(10**58, 1)), "should truncate to 10**58"); + Assert.equal(0, truncate(getExpFromRational(1, 2)), "should truncate to 0"); + Assert.equal(0, truncate(getExpFromRational(2, 3)), "should truncate to 0"); + Assert.equal(1, truncate(getExpFromRational(3, 2)), "should truncate to 1"); + Assert.equal(8, truncate(getExpFromRational(4000, 500)), "should truncate to 8"); + Assert.equal(10**5, truncate(getExpFromRational(10**20, 10**15)), "should truncate to 2000"); + } + + function testIsZeroExp() public { + + Assert.equal(true, isZeroExp(getExpFromRational(0, 1)), "zero should be zero"); + Assert.equal(true, isZeroExp(getExpFromRational(0, 10**58)), "zero from a large denominator should be zero"); + + Assert.equal(false, isZeroExp(getExpFromRational(10**58, 3)), "large rational should not be zero"); + Assert.equal(false, isZeroExp(getExpFromRational(10**58, 1)), "large integer should not be zero"); + Assert.equal(false, isZeroExp(getExpFromRational(1, 1)), "small integer should not be zero"); + + Exp memory tinyFraction = getExpFromRational(1, 10**18); + Assert.equal(1, tinyFraction.mantissa, "tinyFraction setup failed"); + + Assert.equal(false, isZeroExp(tinyFraction), "tiny fraction should not be zero"); + } + + // divExp just calls getExp, which is already tested, so here we just verify that it is passing the + // correct arguments to getExp and check identities and error case + function testDivExp() public { + MathError err; + Exp memory result; + + //////////////////// + // Simple division + Exp memory left = getExpFromRational(1, 1); + Exp memory right = getExpFromRational(3, 1); + (err, result)= divExp(left, right); + assertNoError(err); + + Assert.equal(result.mantissa, 333333333333333333, "Exp division failed- result.mantissa not 333333333333333333"); + + //////////////////// + // Divide by 1 + left = getExpFromRational(3, 1); + right = getExpFromRational(1, 1); + (err, result)= divExp(left, right); + assertNoError(err); + + Assert.equal(result.mantissa, left.mantissa, "Exp division by 1 failed- result.mantissa not left.mantissa"); + + //////////////////// + // Divide very small number by itself + left = getExpFromRational(1, 10**16); // our scaled representation of 10e-16. + + (err, result) = divExp(left, left); + assertNoError(err); + + Assert.equal(result.mantissa, 1000000000000000000, "Exp division failed- result.mantissa not 1000000000000000000"); + + //////////////////// + // Divide by 0 returns error + left = getExpFromRational(1, 1000); // .001 + right = getExpFromRational(0, 1); // 0 + + (err, result) = divExp(left, right); + Assert.equal(uint(err), uint(MathError.DIVISION_BY_ZERO), "Exp division by 0 should have returned MathError.DIVISION_BY_ZERO"); + Assert.equal(result.mantissa, 0, "Exp division by 0 mantissa should be 0"); + } + + + function testDivScalarByExp() public { + MathError err; + Exp memory result; + + //////////////////// + // divide by 1 + (err, result) = divScalarByExp(300, getExpFromRational(1, 1)); + assertNoError(err); + + Assert.equal(result.mantissa, 300 * 10**18, "Exp division failed- result.mantissa not 300 * 10**18"); + + //////////////////// + // divide 0 by non-zero + (err, result) = divScalarByExp(0, getExpFromRational(108, 1000)); + assertNoError(err); + + Assert.equal(result.mantissa, 0, "Exp division failed- result.mantissa not 0"); + + //////////////////// + // simple division by rational > 1: 300 / 1.6 = 187.5 + (err, result) = divScalarByExp(300, getExpFromRational(16, 10)); + assertNoError(err); + + Assert.equal(result.mantissa, 187500000000000000000, "Exp division failed- result.mantissa not 187500000000000000000"); + + //////////////////// + // simple division by rational < 1: 300 / .85 = 352.9411764705882352941176470588235294117647058823529411764... + // scaled as 352941176470588235294 + (err, result) = divScalarByExp(300, getExpFromRational(85, 100)); + assertNoError(err); + + Assert.equal(result.mantissa, 352941176470588235294, "Exp division failed- result.mantissa not 352941176470588235294"); + + //////////////////// + // divide large uint by rational 123456789012 / 1.6 = 77160493132.5; scaled as 77160493132500000000000000000 + (err, result) = divScalarByExp(123456789012, getExpFromRational(16, 10)); + assertNoError(err); + + Assert.equal(result.mantissa, 77160493132500000000000000000, "Exp division failed- result.mantissa not 77160493132500000000000000000"); + + //////////////////// + // divide large uint by large rational + // 123456789012 / 987654321012345.7 = 0.000124999998871524997371961899045794758369664776317619765..., + // scaled as 124999998871525 + (err, result) = divScalarByExp(123456789012, getExpFromRational(9876543210123456, 10)); + assertNoError(err); + + Assert.equal(result.mantissa, 124999998871525, "Exp division failed- result.mantissa not 124999998871525"); + + //////////////////// + // overflow with large scalar > max Exp 2^237 - 1 + (err, result) = divScalarByExp(2**237, getExpFromRational(10, 1)); + + Assert.equal(uint(err), uint(MathError.INTEGER_OVERFLOW), "scalar >= 2**237 should cause overflow when converted to Exp"); + + //////////////////// + // division by zero + (err, result) = divScalarByExp(10, getExpFromRational(0, 1)); + + Assert.equal(uint(err), uint(MathError.DIVISION_BY_ZERO), "division by zero should return error DIVISION_BY_ZERO"); + } + + + function testLessThanOrEqualExp() public { + + // identity + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(1, 1), getExpFromRational(1, 1)), "1/1 <= itself"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(1, 3), getExpFromRational(1, 3)), "1/3 <= itself"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(3, 1), getExpFromRational(3, 1)), "3/1 <= itself"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(0, 1), getExpFromRational(0, 3)), "0 <= itself even with different demoninators"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(11 * 10**17, 3), getExpFromRational(110 * 10**16, 3)), "(11 * 10**17)/3 <= itself"); + + // strictly less than + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(7, 9), getExpFromRational(1, 1)), "7/9 <= 1"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(1, 4), getExpFromRational(1, 3)), "1/4 <= 1/3"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(3, 2), getExpFromRational(3, 1)), "3/2 <= 3 "); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(100, 3), getExpFromRational(100, 2)), "100/3 <= 100/2"); + Assert.isTrue(lessThanOrEqualExp(getExpFromRational(10**18, 3), getExpFromRational(10**19, 3)), "10e18/3 <= 10e19/3"); + + // Reverse the previous block of strictly less than tests + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(1, 1), getExpFromRational(7, 9)), "1 !<= 7/9 "); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(1, 3), getExpFromRational(1, 4)), "1/3 !<= 1/4"); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(3, 1), getExpFromRational(3, 2)), "3 !<= 3/2"); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(100, 2), getExpFromRational(100, 3)), "100/2 !<= 100/3"); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(10**19, 3), getExpFromRational(10**18, 3)), "10e19/3 !<= 10e18/3"); + + // Let's do some more failure cases + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(3, 1), getExpFromRational(1, 3)), "3/1 and 1/3"); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(3, 1), getExpFromRational(1, 1)), "3/1 and 1/1"); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(3, 1), getExpFromRational(0, 1)), "3/1 and 0/1"); + Assert.isFalse(lessThanOrEqualExp(getExpFromRational(30, 1), getExpFromRational(3, 1)), "30/1 and 3/1"); + } + + function assertError(MathError expected, MathError given, string memory message) internal { + Assert.equal(uint(expected), uint(given), message); + } + + function assertNoError(MathError err) internal { + assertError(MathError.NO_ERROR, err, "should have error NO_ERROR"); + } + + function assertZero(uint value, string memory message) internal { + Assert.equal(0, value, message); + } + +} \ No newline at end of file diff --git a/test/MaximillionTest.js b/test/MaximillionTest.js new file mode 100644 index 000000000..b9e8cac09 --- /dev/null +++ b/test/MaximillionTest.js @@ -0,0 +1,66 @@ +const { + etherBalance, + etherGasCost, + getContract, + call, + send +} = require('./Utils/MochaTruffle'); + +const { + makeComptroller, + makeCToken, + makePriceOracle, + pretendBorrow, + borrowSnapshot +} = require('./Utils/Compound'); + +const Maximillion = getContract('Maximillion'); + +contract('Maximillion', function([root, borrower]) { + let maximillion, cEther; + before(async () =>{ + cEther = await makeCToken({kind: "cether", supportMarket: true}); + maximillion = await Maximillion.deploy({arguments: [cEther._address]}).send({from: root}); + }); + + describe("constructor", async () => { + it("sets address of cEther", async () => { + assert.equal(await call(maximillion, "cEther"), cEther._address); + }); + }); + + describe("repayBehalf", async () => { + it("refunds the entire amount with no borrows", async () => { + const beforeBalance = await etherBalance(root); + const result = await send(maximillion, "repayBehalf", [borrower], {value: 100}); + const gasCost = await etherGasCost(result); + const afterBalance = await etherBalance(root); + assert.success(result); + assert.numEqual(afterBalance, beforeBalance.sub(gasCost)); + }); + + it("repays part of a borrow", async () => { + await pretendBorrow(cEther, borrower, 1, 1, 150); + const beforeBalance = await etherBalance(root); + const result = await send(maximillion, "repayBehalf", [borrower], {value: 100}); + const gasCost = await etherGasCost(result); + const afterBalance = await etherBalance(root); + const afterBorrowSnap = await borrowSnapshot(cEther, borrower); + assert.success(result); + assert.numEqual(afterBalance, beforeBalance.sub(gasCost).sub(100)); + assert.numEqual(afterBorrowSnap.principal, 50); + }); + + it("repays a full borrow and refunds the rest", async () => { + await pretendBorrow(cEther, borrower, 1, 1, 90); + const beforeBalance = await etherBalance(root); + const result = await send(maximillion, "repayBehalf", [borrower], {value: 100}); + const gasCost = await etherGasCost(result); + const afterBalance = await etherBalance(root); + const afterBorrowSnap = await borrowSnapshot(cEther, borrower); + assert.success(result); + assert.numEqual(afterBalance, beforeBalance.sub(gasCost).sub(90)); + assert.numEqual(afterBorrowSnap.principal, 0); + }); + }); +}); diff --git a/test/Models/interestRateModelTest.js b/test/Models/interestRateModelTest.js new file mode 100644 index 000000000..58a701bf6 --- /dev/null +++ b/test/Models/interestRateModelTest.js @@ -0,0 +1,150 @@ +const {call} = require('../Utils/MochaTruffle'); +const { + makeInterestRateModel, + getBorrowRate +} = require('../Utils/Compound'); + + +function utilizationRate(cash, borrows, reserves) { + return borrows ? borrows / (cash + borrows) : 0; +} + +function whitePaperRateFn(base, slope) { + return (cash, borrows, reserves) => { + const ua = utilizationRate(cash, borrows, reserves); + return (ua * slope + base) / blocksPerYear; + } +} + +const ExpectedRates = { + 'baseP025-slopeP20': {base: 0.025, slope: 0.20}, + 'baseP05-slopeP45': {base: 0.05, slope: 0.45}, + 'white-paper': {base: 0.1, slope: 0.45} +} + +const blocksPerYear = 2102400; +const rateInputs = [ + [500, 100], + [3e18, 5e18], + [5e18, 3e18], + [500, 3e18], + [0, 500], + [500, 0], + [0, 0], + [3e18, 500], + ["1000.00000000e18", "310.00000000e18"], + ["690.00000000e18", "310.00000000e18"] +].map(vs => vs.map(Number)); + +contract('InterestRateModel', async function ([root, ...accounts]) { + Object.entries(ExpectedRates).forEach(async ([kind, info]) => { + let model; + before(async () => { + model = await makeInterestRateModel({kind: 'white-paper', baseRate: info.base, multiplier: info.slope}); + }); + + const rateCases = (rateFn) => { + rateInputs.forEach(([cash, borrows, reserves = 0]) => { + it(`calculates correct borrow value for ${cash}, ${borrows}, ${reserves}`, async () => { + const expected = rateFn(cash, borrows, reserves); + assert.hasIRErrorTuple( + await getBorrowRate(model, cash, borrows, reserves), + ['NO_ERROR', (x) => assert.approximately(Number(x) / 1e18, expected, 1e7)] + ); + }); + }); + }; + + describe(kind, async () => { + it('isInterestRateModel', async () => { + assert.equal(await call(model, 'isInterestRateModel'), true); + }); + + rateCases(whitePaperRateFn(info.base, info.slope)); + + if (kind == 'white-paper') { + // Only need to do these for the WhitePaper + + it('handles overflowed cash + borrows', async () => { + assert.hasIRErrorTuple( + await getBorrowRate(model, -1, -1, 0), + ['FAILED_TO_ADD_CASH_PLUS_BORROWS', 0] + ); + }); + + it('handles failing to get exp of borrows / cash + borrows', async() => { + assert.hasIRErrorTuple( + await getBorrowRate(model, 0, -1, 0), + ['FAILED_TO_GET_EXP', 0] + ); + }); + + it('handles overflow utilization rate times slope', async() => { + const badModel = await makeInterestRateModel({kind, baseRate: 0, multiplier: -1}); + assert.hasIRErrorTuple( + await getBorrowRate(badModel, 1, 1, 0), + ['FAILED_TO_MUL_UTILIZATION_RATE', 0] + ); + }); + + it('handles overflow utilization rate times slope', async() => { + const badModel = await makeInterestRateModel({kind, baseRate: -1, multiplier: 1}); + assert.hasIRErrorTuple( + await getBorrowRate(badModel, 1, 1, 0), + ['FAILED_TO_ADD_BASE_RATE', 0] + ); + }); + + describe('getBorrowRate', async () => { + // We'll generate a large number of tests to verify approximate accuracy + [ + // Description of tests arrays: + // [base, slope, cash, borrows] + + // 50% base and 45% slope + [0.5e18, 0.45e18, 500, 100], + [0.5e18, 0.45e18, 3e18, 5e18], + [0.5e18, 0.45e18, 5e18, 3e18], + [0.5e18, 0.45e18, 500, 3e18], + [0.5e18, 0.45e18, 0, 500], + [0.5e18, 0.45e18, 500, 0], + [0.5e18, 0.45e18, 0, 0], + [0.5e18, 0.45e18, 3e18, 500], + [0.5e18, 0.45e18, "1000.00000000e18", "310.00000000e18"], + [0.5e18, 0.45e18, "690.00000000e18", "310.00000000e18"], + + // 10% base and 200% slope + [0.1e18, 2.0e18, 500, 100], + [0.1e18, 2.0e18, 3e18, 5e18], + [0.1e18, 2.0e18, 5e18, 3e18], + [0.1e18, 2.0e18, 500, 3e18], + [0.1e18, 2.0e18, 0, 500], + [0.1e18, 2.0e18, 500, 0], + [0.1e18, 2.0e18, 0, 0], + [0.1e18, 2.0e18, 3e18, 500], + + // 2000% base and 4000% slope + [20.0e18, 40.0e18, 500, 100], + [20.0e18, 40.0e18, 3e18, 5e18], + [20.0e18, 40.0e18, 5e18, 3e18], + [20.0e18, 40.0e18, 500, 3e18], + [20.0e18, 40.0e18, 0, 500], + [20.0e18, 40.0e18, 500, 0], + [20.0e18, 40.0e18, 0, 0], + [20.0e18, 40.0e18, 3e18, 500], + ].map(vs => vs.map(Number)) + .forEach(([base, slope, cash, borrows, reserves = 0]) => { // XXX add reserves + it(`calculates correct borrow value for base=${base/1e16}%,slope=${slope/1e16}%, cash=${cash}, borrows=${borrows}`, async () => { + const altModel = await makeInterestRateModel({kind: 'white-paper', baseRate: base / 1e18, multiplier: slope / 1e18}); + const expected = whitePaperRateFn(base / 1e18, slope / 1e18)(cash, borrows, reserves); + assert.hasIRErrorTuple( + await getBorrowRate(altModel, cash, borrows, reserves), + ['NO_ERROR', (x) => assert.approximately(Number(x) / 1e18, expected, 1e-8)] + ); + }); + }); + }); + } + }); + }) +}); \ No newline at end of file diff --git a/test/PriceOracleProxyTest.js b/test/PriceOracleProxyTest.js new file mode 100644 index 000000000..80efc806d --- /dev/null +++ b/test/PriceOracleProxyTest.js @@ -0,0 +1,129 @@ +const BigNumber = require('bignumber.js'); + +const { + address, + etherMantissa, + getContract, + call, + send +} = require('./Utils/MochaTruffle'); + +const { + makeComptroller, + makeCToken, + makePriceOracle, +} = require('./Utils/Compound'); + +const OraclePriceOracleProxy = getContract('PriceOracleProxy'); + +contract('PriceOracleProxy', function([root, ...accounts]) { + let oracle, comptroller, backingOracle, cEther, cErc20, cUsdc, fakeUSDC; + + before(async () =>{ + cEther = await makeCToken({kind: "cether", + comptrollerOpts: { kind: "v1-no-proxy"}, + supportMarket: true}); + + cUsdc = await makeCToken({comptroller: cEther.comptroller, + supportMarket: true}); + + backingOracle = await makePriceOracle(); + oracle = await OraclePriceOracleProxy + .deploy({ + arguments: [ + cEther.comptroller._address, + backingOracle._address, + cEther._address, + cUsdc._address + ]}) + .send({from: root}); + }); + + describe("constructor", async () => { + it("sets address of comptroller", async () => { + let configuredComptroller = await call(oracle, "comptroller"); + assert.equal(configuredComptroller, cEther.comptroller._address); + }); + + it("sets address of v1 oracle", async () => { + let configuredOracle = await call(oracle, "v1PriceOracle"); + assert.equal(configuredOracle, backingOracle._address); + }); + + it("sets address of cEther", async () => { + let configuredCEther = await call(oracle, "cEtherAddress"); + assert.equal(configuredCEther, cEther._address); + }); + + it("sets address of cUSDC", async () => { + let configuredCUSD = await call(oracle, "cUsdcAddress"); + assert.equal(configuredCUSD, cUsdc._address); + }); + }); + + describe("getUnderlyingPrice", async () => { + let setAndVerifyBackingPrice = async (cToken, price) => { + await send( + backingOracle, + "setUnderlyingPrice", + [cToken._address, etherMantissa(price)]); + + let backingOraclePrice = await call( + backingOracle, + "assetPrices", + [cToken.underlying._address]); + + assert.equal(Number(backingOraclePrice), price * 1e18); + }; + + let readAndVerifyProxyPrice = async (token, price) =>{ + let proxyPrice = await call(oracle, "getUnderlyingPrice", [token._address]); + assert.equal(Number(proxyPrice), price * 1e18);; + }; + + it("always returns 1e18 for cEther", async () => { + await readAndVerifyProxyPrice(cEther, 1); + }); + + it("checks address(1) for cusdc", async () => { + await send( + backingOracle, + "setDirectPrice", + [address(1), etherMantissa(50)]); + + await readAndVerifyProxyPrice(cUsdc, 50); + }); + + it("proxies to v1 oracle for listed cErc20's", async () => { + let listedToken = await makeCToken({comptroller: cEther.comptroller, supportMarket: true}); + + await setAndVerifyBackingPrice(listedToken, 12); + await readAndVerifyProxyPrice(listedToken, 12); + + await setAndVerifyBackingPrice(listedToken, 37); + await readAndVerifyProxyPrice(listedToken, 37); + }); + + describe("returns 0 for unlisted tokens", async () => { + it("right comptroller, not supported", async () => { + let unlistedToken = await makeCToken({comptroller: comptroller, + supportMarket: false}); + + await setAndVerifyBackingPrice(unlistedToken, 12); + await readAndVerifyProxyPrice(unlistedToken, 0); + }); + + it("wrong comptroller", async () => { + let wrongNetworkToken = await makeCToken({supportMarket: true}); + await setAndVerifyBackingPrice(wrongNetworkToken, 10); + + await readAndVerifyProxyPrice(wrongNetworkToken, 0); + }); + + it("not even a cToken", async () => { + let proxyPrice = await call(oracle, "getUnderlyingPrice", [root]); + assert.equal(Number(proxyPrice), 0); + }); + }); + }); +}); diff --git a/test/ScenarioTest.js b/test/ScenarioTest.js new file mode 100644 index 000000000..36e451350 --- /dev/null +++ b/test/ScenarioTest.js @@ -0,0 +1,121 @@ +"use strict"; + +const {initWorld, loadVerbose, loadInvokationOpts} = require('../scenario/.tsbuilt/World.js'); +const {processEvents} = require('../scenario/.tsbuilt/CoreEvent.js'); +const {parse} = require('../scenario/.tsbuilt/Parser.js'); +const {ConsolePrinter} = require('../scenario/.tsbuilt/Printer.js'); + +const fs = require('fs'); +const path = require('path'); + +const basePath = process.env.proj_root || path.join(process.cwd(), '..'); +const baseScenarioPath = path.join(basePath, 'spec', 'scenario'); +const coreMacros = fs.readFileSync(path.join(baseScenarioPath, 'CoreMacros')); + +const scenarios = {}; + +function loadScenarios(dir) { + fs.readdirSync(dir).forEach(file => { + const fullPath = `${dir}/${file}`; + + const stat = fs.statSync(fullPath); + + // Check if directory, and if so, recurse + if (stat && stat.isDirectory()) { + loadScenarios(fullPath); + } else { + // Ignore files if they don't match `.scen` + if (file.match(/\.scen$/)) { + // Load file data + const data = fs.readFileSync(fullPath, 'utf8'); + + // Get the name of the test from its file name + const name = file.replace(/\..*$/g, 'Scen'); + + try { + // Try and parse the file + const scen = parse(coreMacros + data); + + // Add each scenario, prefixed by test name + Object.entries(scen).forEach(([key, val]) => { + scenarios[`${name}: ${key}`] = val; + }); + } catch (e) { + throw `Cannot parse scenario ${file}: ${e}` + } + } + } + }); +} + +loadScenarios(baseScenarioPath); + +/** + * Allows user to specify a scenario filter + */ +let scenarioFilter; + +const scenarioEnv = process.env['scenarios'] || process.env['SCENARIOS']; +const verbose = !!process.env['verbose']; +const network = process.env['NETWORK'] || process.env['network'] || 'test'; + +if (scenarioEnv) { + console.log(`running scenarios matching: /${scenarioEnv}/i`); + scenarioFilter = new RegExp(scenarioEnv, 'i'); +} + +contract('ScenarioTest', function(accounts) { + /* + * This test runs our scenarios, which come from the reference implementation. + */ + + Object.entries(scenarios).forEach(([name, events]) => { + if (!scenarioFilter || name.match(scenarioFilter)) { + let fn = it; + let runner; + + switch (events[0]) { + case "Pending": + events = []; + break; + case "Gas": + // Skip gas tests on coverage + if (network === 'coverage') { + fn = it.skip; + } + events.shift(); + break; + case "Only": + fn = it.only; + events.shift(); + break; + case "Skip": + fn = it.skip; + events.shift(); + break; + } + + if (events.length === 0) { + runner = undefined; + } else { + runner = async () => { + let world = await initWorld(assert, new ConsolePrinter(verbose), web3, artifacts, network, accounts, basePath); + world = loadVerbose(world); + world = loadInvokationOpts(world); + + let finalWorld; + + // console.log(["Scenario", name, "Events", events, world]); + + finalWorld = await processEvents(world, events); + + // console.log(["Final world", finalWorld, finalWorld.actions]); + } + } + + fn("scenario: " + name, runner); + } else { + it.skip("scenario: " + name, async () => {}); + } + }); +}); diff --git a/test/SpinaramaTest.js b/test/SpinaramaTest.js new file mode 100644 index 000000000..119827ec1 --- /dev/null +++ b/test/SpinaramaTest.js @@ -0,0 +1,315 @@ +const { + etherMantissa, + minerStart, + minerStop, + send, + call +} = require('./Utils/MochaTruffle'); + +const { + makeCToken, + balanceOf, + borrowSnapshot, + enterMarkets +} = require('./Utils/Compound'); + +contract('Spinarama', function([root, from, ...accounts]) { + describe('#mintMint', async () => { + it('should succeed', async () => { + const cToken = await makeCToken({supportMarket: true}); + await send(cToken.underlying, 'harnessSetBalance', [from, 100], {from}); + await send(cToken.underlying, 'approve', [cToken._address, -1], {from}); + await minerStop(); + const p1 = send(cToken, 'mint', [1], {from}); + const p2 = send(cToken, 'mint', [2], {from}); + await minerStart(); + assert.success(await p1); + assert.success(await p2); + assert.numEqual(await balanceOf(cToken, from), 3); + }); + + it('should partial succeed', async () => { + const cToken = await makeCToken({supportMarket: true}); + await send(cToken.underlying, 'harnessSetBalance', [from, 100], {from}); + await send(cToken.underlying, 'approve', [cToken._address, 10], {from}); + await minerStop(); + const p1 = send(cToken, 'mint', [11], {from}); + const p2 = send(cToken, 'mint', [10], {from}); + await minerStart(); + assert.hasTokenFailure(await p1, 'TOKEN_INSUFFICIENT_ALLOWANCE', 'MINT_TRANSFER_IN_NOT_POSSIBLE'); + assert.success(await p2); + assert.numEqual(await balanceOf(cToken, from), 10); + }); + }); + + describe('#mintRedeem', async () => { + it('should succeed', async () => { + const cToken = await makeCToken({supportMarket: true}); + await send(cToken.underlying, 'harnessSetBalance', [from, 100], {from}); + await send(cToken.underlying, 'approve', [cToken._address, 10], {from}); + await minerStop(); + const p1 = send(cToken, 'mint', [10], {from}); + const p2 = send(cToken, 'redeemUnderlying', [10], {from}); + await minerStart(); + assert.success(await p1); + assert.success(await p2); + assert.numEqual(await balanceOf(cToken, from), 0); + }); + }); + + describe('#redeemMint', async () => { + it('should succeed', async () => { + const cToken = await makeCToken({supportMarket: true}); + await send(cToken, 'harnessSetTotalSupply', [10]); + await send(cToken, 'harnessSetExchangeRate', [etherMantissa(1)]); + await send(cToken, 'harnessSetBalance', [from, 10]); + await send(cToken.underlying, 'harnessSetBalance', [cToken._address, 10]); + await send(cToken.underlying, 'approve', [cToken._address, 10], {from}); + await minerStop(); + const p1 = send(cToken, 'redeem', [10], {from}); + const p2 = send(cToken, 'mint', [10], {from}); + await minerStart(); + assert.success(await p1); + assert.success(await p2); + assert.numEqual(await balanceOf(cToken, from), 10); + }); + }); + + describe('#repayRepay', async () => { + it('should succeed', async () => { + const cToken1 = await makeCToken({supportMarket: true, underlyingPrice: 1, collateralFactor: .5}); + const cToken2 = await makeCToken({supportMarket: true, underlyingPrice: 1, comptroller: cToken1.comptroller}); + await send(cToken1.underlying, 'harnessSetBalance', [from, 10]); + await send(cToken1.underlying, 'approve', [cToken1._address, 10], {from}); + await send(cToken2.underlying, 'harnessSetBalance', [cToken2._address, 10]); + await send(cToken2, 'harnessSetTotalSupply', [100]); + await send(cToken2.underlying, 'approve', [cToken2._address, 10], {from}); + await send(cToken2, 'harnessSetExchangeRate', [etherMantissa(1)]); + assert.success(await enterMarkets([cToken1, cToken2], from)); + assert.success(await send(cToken1, 'mint', [10], {from})); + assert.success(await send(cToken2, 'borrow', [2], {from})); + await minerStop(); + const p1 = send(cToken2, 'repayBorrow', [1], {from}); + const p2 = send(cToken2, 'repayBorrow', [1], {from}); + await minerStart(); + assert.success(await p1); + assert.success(await p2); + assert.numEqual((await borrowSnapshot(cToken2, from)).principal, 0); + }); + + // XXX not yet converted below this point...moving on to certora + + it.skip('can have partial failure succeed', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + // Now borrow 5 bat + assert.success( + await spinarama.methods.borrow(BAT._address, 5).send({from: accounts[0]})); + + // And repay it, repay it + const {'0': err0, '1': err1} = await spinarama.methods.repayRepay(BAT._address, 100, 1).call({from: accounts[0]}); + + assert.hasErrorCode(err0, ErrorEnum.INTEGER_UNDERFLOW); + assert.hasErrorCode(err1, ErrorEnum.NO_ERROR); + }); + }); + + describe('#borrowRepayBorrow', async () => { + it.skip('should fail', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + // Borrow then repayBorrow should revert + await assert.revert(spinarama.methods.borrowRepayBorrow(BAT._address, 5, 1).call({from: accounts[0]})); + }); + + it.skip('can succeed with partial failure', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + // Borrow a little, repay a lot + const {'0': err0, '1': err1} = await spinarama.methods.borrowRepayBorrow(BAT._address, 1, 1000).call({from: accounts[0]}); + + assert.hasErrorCode(err0, ErrorEnum.NO_ERROR); + assert.hasErrorCode(err1, ErrorEnum.INTEGER_UNDERFLOW); + }); + }); + + describe('#borrowSupply', async () => { + it.skip('should fail in same asset', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + // Borrow then supply should revert + await assert.revert(spinarama.methods.borrowSupply(BAT._address, BAT._address, 5, 1).call({from: accounts[0]})); + }); + + it.skip('should fail, even in different assets', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + // Borrow then supply in different assets + await assert.revert(spinarama.methods.borrowSupply(BAT._address, OMG._address, 5, 1).call({from: accounts[0]})); + }); + }); + + describe('#supplyLiquidate', async () => { + it.skip('should fail', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + await assert.revert(spinarama.methods.supplyLiquidate(OMG._address, 5, accounts[0], OMG._address, BAT._address, 0).call({from: accounts[0]})); + }); + }); + + describe('#withdrawLiquidate', async () => { + it.skip('should fail', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + await assert.revert(spinarama.methods.withdrawLiquidate(OMG._address, 5, accounts[0], OMG._address, BAT._address, 0).call({from: accounts[0]})); + }); + }); + + describe('#borrowLiquidate', async () => { + it.skip('should fail', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root); + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + await assert.revert(spinarama.methods.borrowLiquidate(OMG._address, 5, accounts[0], OMG._address, BAT._address, 0).call({from: accounts[0]})); + }); + }); + + describe('#repayBorrowLiquidate', async () => { + it.skip('should fail', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root) + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + // Borrow some OMG + assert.success( + await spinarama.methods.borrow(OMG._address, 5).send({from: accounts[0]})); + + await assert.revert(spinarama.methods.repayBorrowLiquidate(OMG._address, 1, accounts[0], OMG._address, BAT._address, 0).call({from: accounts[0]})); + }); + }); + + describe('#liquidateLiquidate', async () => { + it.skip('should fail', async () => { + const {moneyMarketHarness, + priceOracle, + interestRateModel} = await setupMoneyMarket(root) + const spinarama = await Spinarama.new(moneyMarketHarness._address).send({from: root}); + const OMG = await setupSupply(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + const BAT = await setupBorrow(root, accounts[0], spinarama, moneyMarketHarness, priceOracle, interestRateModel); + + // Add cash to the protocol + await addCash(moneyMarketHarness, BAT, root); + + // Supply some collateral + assert.success( + await spinarama.methods.supply(OMG._address, 15).send({from: accounts[0]})); + + await assert.revert(spinarama.methods.liquidateLiquidate(OMG._address, 1, accounts[0], OMG._address, BAT._address, 0).call({from: accounts[0]})); + }); + }); +}); diff --git a/test/Tokens/accrueInterestTest.js b/test/Tokens/accrueInterestTest.js new file mode 100644 index 000000000..cba5624b0 --- /dev/null +++ b/test/Tokens/accrueInterestTest.js @@ -0,0 +1,139 @@ +const {etherUnsigned, call, send} = require('../Utils/MochaTruffle'); +const { + makeCToken, + setBorrowRate +} = require('../Utils/Compound'); + +const blockNumber = 2e7; +const borrowIndex = 1e18; +const borrowRate = .0001; + +async function pretendBlock(cToken, accrualBlock = blockNumber, deltaBlocks = 1) { + await send(cToken, 'harnessSetAccrualBlockNumber', [etherUnsigned(blockNumber)]); + await send(cToken, 'harnessSetBlockNumber', [etherUnsigned(blockNumber + deltaBlocks)]); + await send(cToken, 'harnessSetBorrowIndex', [etherUnsigned(borrowIndex)]); +} + +async function preAccrue(cToken) { + await pretendBlock(cToken, blockNumber, 0); + await setBorrowRate(cToken, borrowRate); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken, 'harnessExchangeRateDetails', [0, 0, 0]); +} + +contract('CToken', function ([root, ...accounts]) { + let cToken; + before(async () => { + cToken = await makeCToken({comptrollerOpts: {kind: 'bool'}}); + }); + + beforeEach(async () => { + await preAccrue(cToken); + }); + + describe('accrueInterest', async () => { + it('reverts if the interest rate is absurdly high', async () => { + await setBorrowRate(cToken, .001); + await assert.revert(send(cToken, 'accrueInterest'), "revert borrow rate is absurdly high"); + }); + + it('fails if new borrow rate calculation fails', async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'INTEREST_RATE_MODEL_ERROR', + 'ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED' + ); + }); + + it('fails if simple interest factor calculation fails', async () => { + await pretendBlock(cToken, blockNumber, 5e70); + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED' + ); + }); + + it('fails if new borrow index calculation fails', async () => { + await pretendBlock(cToken, blockNumber, 5e60); + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED' + ); + }); + + it('fails if new borrow interest index calculation fails', async () => { + await pretendBlock(cToken) + await send(cToken, 'harnessSetBorrowIndex', [-1]); + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED' + ); + }); + + it('fails if interest accumulated calculation fails', async () => { + await send(cToken, 'harnessExchangeRateDetails', [0, -1, 0]); + await pretendBlock(cToken) + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED' + ); + }); + + it('fails if new total borrows calculation fails', async () => { + await setBorrowRate(cToken, 1e-18); + await pretendBlock(cToken) + await send(cToken, 'harnessExchangeRateDetails', [0, -1, 0]); + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED' + ); + }); + + it('fails if interest accumulated for reserves calculation fails', async () => { + await setBorrowRate(cToken, .0001); + await send(cToken, 'harnessExchangeRateDetails', [0, etherUnsigned(1e30), -1]); + await send(cToken, 'harnessSetReserveFactorFresh', [etherUnsigned(1e10)]); + await pretendBlock(cToken, blockNumber, 5e20) + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED' + ); + }); + + it('fails if new total reserves calculation fails', async () => { + await setBorrowRate(cToken, 1e-18); + await send(cToken, 'harnessExchangeRateDetails', [0, etherUnsigned(1e56), -1]); + await send(cToken, 'harnessSetReserveFactorFresh', [etherUnsigned(1e17)]); + await pretendBlock(cToken) + assert.hasTokenFailure( + await send(cToken, 'accrueInterest'), + 'MATH_ERROR', + 'ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED' + ); + }); + + it('succeeds and saves updated values in storage on success', async () => { + await send(cToken, 'harnessExchangeRateDetails', [0, etherUnsigned(1e22), etherUnsigned(1e20)]); + await send(cToken, 'harnessSetReserveFactorFresh', [etherUnsigned(1e17)]); + await pretendBlock(cToken) + + const expectedAccrualBlockNumber = blockNumber + 1; + const expectedBorrowIndex = borrowIndex + borrowRate * 1e18; + const expectedTotalBorrows = 1e22 + 1e18; + const expectedTotalReserves = 1e20 + 1e17; + + assert.success(await send(cToken, 'accrueInterest')); + assert.equal(await call(cToken, 'accrualBlockNumber'), expectedAccrualBlockNumber); + assert.equal(await call(cToken, 'borrowIndex'), expectedBorrowIndex); + assert.equal(await call(cToken, 'totalBorrows'), expectedTotalBorrows); + assert.equal(await call(cToken, 'totalReserves'), expectedTotalReserves); + }); + }); +}); diff --git a/test/Tokens/adminTest.js b/test/Tokens/adminTest.js new file mode 100644 index 000000000..85f44decf --- /dev/null +++ b/test/Tokens/adminTest.js @@ -0,0 +1,109 @@ +const {address, call, send} = require('../Utils/MochaTruffle'); +const {makeCToken} = require('../Utils/Compound'); + +contract('admin / _setPendingAdmin / _acceptAdmin', function([root, ...accounts]) { + let cToken; + beforeEach(async () => { + cToken = await makeCToken(); + }); + + describe('admin()', async () => { + it('should return correct admin', async () => { + assert.equal(await call(cToken, 'admin'), root); + }); + }); + + describe('pendingAdmin()', async () => { + it('should return correct pending admin', async () => { + assert.addressZero(await call(cToken, 'pendingAdmin')); + }); + }); + + describe('_setPendingAdmin()', async () => { + it('should only be callable by admin', async () => { + assert.hasTokenFailure( + await send(cToken, '_setPendingAdmin', [accounts[0]], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_PENDING_ADMIN_OWNER_CHECK' + ); + + // Check admin stays the same + assert.equal(await call(cToken, 'admin'), root); + assert.addressZero(await call(cToken, 'pendingAdmin')); + }); + + it('should properly set pending admin', async () => { + assert.success(await send(cToken, '_setPendingAdmin', [accounts[0]])); + + // Check admin stays the same + assert.equal(await call(cToken, 'admin'), root); + assert.equal(await call(cToken, 'pendingAdmin'), accounts[0]); + }); + + it('should properly set pending admin twice', async () => { + assert.success(await send(cToken, '_setPendingAdmin', [accounts[0]])); + assert.success(await send(cToken, '_setPendingAdmin', [accounts[1]])); + + // Check admin stays the same + assert.equal(await call(cToken, 'admin'), root); + assert.equal(await call(cToken, 'pendingAdmin'), accounts[1]); + }); + + it('should emit event', async () => { + const result = await send(cToken, '_setPendingAdmin', [accounts[0]]); + assert.hasLog(result, 'NewPendingAdmin', { + oldPendingAdmin: address(0), + newPendingAdmin: accounts[0], + }); + }); + }); + + describe('_acceptAdmin()', async () => { + it('should fail when pending admin is zero', async () => { + assert.hasTokenFailure( + await send(cToken, '_acceptAdmin'), + 'UNAUTHORIZED', + 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK' + ); + + // Check admin stays the same + assert.equal(await call(cToken, 'admin'), root); + assert.addressZero(await call(cToken, 'pendingAdmin')); + }); + + it('should fail when called by another account (e.g. root)', async () => { + assert.success(await send(cToken, '_setPendingAdmin', [accounts[0]])); + assert.hasTokenFailure( + await send(cToken, '_acceptAdmin'), + 'UNAUTHORIZED', + 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK' + ); + + // Check admin stays the same + assert.equal(await call(cToken, 'admin'), root); + assert.equal(await call(cToken, 'pendingAdmin') [accounts[0]]); + }); + + it('should succeed and set admin and clear pending admin', async () => { + assert.success(await send(cToken, '_setPendingAdmin', [accounts[0]])); + assert.success(await send(cToken, '_acceptAdmin', [], {from: accounts[0]})); + + // Check admin stays the same + assert.equal(await call(cToken, 'admin'), accounts[0]); + assert.addressZero(await call(cToken, 'pendingAdmin')); + }); + + it('should emit log on success', async () => { + assert.success(await send(cToken, '_setPendingAdmin', [accounts[0]])); + const result = await send(cToken, '_acceptAdmin', [], {from: accounts[0]}); + assert.hasLog(result, 'NewAdmin', { + oldAdmin: root, + newAdmin: accounts[0], + }); + assert.hasLog(result, 'NewPendingAdmin', { + oldPendingAdmin: accounts[0], + newPendingAdmin: address(0), + }); + }); + }); +}); diff --git a/test/Tokens/borrowAndRepayCEtherTest.js b/test/Tokens/borrowAndRepayCEtherTest.js new file mode 100644 index 000000000..e024c7238 --- /dev/null +++ b/test/Tokens/borrowAndRepayCEtherTest.js @@ -0,0 +1,362 @@ +const { + etherGasCost, + etherUnsigned, + etherMantissa, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + balanceOf, + borrowSnapshot, + totalBorrows, + fastForward, + setBalance, + preApprove, + pretendBorrow, + setEtherBalance, + getBalances, + adjustBalances +} = require('../Utils/Compound'); + +const BigNumber = require('bignumber.js'); + +const borrowAmount = etherUnsigned(10e3); +const repayAmount = etherUnsigned(10e2); + +async function preBorrow(cToken, borrower, borrowAmount) { + await send(cToken.comptroller, 'setBorrowAllowed', [true]); + await send(cToken.comptroller, 'setBorrowVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken, 'harnessSetFailTransferToAddress', [borrower, false]); + await send(cToken, 'harnessSetAccountBorrows', [borrower, 0, 0]); + await send(cToken, 'harnessSetTotalBorrows', [0]); + await setEtherBalance(cToken, borrowAmount); +} + +async function borrowFresh(cToken, borrower, borrowAmount) { + return send(cToken, 'harnessBorrowFresh', [borrower, borrowAmount], {from: borrower}); +} + +async function borrow(cToken, borrower, borrowAmount, opts = {}) { + return send(cToken, 'borrow', [borrowAmount], {from: borrower}); +} + +async function preRepay(cToken, benefactor, borrower, repayAmount) { + // setup either benefactor OR borrower for success in repaying + await send(cToken.comptroller, 'setRepayBorrowAllowed', [true]); + await send(cToken.comptroller, 'setRepayBorrowVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await pretendBorrow(cToken, borrower, 1, 1, repayAmount); +} + +async function repayBorrowFresh(cToken, payer, borrower, repayAmount) { + return send(cToken, 'harnessRepayBorrowFresh', [payer, borrower, repayAmount], {from: payer, value: repayAmount}); +} + +async function repayBorrow(cToken, borrower, repayAmount) { + return send(cToken, 'repayBorrow', [], {from: borrower, value: repayAmount}); +} + +async function repayBorrowBehalf(cToken, payer, borrower, repayAmount) { + return send(cToken, 'repayBorrowBehalf', [borrower], {from: payer, value: repayAmount}); +} + +contract('CEther', function ([root, borrower, benefactor, ...accounts]) { + let cToken; + before(async () => { + cToken = await makeCToken({kind: 'cether', comptrollerOpts: {kind: 'bool'}}); + }); + + describe('borrowFresh', async () => { + beforeEach(async () => await preBorrow(cToken, borrower, borrowAmount)); + + it("fails if comptroller tells it to", async () => { + await send(cToken.comptroller, 'setBorrowAllowed', [false]); + assert.hasTrollReject( + await borrowFresh(cToken, borrower, borrowAmount), + 'BORROW_COMPTROLLER_REJECTION' + ); + }); + + it("proceeds if comptroller tells it to", async () => { + await assert.success(await borrowFresh(cToken, borrower, borrowAmount)); + }); + + it("fails if market not fresh", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MARKET_NOT_FRESH', + 'BORROW_FRESHNESS_CHECK' + ); + }); + + it("continues if fresh", async () => { + await assert.succeeds(cToken, 'accrueInterest'); + await assert.success(await borrowFresh(cToken, borrower, borrowAmount)); + }); + + it("fails if protocol has less than borrowAmount of underlying", async () => { + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount.add(1)), + 'TOKEN_INSUFFICIENT_CASH', + 'BORROW_CASH_NOT_AVAILABLE' + ); + }); + + it("fails if borrowBalanceStored fails (due to non-zero stored principal with zero account index)", async () => { + await pretendBorrow(cToken, borrower, 0, 3e18, 5e18); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MATH_ERROR', + 'BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED' + ); + }); + + it("fails if calculating account new total borrow balance overflows", async () => { + await pretendBorrow(cToken, borrower, 1e-18, 1e-18, -1); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MATH_ERROR', + 'BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED' + ); + }); + + it("fails if calculation of new total borrow balance overflows", async () => { + await send(cToken, 'harnessSetTotalBorrows', [-1]); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MATH_ERROR', + 'BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', + ); + }); + + it("reverts if transfer out fails", async () => { + await send(cToken, 'harnessSetFailTransferToAddress', [borrower, true]); + await assert.revert(borrowFresh(cToken, borrower, borrowAmount), "revert borrow transfer out failed"); + }); + + it("reverts if borrowVerify fails", async() => { + await send(cToken.comptroller, 'setBorrowVerify', [false]); + await assert.revert(borrowFresh(cToken, borrower, borrowAmount), "revert borrowVerify rejected borrow"); + }); + + it("transfers the underlying cash, tokens, and emits Borrow event", async () => { + const beforeBalances = await getBalances([cToken], [borrower]); + const beforeProtocolBorrows = await totalBorrows(cToken); + const result = await borrowFresh(cToken, borrower, borrowAmount); + const afterBalances = await getBalances([cToken], [borrower]); + assert.success(result); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'eth', -borrowAmount], + [cToken, 'borrows', borrowAmount], + [cToken, borrower, 'eth', borrowAmount.sub(await etherGasCost(result))], + [cToken, borrower, 'borrows', borrowAmount] + ])); + assert.hasLog(result, 'Borrow', { + borrower: borrower, + borrowAmount: borrowAmount.toString(), + accountBorrows: borrowAmount.toString(), + totalBorrows: beforeProtocolBorrows.add(borrowAmount).toString() + }); + }); + + it("stores new borrow principal and interest index", async () => { + const beforeProtocolBorrows = await totalBorrows(cToken); + await pretendBorrow(cToken, borrower, 0, 3, 0); + await borrowFresh(cToken, borrower, borrowAmount); + const borrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(borrowSnap.principal, borrowAmount); + assert.numEqual(borrowSnap.interestIndex, etherMantissa(3)); + assert.numEqual(await totalBorrows(cToken), beforeProtocolBorrows.add(borrowAmount)); + }); + }); + + describe('borrow', async () => { + beforeEach(async () => await preBorrow(cToken, borrower, borrowAmount)); + + it("emits a borrow failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await borrow(cToken, borrower, borrowAmount), + 'INTEREST_RATE_MODEL_ERROR', + 'BORROW_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from borrowFresh without emitting any extra logs", async () => { + assert.hasTokenFailure( + await borrow(cToken, borrower, borrowAmount.add(1)), + 'TOKEN_INSUFFICIENT_CASH', + 'BORROW_CASH_NOT_AVAILABLE' + ); + }); + + it("returns success from borrowFresh and transfers the correct amount", async () => { + const beforeBalances = await getBalances([cToken], [borrower]); + await fastForward(cToken); + const result = await borrow(cToken, borrower, borrowAmount); + const afterBalances = await getBalances([cToken], [borrower]); + assert.success(result); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'eth', -borrowAmount], + [cToken, 'borrows', borrowAmount], + [cToken, borrower, 'eth', borrowAmount.sub(await etherGasCost(result))], + [cToken, borrower, 'borrows', borrowAmount] + ])); + }); + }); + + describe('repayBorrowFresh', async () => { + [benefactor, borrower].forEach(async (payer) => { + const label = benefactor == payer ? "benefactor paying" : "borrower paying"; + describe(label, () => { + beforeEach(async () => { + await preRepay(cToken, payer, borrower, repayAmount); + }); + + it("fails if repay is not allowed", async () => { + await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); + assert.hasTrollReject( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'REPAY_BORROW_COMPTROLLER_REJECTION', + 'MATH_ERROR' + ); + }); + + it("fails if block number ≠ current block number", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'MARKET_NOT_FRESH', + 'REPAY_BORROW_FRESHNESS_CHECK' + ); + }); + + it("returns an error if calculating account new account borrow balance fails", async () => { + await pretendBorrow(cToken, borrower, 1, 1, 1); + assert.hasTokenMathFail( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED', + 'INTEGER_UNDERFLOW' + ); + }); + + it("returns an error if calculation of new total borrow balance fails", async () => { + await send(cToken, 'harnessSetTotalBorrows', [1]); + assert.hasTokenMathFail( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', + 'INTEGER_UNDERFLOW' + ); + }); + + it("reverts if checkTransferIn fails", async () => { + await assert.revert(send(cToken, 'harnessRepayBorrowFresh', [payer, borrower, repayAmount], {from: root, value: repayAmount}), "revert sender mismatch"); + await assert.revert(send(cToken, 'harnessRepayBorrowFresh', [payer, borrower, repayAmount], {from: payer, value: 1}), "revert value mismatch"); + }); + + it("reverts if repayBorrowVerify fails", async() => { + await send(cToken.comptroller, 'setRepayBorrowVerify', [false]); + await assert.revert(repayBorrowFresh(cToken, payer, borrower, repayAmount), "revert repayBorrowVerify rejected repayBorrow"); + }); + + it("transfers the underlying cash, and emits RepayBorrow event", async () => { + const beforeBalances = await getBalances([cToken], [borrower]); + const result = await repayBorrowFresh(cToken, payer, borrower, repayAmount); + const afterBalances = await getBalances([cToken], [borrower]); + assert.success(result); + if (borrower == payer) { + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'eth', repayAmount], + [cToken, 'borrows', -repayAmount], + [cToken, borrower, 'borrows', -repayAmount], + [cToken, borrower, 'eth', -repayAmount.add(await etherGasCost(result))] + ])); + } else { + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'eth', repayAmount], + [cToken, 'borrows', -repayAmount], + [cToken, borrower, 'borrows', -repayAmount], + ])); + } + assert.hasLog(result, 'RepayBorrow', { + payer: payer, + borrower: borrower, + repayAmount: repayAmount.toString(), + accountBorrows: "0", + totalBorrows: "0" + }); + }); + + it("stores new borrow principal and interest index", async () => { + const beforeProtocolBorrows = await totalBorrows(cToken); + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.success(await repayBorrowFresh(cToken, payer, borrower, repayAmount)); + const afterAccountBorrows = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrows.principal, beforeAccountBorrowSnap.principal.sub(repayAmount)); + assert.numEqual(afterAccountBorrows.interestIndex, etherMantissa(1)); + assert.numEqual(await totalBorrows(cToken), beforeProtocolBorrows.sub(repayAmount)); + }); + }); + }); + }); + + describe('repayBorrow', async () => { + beforeEach(async () => { + await preRepay(cToken, borrower, borrower, repayAmount); + }); + + it("reverts if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + await assert.revertWithError(repayBorrow(cToken, borrower, repayAmount), 'INTEREST_RATE_MODEL_ERROR', "revert repayBorrow failed"); + }); + + it("reverts when repay borrow fresh fails", async () => { + await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); + await assert.revertWithError(repayBorrow(cToken, borrower, repayAmount), 'COMPTROLLER_REJECTION', "revert repayBorrow failed"); + }); + + it("returns success from repayBorrowFresh and repays the right amount", async () => { + await fastForward(cToken); + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.success(await repayBorrow(cToken, borrower, repayAmount)); + const afterAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrowSnap.principal, beforeAccountBorrowSnap.principal.sub(repayAmount)); + }); + + it("reverts if overpaying", async () => { + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + let tooMuch = new BigNumber(beforeAccountBorrowSnap.principal).plus(1); + await assert.revertWithError(repayBorrow(cToken, borrower, tooMuch), 'MATH_ERROR', "revert repayBorrow failed"); + }); + }); + + describe('repayBorrowBehalf', async () => { + const payer = benefactor; + + beforeEach(async () => { + await preRepay(cToken, payer, borrower, repayAmount); + }); + + it("reverts if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + await assert.revertWithError(repayBorrowBehalf(cToken, payer, borrower, repayAmount), 'INTEREST_RATE_MODEL_ERROR', "revert repayBorrowBehalf failed"); + }); + + it("reverts from within repay borrow fresh", async () => { + await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); + await assert.revertWithError(repayBorrowBehalf(cToken, payer, borrower, repayAmount), 'COMPTROLLER_REJECTION', "revert repayBorrowBehalf failed"); + }); + + it("returns success from repayBorrowFresh and repays the right amount", async () => { + await fastForward(cToken); + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.success(await repayBorrowBehalf(cToken, payer, borrower, repayAmount)); + const afterAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrowSnap.principal, beforeAccountBorrowSnap.principal.sub(repayAmount)); + }); + }); +}); diff --git a/test/Tokens/borrowAndRepayTest.js b/test/Tokens/borrowAndRepayTest.js new file mode 100644 index 000000000..76c11f22d --- /dev/null +++ b/test/Tokens/borrowAndRepayTest.js @@ -0,0 +1,390 @@ +const { + etherUnsigned, + etherMantissa, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + balanceOf, + borrowSnapshot, + totalBorrows, + fastForward, + setBalance, + preApprove, + pretendBorrow +} = require('../Utils/Compound'); + +const borrowAmount = etherUnsigned(10e3); +const repayAmount = etherUnsigned(10e2); + +async function preBorrow(cToken, borrower, borrowAmount) { + await send(cToken.comptroller, 'setBorrowAllowed', [true]); + await send(cToken.comptroller, 'setBorrowVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken.underlying, 'harnessSetBalance', [cToken._address, borrowAmount]); + await send(cToken, 'harnessSetFailTransferToAddress', [borrower, false]); + await send(cToken, 'harnessSetAccountBorrows', [borrower, 0, 0]); + await send(cToken, 'harnessSetTotalBorrows', [0]); +} + +async function borrowFresh(cToken, borrower, borrowAmount) { + return send(cToken, 'harnessBorrowFresh', [borrower, borrowAmount]); +} + +async function borrow(cToken, borrower, borrowAmount, opts = {}) { + return send(cToken, 'borrow', [borrowAmount], {from: borrower}); +} + +async function preRepay(cToken, benefactor, borrower, repayAmount) { + // setup either benefactor OR borrower for success in repaying + await send(cToken.comptroller, 'setRepayBorrowAllowed', [true]); + await send(cToken.comptroller, 'setRepayBorrowVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken.underlying, 'harnessSetFailTransferFromAddress', [benefactor, false]); + await send(cToken.underlying, 'harnessSetFailTransferFromAddress', [borrower, false]); + await pretendBorrow(cToken, borrower, 1, 1, repayAmount); + await preApprove(cToken, benefactor, repayAmount); + await preApprove(cToken, borrower, repayAmount); +} + +async function repayBorrowFresh(cToken, payer, borrower, repayAmount) { + return send(cToken, 'harnessRepayBorrowFresh', [payer, borrower, repayAmount], {from: payer}); +} + +async function repayBorrow(cToken, borrower, repayAmount) { + return send(cToken, 'repayBorrow', [repayAmount], {from: borrower}); +} + +async function repayBorrowBehalf(cToken, payer, borrower, repayAmount) { + return send(cToken, 'repayBorrowBehalf', [borrower, repayAmount], {from: payer}); +} + +contract('CToken', function ([root, borrower, benefactor, ...accounts]) { + let cToken; + before(async () => { + cToken = await makeCToken({comptrollerOpts: {kind: 'bool'}}); + }); + + describe('borrowFresh', async () => { + beforeEach(async () => await preBorrow(cToken, borrower, borrowAmount)); + + it("fails if comptroller tells it to", async () => { + await send(cToken.comptroller, 'setBorrowAllowed', [false]); + assert.hasTrollReject( + await borrowFresh(cToken, borrower, borrowAmount), + 'BORROW_COMPTROLLER_REJECTION' + ); + }); + + it("proceeds if comptroller tells it to", async () => { + await assert.success(await borrowFresh(cToken, borrower, borrowAmount)); + }); + + it("fails if market not fresh", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MARKET_NOT_FRESH', + 'BORROW_FRESHNESS_CHECK' + ); + }); + + it("continues if fresh", async () => { + await assert.succeeds(cToken, 'accrueInterest'); + await assert.success(await borrowFresh(cToken, borrower, borrowAmount)); + }); + + it("fails if error if protocol has less than borrowAmount of underlying", async () => { + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount.add(1)), + 'TOKEN_INSUFFICIENT_CASH', + 'BORROW_CASH_NOT_AVAILABLE' + ); + }); + + it("fails if borrowBalanceStored fails (due to non-zero stored principal with zero account index)", async () => { + await pretendBorrow(cToken, borrower, 0, 3e18, 5e18); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MATH_ERROR', + 'BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED' + ); + }); + + it("fails if calculating account new total borrow balance overflows", async () => { + await pretendBorrow(cToken, borrower, 1e-18, 1e-18, -1); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MATH_ERROR', + 'BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED' + ); + }); + + it("fails if calculation of new total borrow balance overflows", async () => { + await send(cToken, 'harnessSetTotalBorrows', [-1]); + assert.hasTokenFailure( + await borrowFresh(cToken, borrower, borrowAmount), + 'MATH_ERROR', + 'BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', + ); + }); + + it("reverts if transfer out fails", async () => { + await send(cToken, 'harnessSetFailTransferToAddress', [borrower, true]); + await assert.revert(borrowFresh(cToken, borrower, borrowAmount), "revert borrow transfer out failed"); + }); + + it("reverts if borrowVerify fails", async() => { + await send(cToken.comptroller, 'setBorrowVerify', [false]); + await assert.revert(borrowFresh(cToken, borrower, borrowAmount), "revert borrowVerify rejected borrow"); + }); + + it("transfers the underlying cash, tokens, and emits Transfer, Borrow events", async () => { + const beforeProtocolCash = await balanceOf(cToken.underlying, cToken._address); + const beforeProtocolBorrows = await totalBorrows(cToken); + const beforeAccountCash = await balanceOf(cToken.underlying, borrower); + const result = await borrowFresh(cToken, borrower, borrowAmount); + assert.success(result); + assert.numEqual(await balanceOf(cToken.underlying, borrower), beforeAccountCash.add(borrowAmount)); + assert.numEqual(await balanceOf(cToken.underlying, cToken._address), beforeProtocolCash.sub(borrowAmount)); + assert.numEqual(await totalBorrows(cToken), beforeProtocolBorrows.add(borrowAmount)); + assert.hasLog(result, 'Transfer', { + from: cToken._address, + to: borrower, + amount: borrowAmount.toString() + }); + assert.hasLog(result, 'Borrow', { + borrower: borrower, + borrowAmount: borrowAmount.toString(), + accountBorrows: borrowAmount.toString(), + totalBorrows: beforeProtocolBorrows.add(borrowAmount).toString() + }); + }); + + it("stores new borrow principal and interest index", async () => { + const beforeProtocolBorrows = await totalBorrows(cToken); + await pretendBorrow(cToken, borrower, 0, 3, 0); + await borrowFresh(cToken, borrower, borrowAmount); + const borrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(borrowSnap.principal, borrowAmount); + assert.numEqual(borrowSnap.interestIndex, etherMantissa(3)); + assert.numEqual(await totalBorrows(cToken), beforeProtocolBorrows.add(borrowAmount)); + }); + }); + + describe('borrow', async () => { + beforeEach(async () => await preBorrow(cToken, borrower, borrowAmount)); + + it("emits a borrow failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await borrow(cToken, borrower, borrowAmount), + 'INTEREST_RATE_MODEL_ERROR', + 'BORROW_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from borrowFresh without emitting any extra logs", async () => { + assert.hasTokenFailure( + await borrow(cToken, borrower, borrowAmount.add(1)), + 'TOKEN_INSUFFICIENT_CASH', + 'BORROW_CASH_NOT_AVAILABLE' + ); + }); + + it("returns success from borrowFresh and transfers the correct amount", async () => { + const beforeAccountCash = await balanceOf(cToken.underlying, borrower); + await fastForward(cToken); + assert.success(await borrow(cToken, borrower, borrowAmount)); + assert.numEqual(await balanceOf(cToken.underlying, borrower), beforeAccountCash.add(borrowAmount)); + }); + }); + + describe('repayBorrowFresh', async () => { + [benefactor, borrower].forEach(async (payer) => { + const label = benefactor == payer ? "benefactor paying" : "borrower paying"; + describe(label, () => { + beforeEach(async () => { + await preRepay(cToken, payer, borrower, repayAmount); + }); + + it("fails if repay is not allowed", async () => { + await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); + assert.hasTrollReject( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'REPAY_BORROW_COMPTROLLER_REJECTION', + 'MATH_ERROR' + ); + }); + + it("fails if block number ≠ current block number", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'MARKET_NOT_FRESH', + 'REPAY_BORROW_FRESHNESS_CHECK' + ); + }); + + it("fails if insufficient approval", async() => { + await preApprove(cToken, payer, 1); + assert.hasTokenFailure( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'TOKEN_INSUFFICIENT_ALLOWANCE', + 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("fails if insufficient balance", async() => { + await setBalance(cToken.underlying, payer, 1); + assert.hasTokenFailure( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'TOKEN_INSUFFICIENT_BALANCE', + 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("returns an error if calculating account new account borrow balance fails", async () => { + await pretendBorrow(cToken, borrower, 1, 1, 1); + assert.hasTokenMathFail( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED', + 'INTEGER_UNDERFLOW' + ); + }); + + it("returns an error if calculation of new total borrow balance fails", async () => { + await send(cToken, 'harnessSetTotalBorrows', [1]); + assert.hasTokenMathFail( + await repayBorrowFresh(cToken, payer, borrower, repayAmount), + 'REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', + 'INTEGER_UNDERFLOW' + ); + }); + + it("reverts if doTransferIn fails", async () => { + await send(cToken.underlying, 'harnessSetFailTransferFromAddress', [payer, true]); + await assert.revert(repayBorrowFresh(cToken, payer, borrower, repayAmount), "revert repay borrow transfer in failed"); + }); + + it("reverts if repayBorrowVerify fails", async() => { + await send(cToken.comptroller, 'setRepayBorrowVerify', [false]); + await assert.revert(repayBorrowFresh(cToken, payer, borrower, repayAmount), "revert repayBorrowVerify rejected repayBorrow"); + }); + + it("transfers the underlying cash, and emits Transfer, RepayBorrow events", async () => { + const beforeProtocolCash = await balanceOf(cToken.underlying, cToken._address); + const result = await repayBorrowFresh(cToken, payer, borrower, repayAmount); + assert.numEqual(await balanceOf(cToken.underlying, cToken._address), beforeProtocolCash.add(repayAmount)); + assert.hasLog(result, 'Transfer', { + from: payer, + to: cToken._address, + amount: repayAmount.toString() + }); + assert.hasLog(result, 'RepayBorrow', { + payer: payer, + borrower: borrower, + repayAmount: repayAmount.toString(), + accountBorrows: "0", + totalBorrows: "0" + }); + }); + + it("stores new borrow principal and interest index", async () => { + const beforeProtocolBorrows = await totalBorrows(cToken); + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.success(await repayBorrowFresh(cToken, payer, borrower, repayAmount)); + const afterAccountBorrows = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrows.principal, beforeAccountBorrowSnap.principal.sub(repayAmount)); + assert.numEqual(afterAccountBorrows.interestIndex, etherMantissa(1)); + assert.numEqual(await totalBorrows(cToken), beforeProtocolBorrows.sub(repayAmount)); + }); + }); + }); + }); + + describe('repayBorrow', async () => { + beforeEach(async () => { + await preRepay(cToken, borrower, borrower, repayAmount); + }); + + it("emits a repay borrow failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await repayBorrow(cToken, borrower, repayAmount), + 'INTEREST_RATE_MODEL_ERROR', + 'REPAY_BORROW_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from repayBorrowFresh without emitting any extra logs", async () => { + await setBalance(cToken.underlying, borrower, 1); + assert.hasTokenFailure( + await repayBorrow(cToken, borrower, repayAmount), + 'TOKEN_INSUFFICIENT_BALANCE', + 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("returns success from repayBorrowFresh and repays the right amount", async () => { + await fastForward(cToken); + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.success(await repayBorrow(cToken, borrower, repayAmount)); + const afterAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrowSnap.principal, beforeAccountBorrowSnap.principal.sub(repayAmount)); + }); + + it("repays the full amount owed if payer has enough", async () => { + await fastForward(cToken); + assert.success(await repayBorrow(cToken, borrower, -1)); + const afterAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrowSnap.principal, 0); + }); + + it("fails gracefully if payer does not have enough", async () => { + await setBalance(cToken.underlying, borrower, 3); + await fastForward(cToken); + assert.hasTokenFailure( + await repayBorrow(cToken, borrower, -1), + 'TOKEN_INSUFFICIENT_BALANCE', + 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + }); + + describe('repayBorrowBehalf', async () => { + const payer = benefactor; + + beforeEach(async () => { + await preRepay(cToken, payer, borrower, repayAmount); + }); + + it("emits a repay borrow failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await repayBorrowBehalf(cToken, payer, borrower, repayAmount), + 'INTEREST_RATE_MODEL_ERROR', + 'REPAY_BEHALF_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from repayBorrowFresh without emitting any extra logs", async () => { + await setBalance(cToken.underlying, payer, 1); + assert.hasTokenFailure( + await repayBorrowBehalf(cToken, payer, borrower, repayAmount), + 'TOKEN_INSUFFICIENT_BALANCE', + 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("returns success from repayBorrowFresh and repays the right amount", async () => { + await fastForward(cToken); + const beforeAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.success(await repayBorrowBehalf(cToken, payer, borrower, repayAmount)); + const afterAccountBorrowSnap = await borrowSnapshot(cToken, borrower); + assert.numEqual(afterAccountBorrowSnap.principal, beforeAccountBorrowSnap.principal.sub(repayAmount)); + }); + }); +}); diff --git a/test/Tokens/cTokenTest.js b/test/Tokens/cTokenTest.js new file mode 100644 index 000000000..6f4aee6e4 --- /dev/null +++ b/test/Tokens/cTokenTest.js @@ -0,0 +1,200 @@ +const { + etherUnsigned, + etherMantissa, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + setBorrowRate, + pretendBorrow +} = require('../Utils/Compound'); + +contract('CToken', function ([root, ...accounts]) { + describe('constructor', async () => { + it("fails when non erc-20 underlying", async () => { + await assert.revert(makeCToken({underlying: {_address: root}})); + }); + + it("fails when 0 initial exchange rate", async () => { + await assert.revert(makeCToken({exchangeRate: 0}), "revert Initial exchange rate must be greater than zero."); + }); + + it("succeeds with erc-20 underlying and non-zero exchange rate", async () => { + const cToken = await makeCToken(); + assert.equal(await call(cToken, 'underlying'), cToken.underlying._address); + assert.equal(await call(cToken, 'admin',), root); + }); + }); + + describe('name, symbol, decimals', async () => { + let cToken; + before(async () => { + cToken = await makeCToken({name: "CToken Foo", symbol: "cFOO", decimals: 10}); + }); + + it('should return correct name', async () => { + assert.equal(await call(cToken, 'name'), "CToken Foo"); + }); + + it('should return correct symbol', async () => { + assert.equal(await call(cToken, 'symbol'), "cFOO"); + }); + + it('should return correct decimals', async () => { + assert.equal(await call(cToken, 'decimals'), 10); + }); + }); + + describe('balanceOfUnderlying', () => { + it("has an underlying balance", async () => { + const cToken = await makeCToken({supportMarket: true, exchangeRate: 2}); + await send(cToken, 'harnessSetBalance', [root, 100]); + assert.equal(await call(cToken, 'balanceOfUnderlying', [root]), 200); + }); + }); + + describe('borrowRatePerBlock', () => { + it("has a borrow rate", async () => { + const cToken = await makeCToken({supportMarket: true, interestRateModelOpts: {kind: 'white-paper', baseRate: .05, multiplier: 0.45}}); + const perBlock = await call(cToken, 'borrowRatePerBlock'); + assert.approximately(perBlock * 2102400, 5e16, 1e8); + }); + }); + + describe('supplyRatePerBlock', () => { + it("reverts if there's no supply", async () => { + const cToken = await makeCToken({supportMarket: true, interestRateModelOpts: {kind: 'white-paper', baseRate: .05, multiplier: 0.45}}); + await assert.revert(call(cToken, 'supplyRatePerBlock'), "revert supplyRatePerBlock: calculating borrowsPer failed"); + }); + + it("has a supply rate", async () => { + const cToken = await makeCToken({supportMarket: true, interestRateModelOpts: {kind: 'white-paper', baseRate: .05, multiplier: 0.45}}); + await send(cToken, 'harnessSetReserveFactorFresh', [etherMantissa(.01)]); + await send(cToken, 'harnessExchangeRateDetails', [1, 1, 0]); + await send(cToken, 'harnessSetExchangeRate', [etherMantissa(1)]); + const perBlock = await call(cToken, 'supplyRatePerBlock'); + assert.approximately(perBlock * 2102400, 50e16 * .99, 1e8); // full utilization, 1% reserves + }); + }); + + describe("borrowBalanceCurrent", async () => { + const borrower = accounts[0]; + + let cToken; + before(async () => { + cToken = await makeCToken(); + }); + + beforeEach(async () => { + await setBorrowRate(cToken, .001) + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + }); + + it("reverts if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + await assert.revert(send(cToken, 'borrowBalanceCurrent', [borrower]), "revert accrue interest failed"); + }); + + it("returns successful result from borrowBalanceStored with no interest", async () => { + await setBorrowRate(cToken, 0); + await pretendBorrow(cToken, borrower, 1, 1, 5e18); + assert.equal(await call(cToken, 'borrowBalanceCurrent', [borrower]), 5e18) + }); + + it("returns successful result from borrowBalanceCurrent with no interest", async () => { + await setBorrowRate(cToken, 0); + await pretendBorrow(cToken, borrower, 1, 3, 5e18); + assert.success(await send(cToken, 'harnessFastForward', [5])); + assert.equal(await call(cToken, 'borrowBalanceCurrent', [borrower]), 5e18 * 3) + }); + }); + + describe("borrowBalanceStored", async () => { + const borrower = accounts[0]; + + let cToken; + beforeEach(async () => { + cToken = await makeCToken({comptrollerOpts: {kind: 'bool'}}); + }); + + it("returns 0 for account with no borrows", async () => { + assert.equal(await call(cToken, 'borrowBalanceStored', [borrower]), 0) + }); + + it("returns stored principal when account and market indexes are the same", async () => { + await pretendBorrow(cToken, borrower, 1, 1, 5e18); + assert.equal(await call(cToken, 'borrowBalanceStored', [borrower]), 5e18); + }); + + it("returns calculated balance when market index is higher than account index", async () => { + await pretendBorrow(cToken, borrower, 1, 3, 5e18); + assert.equal(await call(cToken, 'borrowBalanceStored', [borrower]), 5e18 * 3); + }); + + it("has undefined behavior when market index is lower than account index", async () => { + // The market index < account index should NEVER happen, so we don't test this case + }); + + it("reverts on overflow of principal", async () => { + await pretendBorrow(cToken, borrower, 1, 3, -1); + await assert.revert(call(cToken, 'borrowBalanceStored', [borrower]), "revert borrowBalanceStored: borrowBalanceStoredInternal failed"); + }); + + it("reverts on non-zero stored principal with zero account index", async () => { + await pretendBorrow(cToken, borrower, 0, 3, 5); + await assert.revert(call(cToken, 'borrowBalanceStored', [borrower]), "revert borrowBalanceStored: borrowBalanceStoredInternal failed"); + }); + }); + + describe('exchangeRateStored', async () => { + let cToken, exchangeRate = 2; + beforeEach(async () => { + cToken = await makeCToken({exchangeRate}); + }); + + it("returns initial exchange rate with zero cTokenSupply", async () => { + const result = await call(cToken, 'exchangeRateStored'); + assert.equal(result, etherMantissa(exchangeRate), "exchange rate should be initial exchange rate"); + }); + + it("calculates with single cTokenSupply and single total borrow", async () => { + const cTokenSupply = 1, totalBorrows = 1, totalReserves = 0; + await send(cToken, 'harnessExchangeRateDetails', [cTokenSupply, totalBorrows, totalReserves]); + const result = await call(cToken, 'exchangeRateStored'); + assert.equal(result, etherMantissa(1), "exchange rate should be 1 to 1 (ie: 1e18)"); + }); + + it("calculates with cTokenSupply and total borrows", async () => { + const cTokenSupply = 100e18, totalBorrows = 10e18, totalReserves = 0; + await send(cToken, 'harnessExchangeRateDetails', [cTokenSupply, totalBorrows, totalReserves].map(etherUnsigned)); + const result = await call(cToken, 'exchangeRateStored'); + assert.equal(result, etherMantissa(.1), "exchange rate should be 0.1 (ie: 10e18 / 100e18)"); + }); + + it("calculates with cash and cTokenSupply", async () => { + const cTokenSupply = 5e18, totalBorrows = 0, totalReserves = 0; + assert.success(await send(cToken.underlying, 'transfer', [cToken._address, etherMantissa(500)])); + await send(cToken, 'harnessExchangeRateDetails', [cTokenSupply, totalBorrows, totalReserves].map(etherUnsigned)); + const result = await call(cToken, 'exchangeRateStored'); + assert.equal(result, etherMantissa(100), "exchange rate should be 100 (ie: 500e18 / 5e18)"); + }); + + it("calculates with cash, borrows, reserves and cTokenSupply", async () => { + const cTokenSupply = 500e18, totalBorrows = 500e18, totalReserves = 5e18; + assert.success(await send(cToken.underlying, 'transfer', [cToken._address, etherMantissa(500)])); + await send(cToken, 'harnessExchangeRateDetails', [cTokenSupply, totalBorrows, totalReserves].map(etherUnsigned)); + const result = await call(cToken, 'exchangeRateStored'); + assert.equal(result, etherMantissa(1.99), "exchange rate should be 1.99 (ie: (500e18 + 500e18 - 5e18) / 500e18)"); + }); + }); + + describe('getCash', async () => { + it("gets the cash", async () => { + const cToken = await makeCToken(); + const result = await call(cToken, 'getCash'); + assert.equal(result, 0); + }); + }); +}); diff --git a/test/Tokens/liquidateTest.js b/test/Tokens/liquidateTest.js new file mode 100644 index 000000000..258a284c9 --- /dev/null +++ b/test/Tokens/liquidateTest.js @@ -0,0 +1,270 @@ +const { + etherGasCost, + etherUnsigned, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + fastForward, + setBalance, + getBalances, + adjustBalances, + pretendBorrow, + preApprove +} = require('../Utils/Compound'); + +const repayAmount = etherUnsigned(10e2); +const seizeAmount = repayAmount; +const seizeTokens = seizeAmount.mul(4); // forced + +async function preLiquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral) { + // setup for success in liquidating + await send(cToken.comptroller, 'setLiquidateBorrowAllowed', [true]); + await send(cToken.comptroller, 'setLiquidateBorrowVerify', [true]); + await send(cToken.comptroller, 'setRepayBorrowAllowed', [true]); + await send(cToken.comptroller, 'setRepayBorrowVerify', [true]); + await send(cToken.comptroller, 'setSeizeAllowed', [true]); + await send(cToken.comptroller, 'setSeizeVerify', [true]); + await send(cToken.comptroller, 'setFailCalculateSeizeTokens', [false]); + await send(cToken.underlying, 'harnessSetFailTransferFromAddress', [liquidator, false]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cTokenCollateral.interestRateModel, 'setFailBorrowRate', [false]); + await send(cTokenCollateral.comptroller, 'setCalculatedSeizeTokens', [seizeTokens]); + await setBalance(cTokenCollateral, liquidator, 0); + await setBalance(cTokenCollateral, borrower, seizeTokens); + await pretendBorrow(cTokenCollateral, borrower, 0, 1, 0); + await pretendBorrow(cToken, borrower, 1, 1, repayAmount); + await preApprove(cToken, liquidator, repayAmount); +} + +async function liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral) { + return send(cToken, 'harnessLiquidateBorrowFresh', [liquidator, borrower, repayAmount, cTokenCollateral._address]); +} + +async function liquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral) { + return send(cToken, 'liquidateBorrow', [borrower, repayAmount, cTokenCollateral._address], {from: liquidator}); +} + +async function seize(cToken, liquidator, borrower, seizeAmount) { + return send(cToken, 'seize', [liquidator, borrower, seizeAmount]); +} + +contract('CToken', function ([root, liquidator, borrower, ...accounts]) { + let cToken, cTokenCollateral; + before(async () => { + cToken = await makeCToken({comptrollerOpts: {kind: 'bool'}}); + cTokenCollateral = await makeCToken({comptroller: cToken.comptroller}); + }); + + beforeEach(async () => { + await preLiquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral); + }); + + describe('liquidateBorrowFresh', async () => { + it("fails if comptroller tells it to", async () => { + await send(cToken.comptroller, 'setLiquidateBorrowAllowed', [false]); + assert.hasTrollReject( + await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'LIQUIDATE_COMPTROLLER_REJECTION', + 'MATH_ERROR' + ); + }); + + it("proceeds if comptroller tells it to", async () => { + assert.success(await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral)); + }); + + it("fails if market not fresh", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'MARKET_NOT_FRESH', + 'LIQUIDATE_FRESHNESS_CHECK' + ); + }); + + it("fails if collateral market not fresh", async () => { + await fastForward(cToken); + await fastForward(cTokenCollateral); + await send(cToken, 'accrueInterest'); + assert.hasTokenFailure( + await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'MARKET_NOT_FRESH', + 'LIQUIDATE_COLLATERAL_FRESHNESS_CHECK' + ); + }); + + it("fails if borrower is equal to liquidator", async () => { + assert.hasTokenFailure( + await liquidateFresh(cToken, borrower, borrower, repayAmount, cTokenCollateral), + 'INVALID_ACCOUNT_PAIR', + 'LIQUIDATE_LIQUIDATOR_IS_BORROWER' + ); + }); + + it("fails if repayAmount = 0", async () => { + assert.hasTokenFailure( + await liquidateFresh(cToken, liquidator, borrower, 0, cTokenCollateral), + 'INVALID_CLOSE_AMOUNT_REQUESTED', + 'LIQUIDATE_CLOSE_AMOUNT_IS_ZERO' + ); + }); + + it("fails if calculating seize tokens fails and does not adjust balances", async () => { + const beforeBalances = await getBalances([cToken, cTokenCollateral], [liquidator, borrower]); + await send(cToken.comptroller, 'setFailCalculateSeizeTokens', [true]); + assert.hasTokenFailure( + await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'COMPTROLLER_CALCULATION_ERROR', + 'LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED', + ); + const afterBalances = await getBalances([cToken, cTokenCollateral], [liquidator, borrower]); + assert.deepEqual(afterBalances, beforeBalances); + }); + + it("fails if repay fails", async () => { + await send(cToken.comptroller, 'setRepayBorrowAllowed', [false]); + assert.hasTrollReject( + await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'LIQUIDATE_REPAY_BORROW_FRESH_FAILED' + ); + }); + + it("reverts if seize fails", async () => { + await send(cToken.comptroller, 'setSeizeAllowed', [false]); + await assert.revert(liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), "revert token seizure failed"); + }); + + it("reverts if liquidateBorrowVerify fails", async() => { + await send(cToken.comptroller, 'setLiquidateBorrowVerify', [false]); + await assert.revert(liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral), "revert liquidateBorrowVerify rejected liquidateBorrow"); + }); + + it("transfers the cash, borrows, tokens, and emits Transfer, LiquidateBorrow events", async () => { + const beforeBalances = await getBalances([cToken, cTokenCollateral], [liquidator, borrower]); + const result = await liquidateFresh(cToken, liquidator, borrower, repayAmount, cTokenCollateral); + const afterBalances = await getBalances([cToken, cTokenCollateral], [liquidator, borrower]); + assert.success(result); + assert.hasLog(result, 'LiquidateBorrow', { + liquidator: liquidator, + borrower: borrower, + repayAmount: repayAmount.toString(), + cTokenCollateral: cTokenCollateral._address, + seizeTokens: seizeTokens.toString() + }); + assert.hasLog(result, ['Transfer', 0], { + from: liquidator, + to: cToken._address, + amount: repayAmount.toString() + }); + assert.hasLog(result, ['Transfer', 1], { + from: borrower, + to: liquidator, + amount: seizeTokens.toString() + }); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'cash', repayAmount], + [cToken, 'borrows', -repayAmount], + [cToken, liquidator, 'cash', -repayAmount], + [cTokenCollateral, liquidator, 'tokens', seizeTokens], + [cToken, borrower, 'borrows', -repayAmount], + [cTokenCollateral, borrower, 'tokens', -seizeTokens] + ])); + }); + }); + + describe('liquidateBorrow', async () => { + it("emits a liquidation failure if borrowed asset interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await liquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'INTEREST_RATE_MODEL_ERROR', + 'LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED' + ); + }); + + it("emits a liquidation failure if collateral asset interest accrual fails", async () => { + await send(cTokenCollateral.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await liquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral), + 'INTEREST_RATE_MODEL_ERROR', + 'LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED' + ); + }); + + it("returns error from liquidateBorrowFresh without emitting any extra logs", async () => { + assert.hasTokenFailure( + await liquidate(cToken, liquidator, borrower, 0, cTokenCollateral), + 'INVALID_CLOSE_AMOUNT_REQUESTED', + 'LIQUIDATE_CLOSE_AMOUNT_IS_ZERO' + ); + }); + + it("returns success from liquidateBorrowFresh and transfers the correct amounts", async () => { + const beforeBalances = await getBalances([cToken, cTokenCollateral], [liquidator, borrower]); + const result = await liquidate(cToken, liquidator, borrower, repayAmount, cTokenCollateral); + const gasCost = await etherGasCost(result); + const afterBalances = await getBalances([cToken, cTokenCollateral], [liquidator, borrower]); + assert.success(result); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'cash', repayAmount], + [cToken, 'borrows', -repayAmount], + [cToken, liquidator, 'eth', -gasCost], + [cToken, liquidator, 'cash', -repayAmount], + [cTokenCollateral, liquidator, 'eth', -gasCost], + [cTokenCollateral, liquidator, 'tokens', seizeTokens], + [cToken, borrower, 'borrows', -repayAmount], + [cTokenCollateral, borrower, 'tokens', -seizeTokens] + ])); + }); + }); + + describe('seize', async () => { + // XXX verify callers are properly checked + + it("fails if seize is not allowed", async () => { + await send(cToken.comptroller, 'setSeizeAllowed', [false]); + assert.hasTrollReject( + await seize(cTokenCollateral, liquidator, borrower, seizeTokens), + 'LIQUIDATE_SEIZE_COMPTROLLER_REJECTION', + 'MATH_ERROR' + ); + }); + + it("fails if cTokenBalances[borrower] < amount", async () => { + await setBalance(cTokenCollateral, borrower, 1); + assert.hasTokenMathFail( + await seize(cTokenCollateral, liquidator, borrower, seizeTokens), + 'LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED', + 'INTEGER_UNDERFLOW' + ); + }); + + it("fails if cTokenBalances[liquidator] overflows", async () => { + await setBalance(cTokenCollateral, liquidator, -1); + assert.hasTokenMathFail( + await seize(cTokenCollateral, liquidator, borrower, seizeTokens), + 'LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED', + 'INTEGER_OVERFLOW' + ); + }); + + it("succeeds, updates balances, and emits Transfer event", async () => { + const beforeBalances = await getBalances([cTokenCollateral], [liquidator, borrower]); + const result = await seize(cTokenCollateral, liquidator, borrower, seizeTokens); + const afterBalances = await getBalances([cTokenCollateral], [liquidator, borrower]); + assert.success(result); + assert.hasLog(result, 'Transfer', { + from: borrower, + to: liquidator, + amount: seizeTokens.toString() + }); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cTokenCollateral, liquidator, 'tokens', seizeTokens], + [cTokenCollateral, borrower, 'tokens', -seizeTokens] + ])); + }); + }); +}); \ No newline at end of file diff --git a/test/Tokens/mintAndRedeemCEtherTest.js b/test/Tokens/mintAndRedeemCEtherTest.js new file mode 100644 index 000000000..deba82e3e --- /dev/null +++ b/test/Tokens/mintAndRedeemCEtherTest.js @@ -0,0 +1,129 @@ +const { + etherGasCost, + etherMantissa, + etherUnsigned, + send, + sendFallback +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + balanceOf, + fastForward, + setBalance, + setEtherBalance, + getBalances, + adjustBalances, +} = require('../Utils/Compound'); + +const exchangeRate = 5; +const mintAmount = etherUnsigned(1e5); +const mintTokens = mintAmount.div(exchangeRate); +const redeemTokens = etherUnsigned(10e3); +const redeemAmount = redeemTokens.mul(exchangeRate); + +async function preMint(cToken, minter, mintAmount, mintTokens, exchangeRate) { + await send(cToken.comptroller, 'setMintAllowed', [true]); + await send(cToken.comptroller, 'setMintVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken, 'harnessSetExchangeRate', [etherMantissa(exchangeRate)]); +} + +async function mintExplicit(cToken, minter, mintAmount) { + return send(cToken, 'mint', [], {from: minter, value: mintAmount}); +} + +async function mintFallback(cToken, minter, mintAmount) { + return sendFallback(cToken, {from: minter, value: mintAmount}); +} + +async function preRedeem(cToken, redeemer, redeemTokens, redeemAmount, exchangeRate) { + await send(cToken.comptroller, 'setRedeemAllowed', [true]); + await send(cToken.comptroller, 'setRedeemVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken, 'harnessSetExchangeRate', [etherMantissa(exchangeRate)]); + await setEtherBalance(cToken, redeemAmount); + await setBalance(cToken, redeemer, redeemTokens); +} + +async function redeemCTokens(cToken, redeemer, redeemTokens, redeemAmount) { + return send(cToken, 'redeem', [redeemTokens], {from: redeemer}); +} + +async function redeemUnderlying(cToken, redeemer, redeemTokens, redeemAmount) { + return send(cToken, 'redeemUnderlying', [redeemAmount], {from: redeemer}); +} + +contract('CEther', function ([root, minter, redeemer, ...accounts]) { + let cToken; + before(async () => { + cToken = await makeCToken({kind: 'cether', comptrollerOpts: {kind: 'bool'}}); + }); + + [mintExplicit, mintFallback].forEach((mint) => { + describe(mint.name, async () => { + beforeEach(async () => { + await preMint(cToken, minter, mintAmount, mintTokens, exchangeRate); + }); + + it("reverts if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + await assert.revertWithError(mint(cToken, minter, mintAmount), 'INTEREST_RATE_MODEL_ERROR', "revert mint failed"); + }); + + it("returns success from mintFresh and mints the correct number of tokens", async () => { + const beforeBalances = await getBalances([cToken], [minter]); + const receipt = await mint(cToken, minter, mintAmount); + const afterBalances = await getBalances([cToken], [minter]); + assert.success(receipt); + assert.numNotEqual(mintTokens, 0); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'eth', mintAmount], + [cToken, 'tokens', mintTokens], + [cToken, minter, 'eth', -mintAmount.add(await etherGasCost(receipt))], + [cToken, minter, 'tokens', mintTokens] + ])); + }); + }); + }); + + [redeemCTokens, redeemUnderlying].forEach((redeem) => { + describe(redeem.name, async () => { + beforeEach(async () => { + await preRedeem(cToken, redeemer, redeemTokens, redeemAmount, exchangeRate); + }); + + it("emits a redeem failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await redeem(cToken, redeemer, redeemTokens, redeemAmount), + 'INTEREST_RATE_MODEL_ERROR', + 'REDEEM_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from redeemFresh without emitting any extra logs", async () => { + assert.hasTokenFailure( + await redeem(cToken, redeemer, redeemTokens.mul(5), redeemAmount.mul(5)), + 'MATH_ERROR', + 'REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED' + ); + }); + + it("returns success from redeemFresh and redeems the correct amount", async () => { + await fastForward(cToken); + const beforeBalances = await getBalances([cToken], [redeemer]); + const receipt = await redeem(cToken, redeemer, redeemTokens, redeemAmount); + const afterBalances = await getBalances([cToken], [redeemer]); + assert.success(receipt); + assert.numNotEqual(redeemTokens, 0); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, 'eth', -redeemAmount], + [cToken, 'tokens', -redeemTokens], + [cToken, redeemer, 'eth', redeemAmount.sub(await etherGasCost(receipt))], + [cToken, redeemer, 'tokens', -redeemTokens] + ])); + }); + }); + }); +}); diff --git a/test/Tokens/mintAndRedeemTest.js b/test/Tokens/mintAndRedeemTest.js new file mode 100644 index 000000000..398c2e612 --- /dev/null +++ b/test/Tokens/mintAndRedeemTest.js @@ -0,0 +1,342 @@ +const { + etherUnsigned, + etherMantissa, + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + balanceOf, + fastForward, + setBalance, + getBalances, + adjustBalances, + preApprove, + quickMint, + preSupply, + quickRedeem, + quickRedeemUnderlying +} = require('../Utils/Compound'); + +const exchangeRate = 50e3; +const mintAmount = etherUnsigned(10e4); +const mintTokens = mintAmount.div(exchangeRate); +const redeemTokens = etherUnsigned(10e3); +const redeemAmount = redeemTokens.mul(exchangeRate); + +async function preMint(cToken, minter, mintAmount, mintTokens, exchangeRate) { + await preApprove(cToken, minter, mintAmount); + await send(cToken.comptroller, 'setMintAllowed', [true]); + await send(cToken.comptroller, 'setMintVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken.underlying, 'harnessSetFailTransferFromAddress', [minter, false]); + await send(cToken, 'harnessSetBalance', [minter, 0]); + await send(cToken, 'harnessSetExchangeRate', [etherMantissa(exchangeRate)]); +} + +async function mintFresh(cToken, minter, mintAmount) { + return send(cToken, 'harnessMintFresh', [minter, mintAmount]); +} + +async function preRedeem(cToken, redeemer, redeemTokens, redeemAmount, exchangeRate) { + await preSupply(cToken, redeemer, redeemTokens); + await send(cToken.comptroller, 'setRedeemAllowed', [true]); + await send(cToken.comptroller, 'setRedeemVerify', [true]); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken.underlying, 'harnessSetBalance', [cToken._address, redeemAmount]); + await send(cToken.underlying, 'harnessSetBalance', [redeemer, 0]); + await send(cToken.underlying, 'harnessSetFailTransferToAddress', [redeemer, false]); + await send(cToken, 'harnessSetExchangeRate', [etherMantissa(exchangeRate)]); +} + +async function redeemFreshTokens(cToken, redeemer, redeemTokens, redeemAmount) { + return send(cToken, 'harnessRedeemFresh', [redeemer, redeemTokens, 0]); +} + +async function redeemFreshAmount(cToken, redeemer, redeemTokens, redeemAmount) { + return send(cToken, 'harnessRedeemFresh', [redeemer, 0, redeemAmount]); +} + +contract('CToken', function ([root, minter, redeemer, ...accounts]) { + let cToken; + before(async () => { + cToken = await makeCToken({comptrollerOpts: {kind: 'bool'}, exchangeRate}); + }); + + describe('mintFresh', async () => { + beforeEach(async () => { + await preMint(cToken, minter, mintAmount, mintTokens, exchangeRate); + }); + + it("fails if comptroller tells it to", async () => { + await send(cToken.comptroller, 'setMintAllowed', [false]); + assert.hasTrollReject( + await mintFresh(cToken, minter, mintAmount), + 'MINT_COMPTROLLER_REJECTION', + 'MATH_ERROR' + ); + }); + + it("proceeds if comptroller tells it to", async () => { + await assert.success(await mintFresh(cToken, minter, mintAmount)); + }); + + it("fails if not fresh", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await mintFresh(cToken, minter, mintAmount), + 'MARKET_NOT_FRESH', + 'MINT_FRESHNESS_CHECK' + ); + }); + + it("continues if fresh", async () => { + await assert.succeeds(cToken, 'accrueInterest'); + assert.success(await mintFresh(cToken, minter, mintAmount)); + }); + + it("fails if insufficient approval", async () => { + assert.success(await send(cToken.underlying, 'approve', [cToken._address, 1], {from: minter})); + assert.hasTokenFailure( + await mintFresh(cToken, minter, mintAmount), + 'TOKEN_INSUFFICIENT_ALLOWANCE', + 'MINT_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("fails if insufficient balance", async() => { + await setBalance(cToken.underlying, minter, 1); + assert.hasTokenFailure( + await mintFresh(cToken, minter, mintAmount), + 'TOKEN_INSUFFICIENT_BALANCE', + 'MINT_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("proceeds if sufficient approval and balance", async () =>{ + assert.success(await mintFresh(cToken, minter, mintAmount)); + }); + + it("fails if exchange calculation fails", async () => { + assert.success(await send(cToken, 'harnessSetExchangeRate', [0])); + assert.hasTokenFailure( + await mintFresh(cToken, minter, mintAmount), + 'MATH_ERROR', + 'MINT_EXCHANGE_CALCULATION_FAILED' + ); + }); + + it("fails if transferring in fails", async () => { + await send(cToken.underlying, 'harnessSetFailTransferFromAddress', [minter, true]); + const result = await mintFresh(cToken, minter, mintAmount); + assert.hasTokenFailure( + result, + 'TOKEN_TRANSFER_IN_FAILED', + 'MINT_TRANSFER_IN_FAILED' + ); + }); + + it("transfers the underlying cash, tokens, and emits Mint, Transfer events", async () => { + const beforeBalances = await getBalances([cToken], [minter]); + const result = await mintFresh(cToken, minter, mintAmount); + const afterBalances = await getBalances([cToken], [minter]); + assert.success(result); + assert.hasLog(result, 'Mint', { + minter, + mintAmount: mintAmount.toString(), + mintTokens: mintTokens.toString() + }); + assert.hasLog(result, ['Transfer', 1], { + from: cToken._address, + to: minter, + amount: mintTokens.toString() + }); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, minter, 'cash', -mintAmount], + [cToken, minter, 'tokens', mintTokens], + [cToken, 'cash', mintAmount], + [cToken, 'tokens', mintTokens] + ])); + }); + }); + + describe('mint', async () => { + beforeEach(async () => { + await preMint(cToken, minter, mintAmount, mintTokens, exchangeRate); + }); + + it("emits a mint failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await quickMint(cToken, minter, mintAmount), + 'INTEREST_RATE_MODEL_ERROR', + 'MINT_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from mintFresh without emitting any extra logs", async () => { + await send(cToken.underlying, 'harnessSetBalance', [minter, 1]); + assert.hasTokenFailure( + await quickMint(cToken, minter, mintAmount, {faucet: false}), + 'TOKEN_INSUFFICIENT_BALANCE', + 'MINT_TRANSFER_IN_NOT_POSSIBLE' + ); + }); + + it("returns success from mintFresh and mints the correct number of tokens", async () => { + assert.success(await quickMint(cToken, minter, mintAmount)); + assert.numNotEqual(mintTokens, 0); + assert.numEqual(await balanceOf(cToken, minter), mintTokens); + }); + + it("emits an AccrueInterest event", async () => { + assert.hasLog(await quickMint(cToken, minter, mintAmount), 'AccrueInterest', {}); + }); + }); + + [redeemFreshTokens, redeemFreshAmount].forEach((redeemFresh) => { + describe(redeemFresh.name, async () => { + beforeEach(async () => { + await preRedeem(cToken, redeemer, redeemTokens, redeemAmount, exchangeRate); + }); + + it("fails if comptroller tells it to", async () =>{ + await send(cToken.comptroller, 'setRedeemAllowed', [false]); + assert.hasTrollReject( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'REDEEM_COMPTROLLER_REJECTION' + ); + }); + + it("fails if not fresh", async () => { + await fastForward(cToken); + assert.hasTokenFailure( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'MARKET_NOT_FRESH', + 'REDEEM_FRESHNESS_CHECK' + ); + }); + + it("continues if fresh", async () => { + await assert.succeeds(cToken, 'accrueInterest'); + assert.success(await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount)); + }); + + it("fails if insufficient protocol cash to transfer out", async() => { + await send(cToken.underlying, 'harnessSetBalance', [cToken._address, 1]); + assert.hasTokenFailure( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'TOKEN_INSUFFICIENT_CASH', + 'REDEEM_TRANSFER_OUT_NOT_POSSIBLE' + ); + }); + + it("fails if exchange calculation fails", async () => { + if (redeemFresh == redeemFreshTokens) { + assert.success(await send(cToken, 'harnessSetExchangeRate', [-1])); + assert.hasTokenFailure( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'MATH_ERROR', + 'REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED' + ); + } else { + assert.success(await send(cToken, 'harnessSetExchangeRate', [0])); + assert.hasTokenFailure( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'MATH_ERROR', + 'REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED' + ); + } + }); + + it("fails if transferring out fails", async () => { + await send(cToken.underlying, 'harnessSetFailTransferToAddress', [redeemer, true]); + await assert.revert(redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), "revert redeem transfer out failed"); + }); + + it("fails if total supply < redemption amount", async () => { + await send(cToken, 'harnessExchangeRateDetails', [0, 0, 0]); + assert.hasTokenFailure( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'MATH_ERROR', + 'REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED' + ); + }); + + it("reverts if new account balance underflows", async () => { + await send(cToken, 'harnessSetBalance', [redeemer, 0]); + assert.hasTokenFailure( + await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount), + 'MATH_ERROR', + 'REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED' + ); + }); + + it("transfers the underlying cash, tokens, and emits Redeem, Transfer events", async () => { + const beforeBalances = await getBalances([cToken], [redeemer]); + const result = await redeemFresh(cToken, redeemer, redeemTokens, redeemAmount); + const afterBalances = await getBalances([cToken], [redeemer]); + assert.success(result); + assert.hasLog(result, 'Redeem', { + redeemer, + redeemAmount: redeemAmount.toString(), + redeemTokens: redeemTokens.toString() + }); + assert.hasLog(result, ['Transfer', 1], { + from: redeemer, + to: cToken._address, + amount: redeemTokens.toString() + }); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, redeemer, 'cash', redeemAmount], + [cToken, redeemer, 'tokens', -redeemTokens], + [cToken, 'cash', -redeemAmount], + [cToken, 'tokens', -redeemTokens] + ])); + }); + }); + }); + + describe('redeem', async () => { + beforeEach(async () => { + await preRedeem(cToken, redeemer, redeemTokens, redeemAmount, exchangeRate); + }); + + it("emits a redeem failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await quickRedeem(cToken, redeemer, redeemTokens), + 'INTEREST_RATE_MODEL_ERROR', + 'REDEEM_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from redeemFresh without emitting any extra logs", async () => { + await setBalance(cToken.underlying, cToken._address, 0); + assert.hasTokenFailure( + await quickRedeem(cToken, redeemer, redeemTokens, {exchangeRate}), + 'TOKEN_INSUFFICIENT_CASH', + 'REDEEM_TRANSFER_OUT_NOT_POSSIBLE' + ); + }); + + it("returns success from redeemFresh and redeems the right amount", async () => { + assert.success(await send(cToken.underlying, 'harnessSetBalance', [cToken._address, redeemAmount])); + assert.success(await quickRedeem(cToken, redeemer, redeemTokens, {exchangeRate})); + assert.numNotEqual(redeemAmount, 0); + assert.numEqual(await balanceOf(cToken.underlying, redeemer), redeemAmount); + }); + + it("returns success from redeemFresh and redeems the right amount of underlying", async () => { + assert.success(await send(cToken.underlying, 'harnessSetBalance', [cToken._address, redeemAmount])); + assert.success(await quickRedeemUnderlying(cToken, redeemer, redeemAmount, {exchangeRate})); + assert.numNotEqual(redeemAmount, 0); + assert.numEqual(await balanceOf(cToken.underlying, redeemer), redeemAmount); + }); + + it("emits an AccrueInterest event", async () => { + assert.hasLog(await quickMint(cToken, minter, mintAmount), 'AccrueInterest', {}); + }); + }); +}); diff --git a/test/Tokens/reservesTest.js b/test/Tokens/reservesTest.js new file mode 100644 index 000000000..4c77a21d5 --- /dev/null +++ b/test/Tokens/reservesTest.js @@ -0,0 +1,209 @@ +const { + etherUnsigned, + etherMantissa, + both, + call, + send +} = require('../Utils/MochaTruffle'); + +const {makeCToken} = require('../Utils/Compound'); + +const factor = etherMantissa(.02); + +const reserves = etherUnsigned(3e12); +const cash = etherUnsigned(reserves.mul(2)); +const reduction = etherUnsigned(2e12); + +contract('CToken', function ([root, ...accounts]) { + describe('_setReserveFactorFresh', async () => { + let cToken; + beforeEach(async () => { + cToken = await makeCToken(); + }); + + it("rejects change by non-admin", async () => { + assert.hasTokenFailure( + await send(cToken, 'harnessSetReserveFactorFresh', [factor], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_RESERVE_FACTOR_ADMIN_CHECK' + ); + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor should still be 0"); + }); + + it("rejects change if market not fresh", async () => { + assert.success(await send(cToken, 'harnessFastForward', [5])); + assert.hasTokenFailure( + await send(cToken, 'harnessSetReserveFactorFresh', [factor]), + 'MARKET_NOT_FRESH', + 'SET_RESERVE_FACTOR_FRESH_CHECK' + ); + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor should still be 0"); + }); + + it("rejects newReserveFactor that descales to 1", async () => { + assert.hasTokenFailure( + await send(cToken, 'harnessSetReserveFactorFresh', [etherMantissa(1.01)]), + 'BAD_INPUT', + 'SET_RESERVE_FACTOR_BOUNDS_CHECK' + ); + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor should still be 0"); + }); + + it("accepts newReserveFactor in valid range and emits log", async () => { + const result = await send(cToken, 'harnessSetReserveFactorFresh', [factor]) + assert.success(result); + assert.equal(await call(cToken, 'reserveFactorMantissa'), factor, "reserve factor should be updated"); + assert.hasLog(result, "NewReserveFactor", { + oldReserveFactorMantissa: '0', + newReserveFactorMantissa: factor.toString(), + }); + }); + + it("accepts a change back to zero", async () => { + const result1 = await send(cToken, 'harnessSetReserveFactorFresh', [factor]); + const result2 = await send(cToken, 'harnessSetReserveFactorFresh', [0]); + assert.success(result1); + assert.success(result2); + assert.hasLog(result2, "NewReserveFactor", { + oldReserveFactorMantissa: factor.toString(), + newReserveFactorMantissa: '0', + }); + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor should still be 0"); + }); + }); + + describe('_setReserveFactor', async () => { + let cToken; + before(async () => { + cToken = await makeCToken(); + }); + + beforeEach(async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + await send(cToken, '_setReserveFactor', [0]); + }); + + it("emits a reserve factor failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await send(cToken, '_setReserveFactor', [factor]), + 'INTEREST_RATE_MODEL_ERROR', + 'SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED' + ); + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor should be 0"); + }); + + it("returns error from setReserveFactorFresh without emitting any extra logs", async () => { + const {reply, receipt} = await both(cToken, '_setReserveFactor', [etherMantissa(2)]); + assert.hasError(reply, 'BAD_INPUT'); + assert.hasTokenFailure( + receipt, + 'BAD_INPUT', + 'SET_RESERVE_FACTOR_BOUNDS_CHECK' + ); + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor should be 0"); + }); + + it("returns success from setReserveFactorFresh", async () => { + assert.equal(await call(cToken, 'reserveFactorMantissa'), 0, "reserve factor begin as 0"); + assert.success(await send(cToken, 'harnessFastForward', [5])); + await assert.succeeds(cToken, '_setReserveFactor', [factor]); + assert.equal(await call(cToken, 'reserveFactorMantissa'), factor, "reserve factor should be updated"); + }); + }); + + describe("_reduceReservesFresh", async () => { + let cToken; + beforeEach(async () => { + cToken = await makeCToken(); + assert.success(await send(cToken, 'harnessSetTotalReserves', [reserves])); + assert.success(await send(cToken.underlying, 'harnessSetBalance', [cToken._address, cash])); + }); + + it("fails if called by non-admin", async () => { + assert.hasTokenFailure( + await send(cToken, 'harnessReduceReservesFresh', [reduction], {from: accounts[0]}), + 'UNAUTHORIZED', + 'REDUCE_RESERVES_ADMIN_CHECK' + ); + assert.equal(await call(cToken, 'totalReserves'), reserves, "reserves should not have changed"); + }); + + it("fails if market not fresh", async () => { + assert.success(await send(cToken, 'harnessFastForward', [5])); + assert.hasTokenFailure( + await send(cToken, 'harnessReduceReservesFresh', [reduction]), + 'MARKET_NOT_FRESH', + 'REDUCE_RESERVES_FRESH_CHECK' + ); + assert.equal(await call(cToken, 'totalReserves'), reserves, "reserves should not have changed"); + }); + + it("fails if amount exceeds reserves", async () => { + assert.hasTokenFailure( + await send(cToken, 'harnessReduceReservesFresh', [reserves.add(1)]), + 'BAD_INPUT', + 'REDUCE_RESERVES_VALIDATION' + ); + assert.equal(await call(cToken, 'totalReserves'), reserves, "reserves should not have changed"); + }); + + it("fails if amount exceeds available cash", async () => { + const cashLessThanReserves = reserves.sub(2); + await send(cToken.underlying, 'harnessSetBalance', [cToken._address, cashLessThanReserves]); + assert.hasTokenFailure( + await send(cToken, 'harnessReduceReservesFresh', [reserves]), + 'TOKEN_INSUFFICIENT_CASH', + 'REDUCE_RESERVES_CASH_NOT_AVAILABLE' + ); + assert.equal(await call(cToken, 'totalReserves'), reserves, "reserves should not have changed"); + }); + + it("increases admin balance and reduces reserves on success", async () => { + const balance = etherUnsigned(await call(cToken.underlying, 'balanceOf', [root])); + assert.success(await send(cToken, 'harnessReduceReservesFresh', [reserves])); + assert.equal(await call(cToken.underlying, 'balanceOf', [root]), balance.add(reserves), "admin balance should have increased"); + assert.equal(await call(cToken, 'totalReserves'), 0, "reserves should have decreased"); + }); + + it("emits an event on success", async () => { + const result = await send(cToken, 'harnessReduceReservesFresh', [reserves]); + assert.hasLog(result, 'ReservesReduced', { + admin: root, + reduceAmount: reserves.toString(), + newTotalReserves: '0' + }); + }); + }); + + describe("_reduceReserves", async () => { + let cToken; + beforeEach(async () => { + cToken = await makeCToken(); + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + assert.success(await send(cToken, 'harnessSetTotalReserves', [reserves])); + assert.success(await send(cToken.underlying, 'harnessSetBalance', [cToken._address, cash])); + }); + + it("emits a reserve-reduction failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await send(cToken, '_reduceReserves', [reduction]), + 'INTEREST_RATE_MODEL_ERROR', + 'REDUCE_RESERVES_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from _reduceReservesFresh without emitting any extra logs", async () => { + const {reply, receipt} = await both(cToken, 'harnessReduceReservesFresh', [reserves.add(1)]); + assert.hasTokenError(reply, 'BAD_INPUT'); + assert.hasTokenFailure(receipt, 'BAD_INPUT', 'REDUCE_RESERVES_VALIDATION'); + }); + + it("returns success code from _reduceReservesFresh and reduces the correct amount", async () => { + assert.equal(await call(cToken, 'totalReserves'), reserves); + assert.success(await send(cToken, 'harnessFastForward', [5])); + await assert.succeeds(cToken, '_reduceReserves', [reduction]); + }); + }); +}); \ No newline at end of file diff --git a/test/Tokens/safeTokenTest.js b/test/Tokens/safeTokenTest.js new file mode 100644 index 000000000..d1f1736f2 --- /dev/null +++ b/test/Tokens/safeTokenTest.js @@ -0,0 +1,69 @@ +const { + call, + send +} = require('../Utils/MochaTruffle'); + +const { + makeCToken, + getBalances, + adjustBalances +} = require('../Utils/Compound'); + +const exchangeRate = 5; + +contract('CEther', function ([root, nonRoot, ...accounts]) { + let cToken; + before(async () => { + cToken = await makeCToken({kind: 'cether', comptrollerOpts: {kind: 'bool'}}); + }); + + describe("getCashPrior", async () => { + it("returns the amount of ether held by the cEther contract before the current message", async () => { + assert.equal(await call(cToken, 'harnessGetCashPrior', [], {value: 100}), 0); + }); + }); + + describe("doTransferIn", async () => { + it("succeeds if from is msg.nonRoot and amount is msg.value", async () => { + assert.equal(await call(cToken, 'harnessDoTransferIn', [root, 100], {value: 100}), 0); + }); + + it("reverts if from != msg.sender", async () => { + await assert.revert(call(cToken, 'harnessDoTransferIn', [nonRoot, 100], {value: 100}), "revert sender mismatch"); + }); + + it("reverts if amount != msg.value", async () => { + await assert.revert(call(cToken, 'harnessDoTransferIn', [root, 77], {value: 100}), "revert value mismatch"); + }); + + describe("doTransferOut", async () => { + it("transfers ether out", async () => { + const beforeBalances = await getBalances([cToken], [nonRoot]); + const receipt = await send(cToken, 'harnessDoTransferOut', [nonRoot, 77], {value: 77}); + const afterBalances = await getBalances([cToken], [nonRoot]); + assert.success(receipt); + assert.deepEqual(afterBalances, await adjustBalances(beforeBalances, [ + [cToken, nonRoot, 'eth', 77] + ])); + }); + + it("reverts if it fails", async () => { + await assert.revert(call(cToken, 'harnessDoTransferOut', [root, 77], {value: 0})); + }); + }); + + describe("checkTransferIn", async () => { + it("succeeds", async () => { + assert.hasError(await call(cToken, 'harnessCheckTransferIn', [root, 100], {value: 100}), 'NO_ERROR'); + }); + + it("reverts if sender is not from", async () => { + await assert.revert(call(cToken, 'harnessCheckTransferIn', [nonRoot, 100], {value: 100}), "revert sender mismatch"); + }); + + it("reverts if amount is not msg.value", async () => { + await assert.revert(call(cToken, 'harnessCheckTransferIn', [root, 77], {value: 100}), "revert value mismatch"); + }); + }); + }); +}); diff --git a/test/Tokens/setComptrollerTest.js b/test/Tokens/setComptrollerTest.js new file mode 100644 index 000000000..3939185aa --- /dev/null +++ b/test/Tokens/setComptrollerTest.js @@ -0,0 +1,48 @@ +const {call, send} = require('../Utils/MochaTruffle'); +const { + makeComptroller, + makeCToken +} = require('../Utils/Compound'); + +contract('CToken', function([root, ...accounts]) { + let cToken, oldComptroller, newComptroller; + before(async () => { + cToken = await makeCToken(); + oldComptroller = cToken.comptroller; + newComptroller = await makeComptroller(); + assert.notEqual(newComptroller._address, oldComptroller._address, 'setup failed'); + }); + + describe('_setComptroller', async () => { + it("should fail if called by non-admin", async () => { + assert.hasTokenFailure( + await send(cToken, '_setComptroller', [newComptroller._address], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_COMPTROLLER_OWNER_CHECK' + ); + assert.equal(await call(cToken, 'comptroller'), oldComptroller._address); + }); + + it("reverts if passed a contract that doesn't implement isComptroller", async () => { + await assert.revert(send(cToken, '_setComptroller', [cToken.underlying._address])); + assert.equal(await call(cToken, 'comptroller'), oldComptroller._address); + }); + + it("reverts if passed a contract that implements isComptroller as false", async () => { + // extremely unlikely to occur, of course, but let's be exhaustive + const badComptroller = await makeComptroller({kind: 'false-marker'}); + await assert.revert(send(cToken, '_setComptroller', [badComptroller._address]), "revert marker method returned false"); + assert.equal(await call(cToken, 'comptroller'), oldComptroller._address); + }); + + it("updates comptroller and emits log on success", async () => { + const result = await send(cToken, '_setComptroller', [newComptroller._address]); + assert.success(result); + assert.hasLog(result, 'NewComptroller', { + oldComptroller: oldComptroller._address, + newComptroller: newComptroller._address + }); + assert.equal(await call(cToken, 'comptroller'), newComptroller._address); + }); + }); +}); diff --git a/test/Tokens/setInterestRateModelTest.js b/test/Tokens/setInterestRateModelTest.js new file mode 100644 index 000000000..905431d74 --- /dev/null +++ b/test/Tokens/setInterestRateModelTest.js @@ -0,0 +1,103 @@ +const {both, call, send} = require('../Utils/MochaTruffle'); +const { + makeCToken, + makeInterestRateModel +} = require('../Utils/Compound'); + +contract('CToken', function ([root, ...accounts]) { + let newModel; + before(async () => { + newModel = await makeInterestRateModel(); + }); + + describe("_setInterestRateModelFresh", async () => { + let cToken, oldModel; + beforeEach(async () => { + cToken = await makeCToken(); + oldModel = cToken.interestRateModel; + assert.notEqual(oldModel._address, newModel._address, 'setup failed'); + }); + + it("fails if called by non-admin", async () => { + assert.hasTokenFailure( + await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address], {from: accounts[0]}), + 'UNAUTHORIZED', + 'SET_INTEREST_RATE_MODEL_OWNER_CHECK' + ); + assert.equal(await call(cToken, 'interestRateModel'), oldModel._address); + }); + + it("fails if market not fresh", async () => { + assert.success(await send(cToken, 'harnessFastForward', [5])); + assert.hasTokenFailure( + await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address]), + 'MARKET_NOT_FRESH', + 'SET_INTEREST_RATE_MODEL_FRESH_CHECK' + ); + assert.equal(await call(cToken, 'interestRateModel'), oldModel._address); + }); + + it("reverts if passed a contract that doesn't implement isInterestRateModel", async () => { + await assert.revert(send(cToken, 'harnessSetInterestRateModelFresh', [cToken.underlying._address])); + assert.equal(await call(cToken, 'interestRateModel'), oldModel._address); + }); + + it("reverts if passed a contract that implements isInterestRateModel as false", async () => { + // extremely unlikely to occur, of course, but let's be exhaustive + const badModel = await makeInterestRateModel({kind: 'false-marker'}); + await assert.revert(send(cToken, 'harnessSetInterestRateModelFresh', [badModel._address]), "revert marker method returned false"); + assert.equal(await call(cToken, 'interestRateModel'), oldModel._address); + }); + + it("accepts new valid interest rate model", async () => { + assert.success(await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address])); + assert.equal(await call(cToken, 'interestRateModel'), newModel._address); + }); + + it("emits expected log when accepting a new valid interest rate model", async () => { + const result = await send(cToken, 'harnessSetInterestRateModelFresh', [newModel._address]); + assert.success(result); + assert.hasLog(result, 'NewMarketInterestRateModel', { + oldInterestRateModel: oldModel._address, + newInterestRateModel: newModel._address, + }); + assert.equal(await call(cToken, 'interestRateModel'), newModel._address); + }); + }); + + describe("_setInterestRateModel", async () => { + let cToken; + before(async () => { + cToken = await makeCToken(); + }); + + beforeEach(async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [false]); + }); + + it("emits a set market interest rate model failure if interest accrual fails", async () => { + await send(cToken.interestRateModel, 'setFailBorrowRate', [true]); + assert.hasTokenFailure( + await send(cToken, '_setInterestRateModel', [newModel._address]), + 'INTEREST_RATE_MODEL_ERROR', + 'SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED' + ); + }); + + it("returns error from _setInterestRateModelFresh without emitting any extra logs", async () => { + const {reply, receipt} = await both(cToken, '_setInterestRateModel', [newModel._address], {from: accounts[0]}); + assert.hasError(reply, 'UNAUTHORIZED'); + assert.hasTokenFailure(receipt, + 'UNAUTHORIZED', + 'SET_INTEREST_RATE_MODEL_OWNER_CHECK' + ); + }); + + it("reports success when _setInterestRateModelFresh succeeds", async () => { + const {reply, receipt} = await both(cToken, '_setInterestRateModel', [newModel._address]); + assert.equal(reply, 0, "return code should be 0"); + assert.success(receipt); + assert.equal(await call(cToken, 'interestRateModel'), newModel._address); + }); + }); +}); \ No newline at end of file diff --git a/test/Tokens/transferTest.js b/test/Tokens/transferTest.js new file mode 100644 index 000000000..cbdb90276 --- /dev/null +++ b/test/Tokens/transferTest.js @@ -0,0 +1,52 @@ +const {call, send} = require('../Utils/MochaTruffle'); +const {makeCToken} = require('../Utils/Compound'); + +contract('CToken', function ([root, ...accounts]) { + describe('transfer', () => { + it("cannot transfer from a zero balance", async () => { + const cToken = await makeCToken({supportMarket: true}); + assert.equal(await call(cToken, 'balanceOf', [root]), 0); + assert.hasTokenFailure( + await send(cToken, 'transfer', [accounts[0], 100]), + 'MATH_ERROR', + 'TRANSFER_NOT_ENOUGH' + ); + }); + + it("transfers 50 tokens", async () => { + const cToken = await makeCToken({supportMarket: true}); + await send(cToken, 'harnessSetBalance', [root, 100]); + assert.equal(await call(cToken, 'balanceOf', [root]), 100); + await send(cToken, 'transfer', [accounts[0], 50]); + assert.equal(await call(cToken, 'balanceOf', [root]), 50); + assert.equal(await call(cToken, 'balanceOf', [accounts[0]]), 50); + }); + + it("doesn't transfer when src == dst", async () => { + const cToken = await makeCToken({supportMarket: true}); + await send(cToken, 'harnessSetBalance', [root, 100]); + assert.equal(await call(cToken, 'balanceOf', [root]), 100); + assert.hasTokenFailure( + await send(cToken, 'transfer', [root, 50]), + 'BAD_INPUT', + 'TRANSFER_NOT_ALLOWED' + ); + }); + + it("rejects transfer when not allowed and reverts if not verified", async () => { + const cToken = await makeCToken({comptrollerOpts: {kind: 'bool'}}); + await send(cToken, 'harnessSetBalance', [root, 100]); + assert.equal(await call(cToken, 'balanceOf', [root]), 100); + + await send(cToken.comptroller, 'setTransferAllowed', [false]) + assert.hasTrollReject( + await send(cToken, 'transfer', [root, 50]), + 'TRANSFER_COMPTROLLER_REJECTION' + ); + + await send(cToken.comptroller, 'setTransferAllowed', [true]) + await send(cToken.comptroller, 'setTransferVerify', [false]) + await assert.revert(send(cToken, 'transfer', [accounts[0], 50]), "revert transferVerify rejected transfer"); + }); + }); +}); \ No newline at end of file diff --git a/test/Utils/Compound.js b/test/Utils/Compound.js new file mode 100644 index 000000000..e15ea5cae --- /dev/null +++ b/test/Utils/Compound.js @@ -0,0 +1,378 @@ +"use strict"; + +const {dfn} = require('./JS'); +const { + etherBalance, + etherMantissa, + etherUnsigned, + + getContract, + getTestContract, + guessRoot, + + send, + call, + callUnsigned +} = require('./MochaTruffle'); + +async function makeComptroller(opts = {}) { + const { + root = await guessRoot(), + kind = 'unitroller-v1' + } = opts || {}; + + if (kind == 'bool') { + const Comptroller = getTestContract('BoolComptroller'); + const comptroller = await Comptroller.deploy().send({from: root}); + return comptroller; + } + + if (kind == 'false-marker') { + const Comptroller = getTestContract('FalseMarkerMethodComptroller'); + const comptroller = await Comptroller.deploy().send({from: root}); + return comptroller; + } + + if (kind == 'v1-no-proxy' ) { + const Comptroller = getContract('ComptrollerHarness'); + const priceOracle = opts.priceOracle || await makePriceOracle(opts.priceOracleOpts); + const closeFactor = etherMantissa(dfn(opts.closeFactor, .051)); + const maxAssets = etherUnsigned(dfn(opts.maxAssets, 10)); + const liquidationIncentive = etherUnsigned(1); + const comptroller = await Comptroller.deploy().send({from: root}); + + await comptroller.methods._setLiquidationIncentive(liquidationIncentive).send({from: root}); + await comptroller.methods._setCloseFactor(closeFactor).send({from: root}); + await comptroller.methods._setMaxAssets(maxAssets).send({from: root}); + await comptroller.methods._setPriceOracle(priceOracle._address).send({from: root}); + + comptroller.options.address = comptroller._address; + return Object.assign(comptroller, {priceOracle}); + } + + if (kind == 'unitroller-v1') { + const Unitroller = getContract('Unitroller'); + const Comptroller = getContract('ComptrollerHarness'); + const priceOracle = opts.priceOracle || await makePriceOracle(opts.priceOracleOpts); + const closeFactor = etherMantissa(dfn(opts.closeFactor, .051)); + const maxAssets = etherUnsigned(dfn(opts.maxAssets, 10)); + const unitroller = await Unitroller.deploy().send({from: root}); + const comptroller = await Comptroller.deploy().send({from: root}); + await unitroller.methods._setPendingImplementation(comptroller._address).send({from: root}); + await comptroller.methods._become(unitroller._address, priceOracle._address, closeFactor, maxAssets, false).send({from: root}); + comptroller.options.address = unitroller._address; + return Object.assign(comptroller, {priceOracle}); + } +} + +async function makeCToken(opts = {}) { + const { + root = await guessRoot(), + kind = 'cerc20' + } = opts || {}; + + const comptroller = opts.comptroller || await makeComptroller(opts.comptrollerOpts); + const interestRateModel = opts.interestRateModel || await makeInterestRateModel(opts.interestRateModelOpts); + const exchangeRate = etherMantissa(dfn(opts.exchangeRate, 1)); + const decimals = etherUnsigned(dfn(opts.decimals, 8)); + const symbol = opts.symbol || 'cOMG'; + const name = opts.name || `CToken ${symbol}`; + + let cToken, underlying; + + switch (kind) { + case 'cether': + const CEther = getTestContract('CEtherHarness'); + cToken = await CEther.deploy({ + arguments: [ + comptroller._address, + interestRateModel._address, + exchangeRate, + name, + symbol, + decimals + ]}).send({from: root}); + break; + case 'cerc20': + default: + const CErc20 = getTestContract('CErc20Harness'); + underlying = opts.underlying || await makeToken(opts.underlyingOpts); + cToken = await CErc20.deploy({ + arguments: [ + underlying._address, + comptroller._address, + interestRateModel._address, + exchangeRate, + name, + symbol, + decimals + ]}).send({from: root}); + break; + } + + if (opts.supportMarket) { + await comptroller.methods._supportMarket(cToken._address).send({from: root}); + } + + if (opts.underlyingPrice) { + const price = etherMantissa(opts.underlyingPrice); + await comptroller.priceOracle.methods.setUnderlyingPrice(cToken._address, price).send({from: root}); + } + + if (opts.collateralFactor) { + const factor = etherMantissa(opts.collateralFactor); + await comptroller.methods._setCollateralFactor(cToken._address, factor).send({from: root}); + } + + return Object.assign(cToken, {name, symbol, underlying, comptroller, interestRateModel}); +} + +async function makeInterestRateModel(opts = {}) { + const { + root = await guessRoot(), + kind = 'harnessed' + } = opts || {}; + + if (kind == 'harnessed') { + const InterestRateModel = getTestContract('InterestRateModelHarness'); + const borrowRate = etherMantissa(dfn(opts.borrowRate, 0)); + const interestRateModel = await InterestRateModel.deploy({arguments: [borrowRate]}).send({from: root}); + return interestRateModel; + } + + if (kind == 'false-marker') { + const InterestRateModel = getTestContract('FalseMarkerMethodInterestRateModel'); + const borrowRate = etherMantissa(dfn(opts.borrowRate, 0)); + const interestRateModel = await InterestRateModel.deploy({arguments: [borrowRate]}).send({from: root}); + return interestRateModel; + } + + if (kind == 'white-paper') { + const InterestRateModel = getTestContract('WhitePaperInterestRateModel'); + const baseRate = etherMantissa(dfn(opts.baseRate, 0)); + const multiplier = etherMantissa(dfn(opts.multiplier, 1e-18)); + const interestRateModel = await InterestRateModel.deploy({arguments: [baseRate, multiplier]}).send({from: root}); + return interestRateModel; + } +} + +async function makePriceOracle(opts = {}) { + const { + root = await guessRoot(), + kind = 'simple' + } = opts || {}; + + if (kind == 'simple') { + const PriceOracle = getContract('SimplePriceOracle'); + const priceOracle = await PriceOracle.deploy().send({from: root}); + return priceOracle; + } + + if (kind == 'proxy') { + const cEther = opts.cEther || await makeCToken({ + kind: 'cether', + supportMarket: true, + comptrollerOpts: { + priceOracleOpts: {kind: 'simple'} + }, ...opts.cEtherOpts}); + const comptroller = cEther.comptroller; + const priceOracle = comptroller.priceOracle; + const PriceOracleProxy = getContract('PriceOracleProxy'); + const priceOracleProxy = await PriceOracleProxy.deploy({ + arguments: [ + comptroller._address, + priceOracle._address, + cEther._address + ]}).send({from: root}); + return Object.assign(priceOracleProxy, {cEther, comptroller, priceOracle}); + } +} + +async function makeToken(opts = {}) { + const { + root = await guessRoot(), + kind = 'erc20' + } = opts || {}; + + if (kind == 'erc20') { + const Token = getTestContract('EIP20Harness'); + const quantity = etherUnsigned(dfn(opts.quantity, 1e25)); + const decimals = etherUnsigned(dfn(opts.decimals, 18)); + const symbol = opts.symbol || 'OMG'; + const name = opts.name || `Erc20 ${symbol}`; + const token = await Token.deploy({arguments: [quantity, name, decimals, symbol]}).send({from: root}); + return token; + } +} + +async function balanceOf(token, account) { + return callUnsigned(token, 'balanceOf', [account]); +} + +async function totalSupply(token) { + return callUnsigned(token, 'totalSupply'); +} + +async function borrowSnapshot(cToken, account) { + const {principal, interestIndex} = await call(cToken, 'harnessAccountBorrows', [account]); + return {principal: etherUnsigned(principal), interestIndex: etherUnsigned(interestIndex)}; +} + +async function totalBorrows(cToken) { + return callUnsigned(cToken, 'totalBorrows'); +} + +async function totalReserves(cToken) { + return callUnsigned(cToken, 'totalReserves'); +} + +async function enterMarkets(cTokens, from) { + return send(cTokens[0].comptroller, 'enterMarkets', [cTokens.map(c => c._address)], {from}); +} + +async function fastForward(cToken, blocks = 5) { + return send(cToken, 'harnessFastForward', [blocks]); +} + +async function setBalance(cToken, account, balance) { + return send(cToken, 'harnessSetBalance', [account, balance]); +} + +async function setEtherBalance(cEther, balance) { + const current = await etherBalance(cEther._address); + const root = await guessRoot(); + await send(cEther, 'harnessDoTransferOut', [root, current]); + await send(cEther, 'harnessDoTransferIn', [root, balance], {value: balance}); +} + +async function getBalances(cTokens, accounts) { + const balances = {}; + for (let cToken of cTokens) { + const cBalances = balances[cToken._address] = {}; + for (let account of accounts) { + cBalances[account] = { + eth: await etherBalance(account), + cash: cToken.underlying && await balanceOf(cToken.underlying, account), + tokens: await balanceOf(cToken, account), + borrows: (await borrowSnapshot(cToken, account)).principal + }; + } + cBalances[cToken._address] = { + eth: await etherBalance(cToken._address), + cash: cToken.underlying && await balanceOf(cToken.underlying, cToken._address), + tokens: await totalSupply(cToken), + borrows: await totalBorrows(cToken), + reserves: await totalReserves(cToken) + }; + } + return balances; +} + +async function adjustBalances(balances, deltas) { + for (let delta of deltas) { + let cToken, account, key, diff; + if (delta.length == 4) { + ([cToken, account, key, diff] = delta); + } else { + ([cToken, key, diff] = delta); + account = cToken._address; + } + balances[cToken._address][account][key] = balances[cToken._address][account][key].add(diff); + } + return balances; +} + + +async function preApprove(cToken, from, amount, opts = {}) { + if (dfn(opts.faucet, true)){ + assert.success(await send(cToken.underlying, 'harnessSetBalance', [from, amount], {from})); + } + return send(cToken.underlying, 'approve', [cToken._address, amount], {from}); +} + +async function quickMint(cToken, minter, mintAmount, opts = {}) { + if (dfn(opts.approve, true)){ + assert.success(await preApprove(cToken, minter, mintAmount, opts)); + } + if (dfn(opts.exchangeRate)){ + assert.success(await send(cToken, 'harnessSetExchangeRate', [etherMantissa(opts.exchangeRate)])); + } + return send(cToken, 'mint', [mintAmount], {from: minter}); +} + + +async function preSupply(cToken, account, tokens, opts = {}) { + if (dfn(opts.total, true)){ + assert.success(await send(cToken, 'harnessSetTotalSupply', [tokens])); + } + return send(cToken, 'harnessSetBalance', [account, tokens]); +} + +async function quickRedeem(cToken, redeemer, redeemTokens, opts = {}) { + if (dfn(opts.supply, true)) { + assert.success(await preSupply(cToken, redeemer, redeemTokens, opts)); + } + if (dfn(opts.exchangeRate)) { + assert.success(await send(cToken, 'harnessSetExchangeRate', [etherMantissa(opts.exchangeRate)])); + } + return send(cToken, 'redeem', [redeemTokens], {from: redeemer}); +} + +async function quickRedeemUnderlying(cToken, redeemer, redeemAmount, opts = {}) { + if (dfn(opts.exchangeRate)){ + assert.success(await send(cToken, 'harnessSetExchangeRate', [etherMantissa(opts.exchangeRate)])); + } + return send(cToken, 'redeemUnderlying', [redeemAmount], {from: redeemer}); +} + +async function setOraclePrice(cToken, price) { + return send(cToken.comptroller.priceOracle, 'setUnderlyingPrice', [cToken._address, etherMantissa(price)]); +} + +async function setBorrowRate(cToken, rate) { + return send(cToken.interestRateModel, 'setBorrowRate', [etherMantissa(rate)]); +} + +async function getBorrowRate(interestRateModel, cash, borrows, reserves) { + return call(interestRateModel, 'getBorrowRate', [cash, borrows, reserves].map(etherUnsigned)); +} + +async function pretendBorrow(cToken, borrower, accountIndex, marketIndex, principalRaw, blockNumber = 2e7) { + await send(cToken, 'harnessSetTotalBorrows', [etherUnsigned(principalRaw)]); + await send(cToken, 'harnessSetAccountBorrows', [borrower, etherUnsigned(principalRaw), etherMantissa(accountIndex)]); + await send(cToken, 'harnessSetBorrowIndex', [etherMantissa(marketIndex)]); + await send(cToken, 'harnessSetAccrualBlockNumber', [etherUnsigned(blockNumber)]); + await send(cToken, 'harnessSetBlockNumber', [etherUnsigned(blockNumber)]); +} + +module.exports = { + makeComptroller, + makeCToken, + makeInterestRateModel, + makePriceOracle, + makeToken, + + balanceOf, + totalSupply, + borrowSnapshot, + totalBorrows, + totalReserves, + enterMarkets, + fastForward, + setBalance, + setEtherBalance, + getBalances, + adjustBalances, + + preApprove, + quickMint, + + preSupply, + quickRedeem, + quickRedeemUnderlying, + + setOraclePrice, + setBorrowRate, + getBorrowRate, + pretendBorrow +}; diff --git a/test/Utils/JS.js b/test/Utils/JS.js new file mode 100644 index 000000000..78b038d62 --- /dev/null +++ b/test/Utils/JS.js @@ -0,0 +1,24 @@ +"use strict"; + +function dfn(val, def) { + return isFinite(val) ? val : def; +} + +function last(elems) { + return Array.isArray(elems) ? elems[elems.length - 1] : elems; +} + +function lookup(obj, path = []) { + return Array.isArray(path) ? path.reduce((a, k) => a[k], obj) : obj[path]; +} + +function select(obj, keys = []) { + return keys.reduce((a, k) => (a[k] = obj[k], a), {}) +} + +module.exports = { + dfn, + last, + lookup, + select +}; diff --git a/test/Utils/MochaTruffle.js b/test/Utils/MochaTruffle.js new file mode 100644 index 000000000..75d5f49f1 --- /dev/null +++ b/test/Utils/MochaTruffle.js @@ -0,0 +1,266 @@ +"use strict"; + +const BigNum = require('bignumber.js'); +const ethers = require('ethers'); + +const {ComptrollerErr, TokenErr, IRErr, MathErr} = require('../Errors'); +const { + last, + lookup, + select +} = require('./JS'); + +async function asIfTesting(env = global) { + // Use this from a nodejs-repl, or something, to get a setup like tests have + const Config = require('truffle-config'); + const Resolver = require('truffle-resolver'); + const TestSource = require('truffle-core/lib/testing/testsource'); + const TestResolver = require('truffle-core/lib/testing/testresolver'); + const config = Config.detect(); + config.network = 'development'; + config.resolver = new Resolver(config); + + const test_source = new TestSource(config); + const test_resolver = new TestResolver(config.resolver, test_source, config.contracts_build_directory); + + env.web3 = new (require('web3'))(config.provider); + env.accounts = await env.web3.eth.getAccounts(); + env.artifacts = test_resolver; + env.artifacts.reset = () => Object.keys(env.artifacts.require_cache).map(k => delete env.artifacts.require_cache[k]); + env.config = config; + return env; +} + +const assert = Object.assign(global.assert || require('assert'), { + addressZero: (actual) => { + assert.equal(actual, address(0), `expected ${address(0)}, but got ${actual}`); + }, + + each: (assertion, actuals, expecteds, reason) => { + actuals.forEach((actual, i) => assert[assertion](actual, expecteds[i], reason)); + }, + + hasTrollError: (actual, expectedErrorName) => assert.hasError(actual, expectedErrorName, ComptrollerErr), + hasTokenError: (actual, expectedErrorName) => assert.hasError(actual, expectedErrorName, TokenErr), + hasError: (actual, expectedErrorName, reporter=TokenErr) => { + let actualErrorCode = actual instanceof Object ? actual[0] : actual; + assert.equal(actualErrorCode, reporter.Error[expectedErrorName], `expected Error.${expectedErrorName}, instead got Error.${reporter.ErrorInv[actualErrorCode]}`); + }, + + hasLog: (result, event, params) => { + const events = result.events; + const log = lookup(events, event); + if (!log) + assert.fail(0, 1, `expected log with event '${event}', found logs with events: ${Object.keys(events)}`); + assert.partEqual(log.returnValues, params); + }, + + hasNoLog: (result, event) => { + assert.equal(lookup(result.events, event), null); + }, + + hasTrollFailure: (result, err, info, detail=undefined) => assert.hasFailure(result, err, info, detail, ComptrollerErr), + hasTokenFailure: (result, err, info, detail=undefined) => assert.hasFailure(result, err, info, detail, TokenErr), + hasFailure: (result, expectedError, expectedInfo, expectedDetail=undefined, reporter=TokenErr) => { + const events = result.events; + const log = last(events['Failure']); + if (!log) + assert.fail(0, 1, `expected failure, but none found, founds logs with events: ${Object.keys(events)}`); + const ret = log.returnValues; + assert.equal(ret.error, reporter.Error[expectedError], `expected Error.${expectedError} (FailureInfo.${expectedInfo}), instead got Error.${reporter.ErrorInv[ret.error]} (FailureInfo.${reporter.FailureInfoInv[ret.info]}) [${ret.detail}]`); + assert.equal(ret.info, reporter.FailureInfo[expectedInfo], `expected (Error.${expectedError}) FailureInfo.${expectedInfo}, instead got (Error.${reporter.ErrorInv[ret.error]}) FailureInfo.${reporter.FailureInfoInv[ret.info]} [${ret.detail}]`); + if (expectedDetail !== undefined) + assert.equal(ret.detail, expectedDetail); + }, + + hasTokenMathFail: (result, info, detail) => { + assert.hasTokenFailure(result, 'MATH_ERROR', info, detail && (MathErr.Error[detail] || -1)); + }, + + hasTrollReject: (result, info, detail) => { + assert.hasTokenFailure(result, 'COMPTROLLER_REJECTION', info, detail && ComptrollerErr.Error[detail]); + }, + + hasIRErrorTuple: (result, tuple) => assert.hasErrorTuple(result, tuple, IRErr), + hasMathErrorTuple: (result, tuple) => assert.hasErrorTuple(result, tuple, MathErr), + hasTrollErrorTuple: (result, tuple) => assert.hasErrorTuple(result, tuple, ComptrollerErr), + hasTokenErrorTuple: (result, tuple) => assert.hasErrorTuple(result, tuple, TokenErr), + hasErrorTuple: (result, tuple, reporter=TokenErr) => { + assert.hasError(result[0], tuple[0], reporter); + assert.like(result[1], tuple[1]); + if (tuple[2] !== undefined) + assert.like(result[2], tuple[2]); + }, + + like: (actual, expected, reason) => { + if (typeof(expected) == 'function') + return expected(actual, reason); + assert.equal(actual, expected, reason); + }, + + numEqual: (actual, expected, reason) => { + assert.equal(actual.toString(), expected.toString(), reason); + }, + + numNotEqual: (actual, expected, reason) => { + assert.notEqual(actual.toString(), expected.toString(), reason); + }, + + partEqual: (actual, partial, reason) => { + assert.deepEqual(select(actual, Object.keys(partial)), partial, reason); + }, + + revert: async (trx, reason='revert') => { + // coverage tests don't currently support checking full message given with a revert + let result; + try { + result = await trx; + } catch (err) { + assert.equal(err.message, `Returned error: VM Exception while processing transaction: ${reason}`); + return; + } + assert.fail(0, 1, `expected revert, instead got result: ${JSON.stringify(result)}`); + }, + + revertWithError: async (trx, expectedErrorName, reason='revert', reporter=TokenErr) => { + assert.revert(trx, `${reason} (${reporter.Error[expectedErrorName].padStart(2, '0')})`) + }, + + succeeds: async (contract, method, args = [], opts = [], reporter=TokenErr) => { + const {reply, receipt} = await both(contract, method, args, opts); + assert.success(receipt); + assert.hasError(reply, 'NO_ERROR', reporter); + }, + + tokenSuccess: (result) => assert.success(result, TokenErr), + trollSuccess: (result) => assert.success(result, ComptrollerErr), + success: (result, reporter=TokenErr) => { + const events = result.events; + if (events['Failure']) { + const failure = last(events['Failure']); + const error = reporter.ErrorInv[failure.returnValues[0]]; + const failureInfo = reporter.FailureInfoInv[failure.returnValues[1]]; + let detail = failure.returnValues[2]; + if (detail && error == 'MATH_ERROR') + detail = MathErr.ErrorInv[detail]; + assert.fail(0, 1, `expected success, instead got failure: ${JSON.stringify(failure)} (Error: ${error}, FailureInfo: ${failureInfo}, Detail: ${detail})`) + } + return result; + } +}); + +function address(n) { + return `0x${(n).toString(16).padStart(40, '0')}`; +} + +async function etherBalance(addr) { + return ethers.utils.bigNumberify(new BigNum(await web3.eth.getBalance(addr)).toFixed()); +} + +async function etherGasCost(receipt) { + const tx = await web3.eth.getTransaction(receipt.transactionHash); + const gasUsed = new BigNum(receipt.gasUsed); + const gasPrice = new BigNum(tx.gasPrice); + return ethers.utils.bigNumberify(gasUsed.times(gasPrice).toFixed()); +} + +function etherMantissa(num) { + if (num < 0) + return ethers.utils.bigNumberify(new BigNum(2).pow(256).plus(num).toFixed()); + return ethers.utils.bigNumberify(new BigNum(num).times(1e18).toFixed()); +} + +function etherUnsigned(num) { + return ethers.utils.bigNumberify(new BigNum(num).toFixed()); +} + +function getContractDefaults() { + if (process.env.NETWORK === 'coverage') + return {gas: 0xfffffffffff, gasPrice: 1}; + return {gas: 20000000, gasPrice: 20000}; +} + +function getContract(name, opts = getContractDefaults()) { + const code = artifacts.require(name); + const contract = new web3.eth.Contract(code._json.abi, null, {data: code._json.bytecode, ...opts}); + contract.at = (addr) => { + return new web3.eth.Contract(code._json.abi, addr, {data: code._json.bytecode, ...opts}); + } + return contract; +} + +function getTestContract(name, opts) { + return getContract(name, opts); +} + +async function guessRoot() { + if (!global.accounts) + global.accounts = await web3.eth.getAccounts(); + return accounts[0]; +} + +async function minerStart() { + return rpc({method: 'miner_start'}); +} + +async function minerStop() { + return rpc({method: 'miner_stop'}); +} + +async function rpc(request) { + return new Promise((okay, fail) => web3.currentProvider.send(request, (err, res) => err ? fail(err) : okay(res))); +} + +async function both(contract, method, args = [], opts = {}) { + const reply = await call(contract, method, args, opts); + const receipt = await send(contract, method, args, opts); + return {reply, receipt}; +} + +async function call(contract, method, args = [], opts = {}) { + const { + from = await guessRoot(), + ...etc + } = opts || {}; + return contract.methods[method](...args).call({from, ...etc}); +} + +async function callUnsigned(contract, method, args = [], opts = {}) { + return etherUnsigned(await call(contract, method, args, opts)); +} + +async function send(contract, method, args = [], opts = {}) { + const { + from = await guessRoot(), + ...etc + } = opts || {}; + return contract.methods[method](...args).send({from, ...etc}); +} + +async function sendFallback(contract, opts = {}) { + const receipt = await web3.eth.sendTransaction({to: contract._address, ...opts}); + return Object.assign(receipt, {events: receipt.logs}); +} + +module.exports = { + asIfTesting, + assert, + address, + etherBalance, + etherGasCost, + etherMantissa, + etherUnsigned, + getContract, + getTestContract, + guessRoot, + + minerStart, + minerStop, + rpc, + + both, + call, + callUnsigned, + send, + sendFallback +}; diff --git a/test/contracts/BasicToken.sol b/test/contracts/BasicToken.sol new file mode 100644 index 000000000..f671d1164 --- /dev/null +++ b/test/contracts/BasicToken.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.5.8; + + +import "./ERC20Basic.sol"; +import "./SafeMath.sol"; + + +/** + * @title Basic token + * @dev Basic version of StandardToken, with no allowances. + */ +contract BasicToken is ERC20Basic { + using SafeMath for uint256; + + mapping(address => uint256) balances; + + uint256 totalSupply_; + + /** + * @dev Total number of tokens in existence + */ + function totalSupply() public view returns (uint256) { + return totalSupply_; + } + + /** + * @dev Transfer token for a specified address + * @param _to The address to transfer to. + * @param _value The amount to be transferred. + */ + function transfer(address _to, uint256 _value) public returns (bool) { + require(_to != address(0)); + require(_value <= balances[msg.sender]); + + balances[msg.sender] = balances[msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + emit Transfer(msg.sender, _to, _value); + return true; + } + + /** + * @dev Gets the balance of the specified address. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address _owner) public view returns (uint256) { + return balances[_owner]; + } + +} \ No newline at end of file diff --git a/test/contracts/BasicTokenNS.sol b/test/contracts/BasicTokenNS.sol new file mode 100644 index 000000000..97bac6af0 --- /dev/null +++ b/test/contracts/BasicTokenNS.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.5.8; + + +import "./ERC20BasicNS.sol"; +import "./SafeMath.sol"; + +/** + * @title Basic token (Non-Standard) + * @dev Basic version of NonStandardToken, with no allowances. + * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` + * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ +contract BasicTokenNS is ERC20BasicNS { + using SafeMath for uint256; + + mapping(address => uint256) balances; + + uint256 totalSupply_; + + /** + * @dev Total number of tokens in existence + */ + function totalSupply() public view returns (uint256) { + return totalSupply_; + } + + /** + * @dev Transfer token for a specified address + * @param _to The address to transfer to. + * @param _value The amount to be transferred. + */ + function transfer(address _to, uint256 _value) public { + require(_to != address(0)); + require(_value <= balances[msg.sender]); + + balances[msg.sender] = balances[msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + emit Transfer(msg.sender, _to, _value); + } + + /** + * @dev Gets the balance of the specified address. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address _owner) public view returns (uint256) { + return balances[_owner]; + } + +} \ No newline at end of file diff --git a/test/contracts/BoolComptroller.sol b/test/contracts/BoolComptroller.sol new file mode 100644 index 000000000..d788f9d87 --- /dev/null +++ b/test/contracts/BoolComptroller.sol @@ -0,0 +1,278 @@ +pragma solidity ^0.5.8; + +import "../ComptrollerInterface.sol"; + +contract BoolComptroller is ComptrollerInterface { + bool public isComptroller = true; + + bool allowMint = true; + bool allowRedeem = true; + bool allowBorrow = true; + bool allowRepayBorrow = true; + bool allowLiquidateBorrow = true; + bool allowSeize = true; + bool allowTransfer = true; + + bool verifyMint = true; + bool verifyRedeem = true; + bool verifyBorrow = true; + bool verifyRepayBorrow = true; + bool verifyLiquidateBorrow = true; + bool verifySeize = true; + bool verifyTransfer = true; + + bool failCalculateSeizeTokens; + uint calculatedSeizeTokens; + + uint noError = 0; + uint opaqueError = noError + 11; // an arbitrary, opaque error code + + /*** Assets You Are In ***/ + + function enterMarkets(address[] calldata _cTokens) external returns (uint[] memory) { + _cTokens; + uint[] memory ret; + return ret; + } + + function exitMarket(address _cToken) external returns (uint) { + _cToken; + return noError; + } + + /*** Policy Hooks ***/ + + function mintAllowed(address _cToken, address _minter, uint _mintAmount) public returns (uint) { + _cToken; + _minter; + _mintAmount; + return allowMint ? noError : opaqueError; + } + + function mintVerify(address _cToken, address _minter, uint _mintAmount, uint _mintTokens) external { + _cToken; + _minter; + _mintAmount; + _mintTokens; + require(verifyMint, "mintVerify rejected mint"); + } + + function redeemAllowed(address _cToken, address _redeemer, uint _redeemTokens) public returns (uint) { + _cToken; + _redeemer; + _redeemTokens; + return allowRedeem ? noError : opaqueError; + } + + function redeemVerify(address _cToken, address _redeemer, uint _redeemAmount, uint _redeemTokens) external { + _cToken; + _redeemer; + _redeemAmount; + _redeemTokens; + require(verifyRedeem, "redeemVerify rejected redeem"); + } + + function borrowAllowed(address _cToken, address _borrower, uint _borrowAmount) public returns (uint) { + _cToken; + _borrower; + _borrowAmount; + return allowBorrow ? noError : opaqueError; + } + + function borrowVerify(address _cToken, address _borrower, uint _borrowAmount) external { + _cToken; + _borrower; + _borrowAmount; + require(verifyBorrow, "borrowVerify rejected borrow"); + } + + function repayBorrowAllowed( + address _cToken, + address _payer, + address _borrower, + uint _repayAmount) public returns (uint) { + _cToken; + _payer; + _borrower; + _repayAmount; + return allowRepayBorrow ? noError : opaqueError; + } + + function repayBorrowVerify( + address _cToken, + address _payer, + address _borrower, + uint _repayAmount, + uint _borrowerIndex) external { + _cToken; + _payer; + _borrower; + _repayAmount; + _borrowerIndex; + require(verifyRepayBorrow, "repayBorrowVerify rejected repayBorrow"); + } + + function liquidateBorrowAllowed( + address _cTokenBorrowed, + address _cTokenCollateral, + address _liquidator, + address _borrower, + uint _repayAmount) public returns (uint) { + _cTokenBorrowed; + _cTokenCollateral; + _liquidator; + _borrower; + _repayAmount; + return allowLiquidateBorrow ? noError : opaqueError; + } + + function liquidateBorrowVerify( + address _cTokenBorrowed, + address _cTokenCollateral, + address _liquidator, + address _borrower, + uint _repayAmount, + uint _seizeTokens) external { + _cTokenBorrowed; + _cTokenCollateral; + _liquidator; + _borrower; + _repayAmount; + _seizeTokens; + require(verifyLiquidateBorrow, "liquidateBorrowVerify rejected liquidateBorrow"); + } + + function seizeAllowed( + address _cTokenCollateral, + address _cTokenBorrowed, + address _borrower, + address _liquidator, + uint _seizeTokens) public returns (uint) { + _cTokenCollateral; + _cTokenBorrowed; + _liquidator; + _borrower; + _seizeTokens; + return allowSeize ? noError : opaqueError; + } + + function seizeVerify( + address _cTokenCollateral, + address _cTokenBorrowed, + address _liquidator, + address _borrower, + uint _seizeTokens) external { + _cTokenCollateral; + _cTokenBorrowed; + _liquidator; + _borrower; + _seizeTokens; + require(verifySeize, "seizeVerify rejected seize"); + } + + function transferAllowed( + address _cToken, + address _src, + address _dst, + uint _transferTokens) public returns (uint) { + _cToken; + _src; + _dst; + _transferTokens; + return allowTransfer ? noError : opaqueError; + } + + function transferVerify( + address _cToken, + address _src, + address _dst, + uint _transferTokens) external { + _cToken; + _src; + _dst; + _transferTokens; + require(verifyTransfer, "transferVerify rejected transfer"); + } + + /*** Special Liquidation Calculation ***/ + + function liquidateCalculateSeizeTokens( + address _cTokenBorrowed, + address _cTokenCollateral, + uint _repayAmount) public view returns (uint, uint) { + _cTokenBorrowed; + _cTokenCollateral; + _repayAmount; + return failCalculateSeizeTokens ? (opaqueError, 0) : (noError, calculatedSeizeTokens); + } + + /**** Mock Settors ****/ + + /*** Policy Hooks ***/ + + function setMintAllowed(bool allowMint_) public { + allowMint = allowMint_; + } + + function setMintVerify(bool verifyMint_) public { + verifyMint = verifyMint_; + } + + function setRedeemAllowed(bool allowRedeem_) public { + allowRedeem = allowRedeem_; + } + + function setRedeemVerify(bool verifyRedeem_) public { + verifyRedeem = verifyRedeem_; + } + + function setBorrowAllowed(bool allowBorrow_) public { + allowBorrow = allowBorrow_; + } + + function setBorrowVerify(bool verifyBorrow_) public { + verifyBorrow = verifyBorrow_; + } + + function setRepayBorrowAllowed(bool allowRepayBorrow_) public { + allowRepayBorrow = allowRepayBorrow_; + } + + function setRepayBorrowVerify(bool verifyRepayBorrow_) public { + verifyRepayBorrow = verifyRepayBorrow_; + } + + function setLiquidateBorrowAllowed(bool allowLiquidateBorrow_) public { + allowLiquidateBorrow = allowLiquidateBorrow_; + } + + function setLiquidateBorrowVerify(bool verifyLiquidateBorrow_) public { + verifyLiquidateBorrow = verifyLiquidateBorrow_; + } + + function setSeizeAllowed(bool allowSeize_) public { + allowSeize = allowSeize_; + } + + function setSeizeVerify(bool verifySeize_) public { + verifySeize = verifySeize_; + } + + function setTransferAllowed(bool allowTransfer_) public { + allowTransfer = allowTransfer_; + } + + function setTransferVerify(bool verifyTransfer_) public { + verifyTransfer = verifyTransfer_; + } + + /*** Liquidity/Liquidation Calculations ***/ + + function setCalculatedSeizeTokens(uint seizeTokens_) public { + calculatedSeizeTokens = seizeTokens_; + } + + function setFailCalculateSeizeTokens(bool shouldFail) public { + failCalculateSeizeTokens = shouldFail; + } +} diff --git a/test/contracts/CErc20Harness.sol b/test/contracts/CErc20Harness.sol new file mode 100644 index 000000000..2657096ee --- /dev/null +++ b/test/contracts/CErc20Harness.sol @@ -0,0 +1,187 @@ +pragma solidity ^0.5.8; + +import "../CErc20.sol"; + +contract CErc20Harness is CErc20 { + + uint blockNumber = 100000; + uint harnessExchangeRate; + bool harnessExchangeRateStored; + + /* + To support testing, we allow the contract to always fail `transfer`. + */ + mapping (address => bool) public failTransferToAddresses; + + constructor(address underlying_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa, + string memory name_, + string memory symbol_, + uint decimals_) + CErc20( + underlying_, + comptroller_, + interestRateModel_, + initialExchangeRateMantissa, + name_, + symbol_, + decimals_) public {} + + /** + * Fresh + * + */ + function getBlockNumber() internal view returns (uint) { + return blockNumber; + } + + function harnessSetBlockNumber(uint newBlockNumber) public { + blockNumber = newBlockNumber; + } + + function harnessFastForward(uint blocks) public { + blockNumber += blocks; + } + + /** + * Account Balances + * + */ + function harnessSetBalance(address account, uint amount) external { + accountTokens[account] = amount; + } + + /** + * Accrual Block Number + */ + function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public { + accrualBlockNumber = _accrualblockNumber; + } + + /** + * Exchange Rate + * + */ + function harnessSetTotalSupply(uint totalSupply_) public { + totalSupply = totalSupply_; + } + + function harnessSetTotalBorrows(uint totalBorrows_) public { + totalBorrows = totalBorrows_; + } + + function harnessSetTotalReserves(uint totalReserves_) public { + totalReserves = totalReserves_; + } + + function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public { + totalSupply = totalSupply_; + totalBorrows = totalBorrows_; + totalReserves = totalReserves_; + } + + function harnessSetExchangeRate(uint exchangeRate) public { + harnessExchangeRate = exchangeRate; + harnessExchangeRateStored = true; + } + + function exchangeRateStoredInternal() internal view returns (MathError, uint) { + if (harnessExchangeRateStored) { + return (MathError.NO_ERROR, harnessExchangeRate); + } + + return super.exchangeRateStoredInternal(); + } + + /** + * Transfer Harness methods + * + */ + + /** + * @dev Specify `address, true` to cause transfers to address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferToAddress(address _to, bool _fail) public { + failTransferToAddresses[_to] = _fail; + } + + function doTransferOut(address payable to, uint amount) internal returns (Error) { + if (failTransferToAddresses[to]) { + return Error.TOKEN_TRANSFER_OUT_FAILED; + } + return super.doTransferOut(to, amount); + } + + /** + * Spearmint? Nah, fresh mint. + * + */ + function harnessMintFresh(address account, uint mintAmount) public returns (uint) { + return super.mintFresh(account, mintAmount); + } + + /** + * Redemption + * + */ + function harnessRedeemFresh(address payable account, uint cTokenAmount, uint underlyingAmount) public returns (uint) { + return super.redeemFresh(account, cTokenAmount, underlyingAmount); + } + + /** + * Borrowing + * + */ + function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) { + BorrowSnapshot memory snapshot = accountBorrows[account]; + return (snapshot.principal, snapshot.interestIndex); + } + + function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public { + accountBorrows[account] = BorrowSnapshot({principal: principal, interestIndex: interestIndex}); + } + + function harnessSetBorrowIndex(uint borrowIndex_) public { + borrowIndex = borrowIndex_; + } + + function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) { + return borrowFresh(account, borrowAmount); + } + + function harnessRepayBorrowFresh(address payer, address account, uint borrowAmount) public returns (uint) { + return repayBorrowFresh(payer, account, borrowAmount); + } + + function harnessLiquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CToken cTokenCollateral) public returns (uint) { + return liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); + } + + /** + * Admin + * + */ + function harnessReduceReservesFresh(uint amount) public returns (uint) { + return _reduceReservesFresh(amount); + } + + function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) { + return _setReserveFactorFresh(newReserveFactorMantissa); + } + + function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) public returns (uint) { + return _setInterestRateModelFresh(newInterestRateModel); + } + + /** + * @dev set the interest rate model directly, with no interest accrual and no checks + * Intended for linking in FailableInterestRateModel to create failures in accrueInterest + */ + function harnessSetInterestRateModel(address newInterestRateModelAddress) public { + interestRateModel = InterestRateModel(newInterestRateModelAddress); + } +} diff --git a/test/contracts/CErc20Scenario.sol b/test/contracts/CErc20Scenario.sol new file mode 100644 index 000000000..408bf04b3 --- /dev/null +++ b/test/contracts/CErc20Scenario.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.5.8; + +import "../CErc20.sol"; +import "./ComptrollerScenario.sol"; + +contract CErc20Scenario is CErc20 { + constructor(address underlying_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa, + string memory name_, + string memory symbol_, + uint decimals_) + CErc20( + underlying_, + comptroller_, + interestRateModel_, + initialExchangeRateMantissa, + name_, + symbol_, + decimals_) public {} + + function setTotalBorrows(uint totalBorrows_) public { + totalBorrows = totalBorrows_; + } + + function setTotalReserves(uint totalReserves_) public { + totalReserves = totalReserves_; + } + + /** + * @dev Function to simply retrieve block number + * This exists mainly for inheriting test contracts to stub this result. + */ + function getBlockNumber() internal view returns (uint) { + ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller)); + + return comptrollerScenario.blockNumber(); + } +} diff --git a/test/contracts/CEtherHarness.sol b/test/contracts/CEtherHarness.sol new file mode 100644 index 000000000..6b25cceca --- /dev/null +++ b/test/contracts/CEtherHarness.sol @@ -0,0 +1,207 @@ +pragma solidity ^0.5.8; + +import "../CEther.sol"; + +contract CEtherHarness is CEther { + + uint harnessExchangeRate; + uint public blockNumber = 100000; + + /* + To support testing, we allow the contract to always fail `transfer`. + */ + mapping (address => bool) public failTransferToAddresses; + + constructor(ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa, + string memory name_, + string memory symbol_, + uint decimals_) + CEther( + comptroller_, + interestRateModel_, + initialExchangeRateMantissa, + name_, + symbol_, + decimals_) public {} + + /** + * Fresh + * + */ + function getBlockNumber() internal view returns (uint) { + return blockNumber; + } + + function harnessSetBlockNumber(uint newBlockNumber) public { + blockNumber = newBlockNumber; + } + + function harnessFastForward(uint blocks) public { + blockNumber += blocks; + } + + /** + * Account Balances + * + */ + function harnessSetBalance(address account, uint amount) external { + accountTokens[account] = amount; + } + + /** + * Accrual Block Number + */ + function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public { + accrualBlockNumber = _accrualblockNumber; + } + + /** + * Exchange Rate + * + */ + function harnessSetTotalSupply(uint totalSupply_) public { + totalSupply = totalSupply_; + } + + function harnessSetTotalBorrows(uint totalBorrows_) public { + totalBorrows = totalBorrows_; + } + + function harnessSetTotalReserves(uint totalReserves_) public { + totalReserves = totalReserves_; + } + + function harnessExchangeRateDetails(uint _totalSupply, uint _totalBorrows, uint _totalReserves) public { + totalSupply = _totalSupply; + totalBorrows = _totalBorrows; + totalReserves = _totalReserves; + } + + function harnessSetExchangeRate(uint exchangeRate) public { + harnessExchangeRate = exchangeRate; + } + + function exchangeRateStoredInternal() internal view returns (MathError, uint) { + if (harnessExchangeRate != 0) { + return (MathError.NO_ERROR, harnessExchangeRate); + } + + return super.exchangeRateStoredInternal(); + } + + /** + * Transfer Harness methods + * + */ + + /** + * @dev Specify `address, true` to cause transfers to address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferToAddress(address _to, bool _fail) public { + failTransferToAddresses[_to] = _fail; + } + + function doTransferOut(address payable to, uint amount) internal returns (Error) { + if (failTransferToAddresses[to]) { + return Error.TOKEN_TRANSFER_OUT_FAILED; + } + return super.doTransferOut(to, amount); + } + + /** + * Spearmint? Nah, fresh mint. + * + */ + function harnessMintFresh(address account, uint mintAmount) public returns (uint) { + return super.mintFresh(account, mintAmount); + } + + /** + * Redemption + * + */ + function harnessRedeemFresh(address payable account, uint cTokenAmount, uint underlyingAmount) public returns (uint) { + return super.redeemFresh(account, cTokenAmount, underlyingAmount); + } + + /** + * Borrowing + * + */ + function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) { + BorrowSnapshot memory snapshot = accountBorrows[account]; + return (snapshot.principal, snapshot.interestIndex); + } + + function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public { + accountBorrows[account] = BorrowSnapshot({principal: principal, interestIndex: interestIndex}); + } + + function harnessSetBorrowIndex(uint borrowIndex_) public { + borrowIndex = borrowIndex_; + } + + function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) { + return borrowFresh(account, borrowAmount); + } + + function harnessRepayBorrowFresh(address payer, address account, uint borrowAmount) public payable returns (uint) { + return repayBorrowFresh(payer, account, borrowAmount); + } + + function harnessLiquidateBorrowFresh(address liquidator, address borrower, uint repayAmount, CToken cTokenCollateral) public returns (uint) { + return liquidateBorrowFresh(liquidator, borrower, repayAmount, cTokenCollateral); + } + /** + * Admin + * + */ + function harnessReduceReservesFresh(uint amount) public returns (uint) { + return _reduceReservesFresh(amount); + } + + function harnessSetReserves(uint amount) public { + totalReserves = amount; + } + + function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) { + return _setReserveFactorFresh(newReserveFactorMantissa); + } + + function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) public returns (uint) { + return _setInterestRateModelFresh(newInterestRateModel); + } + + /** + * @dev set the interest rate model directly, with no interest accrual and no checks + * Intended for linking in FailableInterestRateModel to create failures in accrueInterest + */ + function harnessSetInterestRateModel(address newInterestRateModelAddress) public { + interestRateModel = InterestRateModel(newInterestRateModelAddress); + } + + /** safe token harnes **/ + function harnessGetCashPrior() public payable returns (uint) { + return getCashPrior(); + } + + function harnessDoTransferIn(address from, uint amount) public payable returns (uint) { + return uint(doTransferIn(from, amount)); + } + + function harnessDoTransferOut(address payable to, uint amount) public payable returns (uint) { + return uint(doTransferOut(to, amount)); + } + + function harnessCheckTransferIn(address from, uint amount) external payable returns (uint) { + return uint(checkTransferIn(from, amount)); + } + + function harnessRequireNoError(uint error, string calldata message) external pure { + requireNoError(error, message); + } +} diff --git a/test/contracts/CEtherScenario.sol b/test/contracts/CEtherScenario.sol new file mode 100644 index 000000000..3e10b6e7a --- /dev/null +++ b/test/contracts/CEtherScenario.sol @@ -0,0 +1,44 @@ +pragma solidity ^0.5.8; + +import "../CEther.sol"; +import "./ComptrollerScenario.sol"; + +contract CEtherScenario is CEther { + uint reserveFactor; + + constructor(string memory name_, + string memory symbol_, + uint8 decimals_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa) + CEther(comptroller_, + interestRateModel_, + initialExchangeRateMantissa, + name_, + symbol_, + decimals_) public { + } + + function setTotalBorrows(uint totalBorrows_) public { + totalBorrows = totalBorrows_; + } + + function setTotalReserves(uint totalReserves_) public { + totalReserves = totalReserves_; + } + + function donate() public payable { + // no-op + } + + /** + * @dev Function to simply retrieve block number + * This exists mainly for inheriting test contracts to stub this result. + */ + function getBlockNumber() internal view returns (uint) { + ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller)); + + return comptrollerScenario.blockNumber(); + } +} diff --git a/test/contracts/CEvil.sol b/test/contracts/CEvil.sol new file mode 100644 index 000000000..0490a4977 --- /dev/null +++ b/test/contracts/CEvil.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.5.8; + +import "./CErc20Scenario.sol"; + +contract CEvil is CErc20Scenario { + constructor(address underlying_, + ComptrollerInterface comptroller_, + InterestRateModel interestRateModel_, + uint initialExchangeRateMantissa, + string memory name_, + string memory symbol_, + uint decimals_) + CErc20Scenario( + underlying_, + comptroller_, + interestRateModel_, + initialExchangeRateMantissa, + name_, + symbol_, + decimals_) public {} + + function evilSeize(CToken treasure, address liquidator, address borrower, uint seizeTokens) public returns (uint) { + return treasure.seize(liquidator, borrower, seizeTokens); + } +} diff --git a/test/contracts/ComptrollerBorked.sol b/test/contracts/ComptrollerBorked.sol new file mode 100644 index 000000000..188960293 --- /dev/null +++ b/test/contracts/ComptrollerBorked.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.8; + +import "../Comptroller.sol"; +import "../PriceOracle.sol"; + +contract ComptrollerBorked { + + function _become(Unitroller unitroller, PriceOracle _oracle, uint _closeFactorMantissa, uint _maxAssets, bool _reinitializing) public { + _oracle; + _closeFactorMantissa; + _maxAssets; + _reinitializing; + + require(msg.sender == unitroller.admin(), "only unitroller admin can change brains"); + unitroller._acceptImplementation(); + } + +} diff --git a/test/contracts/ComptrollerHarness.sol b/test/contracts/ComptrollerHarness.sol new file mode 100644 index 000000000..182a673a5 --- /dev/null +++ b/test/contracts/ComptrollerHarness.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.8; + +import "../Comptroller.sol"; +import "../PriceOracle.sol"; + +contract ComptrollerHarness is Comptroller { + constructor() Comptroller() public {} + + function getHypotheticalAccountLiquidity( + address account, + address cTokenModify, + uint redeemTokens, + uint borrowAmount) public view returns (uint, uint, uint) { + (Error err, uint liquidity, uint shortfall) = + super.getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); + return (uint(err), liquidity, shortfall); + } +} diff --git a/test/contracts/ComptrollerScenario.sol b/test/contracts/ComptrollerScenario.sol new file mode 100644 index 000000000..4e3198e49 --- /dev/null +++ b/test/contracts/ComptrollerScenario.sol @@ -0,0 +1,48 @@ +pragma solidity ^0.5.8; + +import "../Comptroller.sol"; +import "../PriceOracle.sol"; + +contract ComptrollerScenario is Comptroller { + uint public blockNumber; + + constructor() Comptroller() public {} + + function membershipLength(CToken cToken) public view returns (uint) { + return accountAssets[address(cToken)].length; + } + + function fastForward(uint blocks) public returns (uint) { + blockNumber += blocks; + + return blockNumber; + } + + function setBlockNumber(uint number) public { + blockNumber = number; + } + + function _become(Unitroller unitroller, PriceOracle _oracle, uint _closeFactorMantissa, uint _maxAssets, bool reinitializing) public { + super._become(unitroller, _oracle, _closeFactorMantissa, _maxAssets, reinitializing); + + if (!reinitializing) { + ComptrollerScenario freshBrainedComptroller = ComptrollerScenario(address(unitroller)); + + freshBrainedComptroller.setBlockNumber(100000); + } + } + + function getHypotheticalAccountLiquidity( + address account, + address cTokenModify, + uint redeemTokens, + uint borrowAmount) public view returns (uint, uint, uint) { + (Error err, uint liquidity, uint shortfall) = + super.getHypotheticalAccountLiquidityInternal(account, CToken(cTokenModify), redeemTokens, borrowAmount); + return (uint(err), liquidity, shortfall); + } + + function unlist(CToken cToken) public { + markets[address(cToken)].isListed = false; + } +} diff --git a/test/contracts/DSValueHarness.sol b/test/contracts/DSValueHarness.sol new file mode 100644 index 000000000..c9ab2f933 --- /dev/null +++ b/test/contracts/DSValueHarness.sol @@ -0,0 +1,32 @@ +// Abstract contract for the full DSValue standard +// -- +pragma solidity ^0.5.8; + +contract DSValueHarness { + bool public has; + bytes32 public val; + + constructor(bytes32 initVal) public { + if (initVal != 0) { + has = true; + val = initVal; + } + } + + function peek() public view returns (bytes32, bool) { + return (val, has); + } + + function read() public view returns (bytes32) { + return val; + } + + function set(bytes32 _val) public { + val = _val; + has = true; + } + + function unset() public { + has = false; + } +} \ No newline at end of file diff --git a/test/contracts/EIP20Harness.sol b/test/contracts/EIP20Harness.sol new file mode 100644 index 000000000..d67ce8328 --- /dev/null +++ b/test/contracts/EIP20Harness.sol @@ -0,0 +1,123 @@ +/* +Implements EIP20 token standard: https://github.com/ethereum/EIPs/issues/20 +.*/ + +pragma solidity ^0.5.8; + +import "../EIP20Interface.sol"; + +contract EIP20Harness is EIP20Interface { + + uint256 constant private MAX_UINT256 = 2**256 - 1; + uint256 public totalSupply; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + + /* + To support testing, we can specify addresses for which transferFrom should fail and return false. + See `harnessSetFailTransferFromAddress` + */ + mapping (address => bool) public failTransferFromAddresses; + + /* + To support testing, we allow the contract to always fail `transfer`. + */ + mapping (address => bool) public failTransferToAddresses; + + + /* + NOTE: + The following variables are OPTIONAL vanities. One does not have to include them. + They allow one to customise the token contract & in no way influences the core functionality. + Some wallets/interfaces might not even bother to look at this information. + */ + string public name; //fancy name: eg Simon Bucks + uint8 public decimals; //How many decimals to show. + string public symbol; //An identifier: eg SBX + + constructor( + uint256 _initialAmount, + string memory _tokenName, + uint8 _decimalUnits, + string memory _tokenSymbol + ) public { + balances[msg.sender] = _initialAmount; // Give the creator all initial tokens + totalSupply = _initialAmount; // Update total supply + name = _tokenName; // Set the name for display purposes + decimals = _decimalUnits; // Amount of decimals for display purposes + symbol = _tokenSymbol; // Set the symbol for display purposes + } + + + /** + * @dev Specify `address, true` to cause transfers from address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferFromAddress(address _from, bool _fail) public { + failTransferFromAddresses[_from] = _fail; + } + + /** + * @dev Specify `address, true` to cause transfers to address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferToAddress(address _to, bool _fail) public { + failTransferToAddresses[_to] = _fail; + } + + function harnessSetBalance(address _account, uint _amount) public { + balances[_account] = _amount; + } + + function transfer(address _to, uint256 _value) public returns (bool success) { + require(balances[msg.sender] >= _value); + + // Added for testing purposes + if (failTransferToAddresses[_to]) { + return false; + } + + balances[msg.sender] -= _value; + balances[_to] += _value; + emit Transfer(msg.sender, _to, _value); + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + // Added for testing purposes + if (_from == address(0)) { + return false; + } + + // Added for testing purposes + if (failTransferFromAddresses[_from]) { + return false; + } + + uint256 allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + emit Transfer(_from, _to, _value); + return true; + } + + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } +} diff --git a/test/contracts/EIP20NonCompliantHarness.sol b/test/contracts/EIP20NonCompliantHarness.sol new file mode 100644 index 000000000..3034e15fc --- /dev/null +++ b/test/contracts/EIP20NonCompliantHarness.sol @@ -0,0 +1,27 @@ +/* +Implements `transfer` and `transferForm` with 64-bit return values, just to be +especially non-compliant and stress safe token. +.*/ + +pragma solidity ^0.5.8; + +contract EIP20NonCompliantHarness { + bool garbage; + + function transfer(address _to, uint256 _value) public returns (uint, uint) { + _to; + _value; // supress unused variable warning + garbage = false; + + return (1, 2); + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (uint, uint) { + _from; + _to; + _value; // supress unused variable warning + garbage = false; + + return (1, 2); + } +} diff --git a/test/contracts/EIP20NonStandardReturnHarness.sol b/test/contracts/EIP20NonStandardReturnHarness.sol new file mode 100644 index 000000000..2d7e46342 --- /dev/null +++ b/test/contracts/EIP20NonStandardReturnHarness.sol @@ -0,0 +1,123 @@ +/* +Implements EIP20 token standard: https://github.com/ethereum/EIPs/issues/20 +.*/ + +pragma solidity ^0.5.8; + +import "../EIP20NonStandardInterface.sol"; + +// Note: the harness here does not throw for expected errors, which allows this +// harness to be used for Solidity tests. For JavaScript tests, use: EIP20NonStandardThrowHarness. +contract EIP20NonStandardReturnHarness is EIP20NonStandardInterface { + + uint256 constant private MAX_UINT256 = 2**256 - 1; + uint256 public totalSupply; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + + /* + To support testing, we can specify addresses for which transferFrom should fail and return false. + See `harnessSetFailTransferFromAddress` + */ + mapping (address => bool) public failTransferFromAddresses; + + /* + To support testing, we allow the contract to always fail `transfer`. + */ + mapping (address => bool) public failTransferToAddresses; + + + /* + NOTE: + The following variables are OPTIONAL vanities. One does not have to include them. + They allow one to customise the token contract & in no way influences the core functionality. + Some wallets/interfaces might not even bother to look at this information. + */ + string public name; //fancy name: eg Simon Bucks + uint8 public decimals; //How many decimals to show. + string public symbol; //An identifier: eg SBX + + constructor( + uint256 _initialAmount, + string memory _tokenName, + uint8 _decimalUnits, + string memory _tokenSymbol + ) public { + balances[msg.sender] = _initialAmount; // Give the creator all initial tokens + totalSupply = _initialAmount; // Update total supply + name = _tokenName; // Set the name for display purposes + decimals = _decimalUnits; // Amount of decimals for display purposes + symbol = _tokenSymbol; // Set the symbol for display purposes + } + + + /** + * @dev Specify `address, true` to cause transfers from address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferFromAddress(address _from, bool _fail) public { + failTransferFromAddresses[_from] = _fail; + } + + /** + * @dev Specify `address, true` to cause transfers to address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferToAddress(address _to, bool _fail) public { + failTransferToAddresses[_to] = _fail; + } + + function harnessSetBalance(address _account, uint _amount) public { + balances[_account] = _amount; + } + + function transfer(address _to, uint256 _value) public { + require(balances[msg.sender] >= _value); + + // Added for testing purposes + if (failTransferToAddresses[_to]) { + return; + } + + balances[msg.sender] -= _value; + balances[_to] += _value; + emit Transfer(msg.sender, _to, _value); + } + + function transferFrom(address _from, address _to, uint256 _value) public { + // Added for testing purposes + if (_from == address(0)) { + return; + } + + // Added for testing purposes + if (failTransferFromAddresses[_from]) { + return; + } + + uint256 allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + emit Transfer(_from, _to, _value); + } + + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } +} diff --git a/test/contracts/EIP20NonStandardThrowHarness.sol b/test/contracts/EIP20NonStandardThrowHarness.sol new file mode 100644 index 000000000..e47580d3d --- /dev/null +++ b/test/contracts/EIP20NonStandardThrowHarness.sol @@ -0,0 +1,123 @@ +/* +Implements EIP20 token standard: https://github.com/ethereum/EIPs/issues/20 +.*/ + +pragma solidity ^0.5.8; + +import "../EIP20NonStandardInterface.sol"; + +// Note: the throw harness here always throws for errors, which is more realistic and useful +// for JavaScript tests. For Solidity tests, use: EIP20NonStandardReturnHarness. +contract EIP20NonStandardThrowHarness is EIP20NonStandardInterface { + + uint256 constant private MAX_UINT256 = 2**256 - 1; + uint256 public totalSupply; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + + /* + To support testing, we can specify addresses for which transferFrom should fail and return false. + See `harnessSetFailTransferFromAddress` + */ + mapping (address => bool) public failTransferFromAddresses; + + /* + To support testing, we allow the contract to always fail `transfer`. + */ + mapping (address => bool) public failTransferToAddresses; + + + /* + NOTE: + The following variables are OPTIONAL vanities. One does not have to include them. + They allow one to customise the token contract & in no way influences the core functionality. + Some wallets/interfaces might not even bother to look at this information. + */ + string public name; //fancy name: eg Simon Bucks + uint8 public decimals; //How many decimals to show. + string public symbol; //An identifier: eg SBX + + constructor( + uint256 _initialAmount, + string memory _tokenName, + uint8 _decimalUnits, + string memory _tokenSymbol + ) public { + balances[msg.sender] = _initialAmount; // Give the creator all initial tokens + totalSupply = _initialAmount; // Update total supply + name = _tokenName; // Set the name for display purposes + decimals = _decimalUnits; // Amount of decimals for display purposes + symbol = _tokenSymbol; // Set the symbol for display purposes + } + + + /** + * @dev Specify `address, true` to cause transfers from address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferFromAddress(address _from, bool _fail) public { + failTransferFromAddresses[_from] = _fail; + } + + /** + * @dev Specify `address, true` to cause transfers to address to fail. + * Once an address has been marked for failure it can be cleared by + * with `address, false` + */ + function harnessSetFailTransferToAddress(address _to, bool _fail) public { + failTransferToAddresses[_to] = _fail; + } + + function harnessSetBalance(address _account, uint _amount) public { + balances[_account] = _amount; + } + + function transfer(address _to, uint256 _value) public { + require(balances[msg.sender] >= _value); + + // Added for testing purposes + if (failTransferToAddresses[_to]) { + revert(); + } + + balances[msg.sender] -= _value; + balances[_to] += _value; + emit Transfer(msg.sender, _to, _value); + } + + function transferFrom(address _from, address _to, uint256 _value) public { + // Added for testing purposes + if (_from == address(0)) { + revert(); + } + + // Added for testing purposes + if (failTransferFromAddresses[_from]) { + revert(); + } + + uint256 allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + emit Transfer(_from, _to, _value); + } + + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } +} diff --git a/test/contracts/ERC20.sol b/test/contracts/ERC20.sol new file mode 100644 index 000000000..221983108 --- /dev/null +++ b/test/contracts/ERC20.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.5.8; + +import "./ERC20Basic.sol"; + +/** + * @title ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/20 + */ +contract ERC20 is ERC20Basic { + function allowance(address owner, address spender) public view returns (uint256); + function transferFrom(address from, address to, uint256 value) public returns (bool); + function approve(address spender, uint256 value) public returns (bool); + + event Approval(address indexed owner, address indexed spender, uint256 value); +} \ No newline at end of file diff --git a/test/contracts/ERC20Basic.sol b/test/contracts/ERC20Basic.sol new file mode 100644 index 000000000..ba4cbd4d4 --- /dev/null +++ b/test/contracts/ERC20Basic.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.5.8; + + +/** + * @title ERC20Basic + * @dev Simpler version of ERC20 interface + * See https://github.com/ethereum/EIPs/issues/179 + */ +contract ERC20Basic { + function totalSupply() public view returns (uint256); + function balanceOf(address who) public view returns (uint256); + function transfer(address to, uint256 value) public returns (bool); + event Transfer(address indexed from, address indexed to, uint256 value); +} \ No newline at end of file diff --git a/test/contracts/ERC20BasicNS.sol b/test/contracts/ERC20BasicNS.sol new file mode 100644 index 000000000..5aadeb652 --- /dev/null +++ b/test/contracts/ERC20BasicNS.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.5.8; + +/** + * @title ERC20BasicNS (Non-Standard) + * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` + * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ +contract ERC20BasicNS { + function totalSupply() public view returns (uint256); + function balanceOf(address who) public view returns (uint256); + function transfer(address to, uint256 value) public; + event Transfer(address indexed from, address indexed to, uint256 value); +} \ No newline at end of file diff --git a/test/contracts/ERC20NS.sol b/test/contracts/ERC20NS.sol new file mode 100644 index 000000000..03486c239 --- /dev/null +++ b/test/contracts/ERC20NS.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.5.8; + +import "./ERC20BasicNS.sol"; + +/** + * @title ERC20 interface (non-standard) + * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` + * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + */ +contract ERC20NS is ERC20BasicNS { + function allowance(address owner, address spender) public view returns (uint256); + function transferFrom(address from, address to, uint256 value) public; + function approve(address spender, uint256 value) public returns (bool); + + event Approval(address indexed owner, address indexed spender, uint256 value); +} \ No newline at end of file diff --git a/test/contracts/ERC20NonView.sol b/test/contracts/ERC20NonView.sol new file mode 100644 index 000000000..34abed289 --- /dev/null +++ b/test/contracts/ERC20NonView.sol @@ -0,0 +1,196 @@ +pragma solidity ^0.5.8; + +import "./SafeMath.sol"; + +/** + * @title Standard ERC20 token with nothing as a "view" + * + * @dev Implementation of the basic standard token. + * https://eips.ethereum.org/EIPS/eip-20 + * Originally based on code by FirstBlood: + * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + * + * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for + * all accounts just by listening to said events. Note that this isn't required by the specification, and other + * compliant implementations may not do it. + */ +contract ERC20NonView { + event Transfer(address indexed from, address indexed to, uint256 value); + + event Approval(address indexed owner, address indexed spender, uint256 value); + + using SafeMath for uint256; + + mapping (address => uint256) public _balances; + + mapping (address => mapping (address => uint256)) public _allowed; + + uint256 public _totalSupply; + + /** + * @dev Total number of tokens in existence + */ + function totalSupply() public returns (uint256) { + _totalSupply = _totalSupply; + return _totalSupply; + } + + /** + * @dev Gets the balance of the specified address. + * @param owner The address to query the balance of. + * @return A uint256 representing the amount owned by the passed address. + */ + function balanceOf(address owner) public returns (uint256) { + _totalSupply = _totalSupply; + return _balances[owner]; + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param owner address The address which owns the funds. + * @param spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance(address owner, address spender) public returns (uint256) { + _totalSupply = _totalSupply; + return _allowed[owner][spender]; + } + + /** + * @dev Transfer token to a specified address + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function transfer(address to, uint256 value) public returns (bool) { + _transfer(msg.sender, to, value); + return true; + } + + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param spender The address which will spend the funds. + * @param value The amount of tokens to be spent. + */ + function approve(address spender, uint256 value) public returns (bool) { + _approve(msg.sender, spender, value); + return true; + } + + /** + * @dev Transfer tokens from one address to another. + * Note that while this function emits an Approval event, this is not required as per the specification, + * and other compliant implementations may not emit the event. + * @param from address The address which you want to send tokens from + * @param to address The address which you want to transfer to + * @param value uint256 the amount of tokens to be transferred + */ + function transferFrom(address from, address to, uint256 value) public returns (bool) { + _transfer(from, to, value); + _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); + return true; + } + + /** + * @dev Increase the amount of tokens that an owner allowed to a spender. + * approve should be called when _allowed[msg.sender][spender] == 0. To increment + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * Emits an Approval event. + * @param spender The address which will spend the funds. + * @param addedValue The amount of tokens to increase the allowance by. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); + return true; + } + + /** + * @dev Decrease the amount of tokens that an owner allowed to a spender. + * approve should be called when _allowed[msg.sender][spender] == 0. To decrement + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * Emits an Approval event. + * @param spender The address which will spend the funds. + * @param subtractedValue The amount of tokens to decrease the allowance by. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); + return true; + } + + /** + * @dev Transfer token for a specified addresses + * @param from The address to transfer from. + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function _transfer(address from, address to, uint256 value) internal { + require(to != address(0)); + + _balances[from] = _balances[from].sub(value); + _balances[to] = _balances[to].add(value); + emit Transfer(from, to, value); + } + + /** + * @dev Internal function that mints an amount of the token and assigns it to + * an account. This encapsulates the modification of balances such that the + * proper events are emitted. + * @param account The account that will receive the created tokens. + * @param value The amount that will be created. + */ + function _mint(address account, uint256 value) internal { + require(account != address(0)); + + _totalSupply = _totalSupply.add(value); + _balances[account] = _balances[account].add(value); + emit Transfer(address(0), account, value); + } + + /** + * @dev Internal function that burns an amount of the token of a given + * account. + * @param account The account whose tokens will be burnt. + * @param value The amount that will be burnt. + */ + function _burn(address account, uint256 value) internal { + require(account != address(0)); + + _totalSupply = _totalSupply.sub(value); + _balances[account] = _balances[account].sub(value); + emit Transfer(account, address(0), value); + } + + /** + * @dev Approve an address to spend another addresses' tokens. + * @param owner The address that owns the tokens. + * @param spender The address that will spend the tokens. + * @param value The number of tokens that can be spent. + */ + function _approve(address owner, address spender, uint256 value) internal { + require(spender != address(0)); + require(owner != address(0)); + + _allowed[owner][spender] = value; + emit Approval(owner, spender, value); + } + + /** + * @dev Internal function that burns an amount of the token of a given + * account, deducting from the sender's allowance for said account. Uses the + * internal burn function. + * Emits an Approval event (reflecting the reduced allowance). + * @param account The account whose tokens will be burnt. + * @param value The amount that will be burnt. + */ + function _burnFrom(address account, uint256 value) internal { + _burn(account, value); + _approve(account, msg.sender, _allowed[account][msg.sender].sub(value)); + } +} diff --git a/test/contracts/EchoTypesComptroller.sol b/test/contracts/EchoTypesComptroller.sol new file mode 100644 index 000000000..fb605864b --- /dev/null +++ b/test/contracts/EchoTypesComptroller.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.5.8; + +import "../ComptrollerStorage.sol"; +import "../Unitroller.sol"; + +contract EchoTypesComptroller is UnitrollerAdminStorage { + + function stringy(string memory s) public pure returns(string memory) { + return s; + } + + function addresses(address a) public pure returns(address) { + return a; + } + + function booly(bool b) public pure returns(bool) { + return b; + } + + function listOInts(uint[] memory u) public pure returns(uint[] memory) { + return u; + } + + function reverty() public pure { + require(false, "gotcha sucka"); + } + + function becomeBrains(address payable unitroller) public { + Unitroller(unitroller)._acceptImplementation(); + } +} diff --git a/test/contracts/EvilToken.sol b/test/contracts/EvilToken.sol new file mode 100644 index 000000000..34cb0c414 --- /dev/null +++ b/test/contracts/EvilToken.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.5.8; + +import "./StandardToken.sol"; + +/** + * @title The Compound Evil Test Token + * @author Compound + * @notice A simple test token that fails certain operations + */ +contract EvilToken is StandardToken { + string public name; + string public symbol; + uint8 public decimals; + bool public fail; + + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public { + totalSupply_ = _initialAmount; + balances[msg.sender] = _initialAmount; + name = _tokenName; + symbol = _tokenSymbol; + decimals = _decimalUnits; + fail = true; + } + + function setFail(bool _fail) public { + fail = _fail; + } + + /** + * @dev Arbitrarily adds tokens to any account + */ + function allocateTo(address _owner, uint256 value) public { + balances[_owner] += value; + totalSupply_ += value; + emit Transfer(address(this), _owner, value); + } + + /** + * @dev Fail to transfer + */ + function transfer(address to, uint256 value) public returns (bool) { + if (fail) { + return false; + } + + return super.transfer(to, value); + } + + /** + * @dev Fail to transfer from + */ + function transferFrom(address from, address to, uint256 value) public returns (bool) { + if (fail) { + return false; + } + + return super.transferFrom(from, to, value); + } +} diff --git a/test/contracts/FalseMarkerMethodComptroller.sol b/test/contracts/FalseMarkerMethodComptroller.sol new file mode 100644 index 000000000..e8496bc30 --- /dev/null +++ b/test/contracts/FalseMarkerMethodComptroller.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.5.8; +import "./BoolComptroller.sol"; + +contract FalseMarkerMethodComptroller is BoolComptroller { + bool public isComptroller = false; +} diff --git a/test/contracts/FalseMarkerMethodInterestRateModel.sol b/test/contracts/FalseMarkerMethodInterestRateModel.sol new file mode 100644 index 000000000..ccf324e6b --- /dev/null +++ b/test/contracts/FalseMarkerMethodInterestRateModel.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.5.8; + +import "../InterestRateModel.sol"; + +/** + * @title Implements the interest rate model marker function but returns false + * @author Compound + */ +contract FalseMarkerMethodInterestRateModel is InterestRateModel { + /** + * For exhaustive testing, this contract implements the marker function but returns false instead of the intended true + */ + bool public constant isInterestRateModel = false; + + uint borrowRate; + + constructor(uint borrowRate_) public { + borrowRate = borrowRate_; + } + + /** + * @notice Gets the current borrow interest rate based on the given asset, total cash and total borrows + * @dev The return value should be scaled by 1e18, thus a return value of + * `(true, 1000000000000)` implies an interest rate of 0.000001% *per block*. + * @param _cash The total cash of the asset in the CToken + * @param _borrows The total borrows of the asset in the CToken + * @param _reserves The total reserves of the asset in the CToken + * @return Success or failure and the borrow interest rate per block scaled by 1e18 + */ + function getBorrowRate(uint _cash, uint _borrows, uint _reserves) view public returns (uint, uint) { + _cash; // unused + _borrows; // unused + _reserves; // unused + return (0, borrowRate); + } +} \ No newline at end of file diff --git a/test/contracts/FaucetNonStandardToken.sol b/test/contracts/FaucetNonStandardToken.sol new file mode 100644 index 000000000..389198fc5 --- /dev/null +++ b/test/contracts/FaucetNonStandardToken.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.5.8; + +import "./NonStandardToken.sol"; + +/** + * @title The Compound Faucet Test Token + * @author Compound + * @notice A simple test token that lets anyone get more of it. + */ +contract FaucetNonStandardToken is NonStandardToken { + string public name; + string public symbol; + uint8 public decimals; + + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public { + totalSupply_ = _initialAmount; + balances[msg.sender] = _initialAmount; + name = _tokenName; + symbol = _tokenSymbol; + decimals = _decimalUnits; + } + + /** + * @dev Arbitrarily adds tokens to any account + */ + function allocateTo(address _owner, uint256 value) public { + balances[_owner] += value; + totalSupply_ += value; + emit Transfer(address(this), _owner, value); + } +} diff --git a/test/contracts/FaucetToken.sol b/test/contracts/FaucetToken.sol new file mode 100644 index 000000000..8d38a702e --- /dev/null +++ b/test/contracts/FaucetToken.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.5.8; + +import "./StandardToken.sol"; + +/** + * @title The Compound Faucet Test Token + * @author Compound + * @notice A simple test token that lets anyone get more of it. + */ +contract FaucetToken is StandardToken { + string public name; + string public symbol; + uint8 public decimals; + + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) public { + totalSupply_ = _initialAmount; + balances[msg.sender] = _initialAmount; + name = _tokenName; + symbol = _tokenSymbol; + decimals = _decimalUnits; + } + + /** + * @dev Arbitrarily adds tokens to any account + */ + function allocateTo(address _owner, uint256 value) public { + balances[_owner] += value; + totalSupply_ += value; + emit Transfer(address(this), _owner, value); + } +} diff --git a/test/contracts/FaucetTokenReEntrantHarness.sol b/test/contracts/FaucetTokenReEntrantHarness.sol new file mode 100644 index 000000000..d98e2d2b7 --- /dev/null +++ b/test/contracts/FaucetTokenReEntrantHarness.sol @@ -0,0 +1,75 @@ +pragma solidity ^0.5.8; + +import "./ERC20NonView.sol"; + +/** + * @title The Compound Faucet Re-Entrant Test Token + * @author Compound + * @notice A test token that is malicious and tries to re-enter callers + */ +contract FaucetTokenReEntrantHarness is ERC20NonView { + string public name; + string public symbol; + uint8 public decimals; + bytes public reEntryCallData; + string public reEntryFun; + + constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol, bytes memory _reEntryCallData, string memory _reEntryFun) public { + _totalSupply = _initialAmount; + _balances[msg.sender] = _initialAmount; + name = _tokenName; + symbol = _tokenSymbol; + decimals = _decimalUnits; + reEntryCallData = _reEntryCallData; + reEntryFun = _reEntryFun; + } + + modifier reEnter(string memory funName) { + string memory _reEntryFun = reEntryFun; + if (compareStrings(_reEntryFun, funName)) { + reEntryFun = ""; // Clear re-entry fun + (bool _res, bytes memory _ret) = msg.sender.call(reEntryCallData); + _res; // unused + _ret; // unused + } + + _; + } + + function compareStrings(string memory a, string memory b) internal pure returns (bool) { + return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))); + } + + /** + * @dev Arbitrarily adds tokens to any account + */ + function allocateTo(address _owner, uint256 value) public { + _balances[_owner] += value; + _totalSupply += value; + emit Transfer(address(this), _owner, value); + } + + function totalSupply() public reEnter("totalSupply") returns (uint256) { + return super.totalSupply(); + } + + function balanceOf(address owner) public reEnter("balanceOf") returns (uint256 balance) { + return super.balanceOf(owner); + } + + function transfer(address dst, uint256 amount) public reEnter("transfer") returns (bool success) { + return super.transfer(dst, amount); + } + + function transferFrom(address src, address dst, uint256 amount) public reEnter("transferFrom") returns (bool success) { + return super.transferFrom(src, dst, amount); + } + + function approve(address spender, uint256 amount) public reEnter("approve") returns (bool success) { + return super.approve(spender, amount); + } + + function allowance(address owner, address spender) public reEnter("allowance") returns (uint256 remaining) { + return super.allowance(owner, spender); + } +} diff --git a/test/contracts/FixedPriceOracle.sol b/test/contracts/FixedPriceOracle.sol new file mode 100644 index 000000000..8b05d300a --- /dev/null +++ b/test/contracts/FixedPriceOracle.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.5.8; + +import "../PriceOracle.sol"; + +contract FixedPriceOracle is PriceOracle { + uint public price; + bool public constant isPriceOracle = true; + + constructor(uint _price) public { + price = _price; + } + + function getUnderlyingPrice(CToken cToken) public view returns (uint) { + cToken; + return price; + } + + function assetPrices(address asset) public view returns (uint) { + asset; + return price; + } +} diff --git a/test/contracts/InterestRateModelHarness.sol b/test/contracts/InterestRateModelHarness.sol new file mode 100644 index 000000000..5e23f51aa --- /dev/null +++ b/test/contracts/InterestRateModelHarness.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.5.8; + +import "../InterestRateModel.sol"; + +/** + * @title An Interest Rate Model for tests that can be instructed to return a failure instead of doing a calculation + * @author Compound + */ +contract InterestRateModelHarness is InterestRateModel { + bool public constant isInterestRateModel = true; + uint public constant opaqueBorrowFailureCode = 20; + bool public failBorrowRate; + uint public borrowRate; + + constructor(uint borrowRate_) public { + borrowRate = borrowRate_; + } + + function setFailBorrowRate(bool failBorrowRate_) public { + failBorrowRate = failBorrowRate_; + } + + function setBorrowRate(uint borrowRate_) public { + borrowRate = borrowRate_; + } + + function getBorrowRate(uint _cash, uint _borrows, uint _reserves) public view returns (uint, uint) { + _cash; // unused + _borrows; // unused + _reserves; // unused + + if (failBorrowRate) { + return (opaqueBorrowFailureCode, 0); + } + return (0, borrowRate); + } +} \ No newline at end of file diff --git a/test/contracts/MathHelpers.sol b/test/contracts/MathHelpers.sol new file mode 100644 index 000000000..c9224965f --- /dev/null +++ b/test/contracts/MathHelpers.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.5.8; + +contract MathHelpers { + + /* + * @dev Creates a number like 15e16 as a uint256 from scientific(15, 16). + */ + function scientific(uint val, uint expTen) pure internal returns (uint) { + return val * ( 10 ** expTen ); + } + +} \ No newline at end of file diff --git a/test/contracts/NonStandardToken.sol b/test/contracts/NonStandardToken.sol new file mode 100644 index 000000000..d51837eca --- /dev/null +++ b/test/contracts/NonStandardToken.sol @@ -0,0 +1,122 @@ +pragma solidity ^0.5.8; + +import "./BasicTokenNS.sol"; +import "./ERC20NS.sol"; + + +/** + * @title Non-Standard ERC20 token + * + * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` + * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca + * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + */ +contract NonStandardToken is ERC20NS, BasicTokenNS { + + mapping (address => mapping (address => uint256)) internal allowed; + + + /** + * @dev Transfer tokens from one address to another + * @param _from address The address which you want to send tokens from + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + */ + function transferFrom( + address _from, + address _to, + uint256 _value + ) + public + { + require(_to != address(0)); + require(_value <= balances[_from]); + require(_value <= allowed[_from][msg.sender]); + + balances[_from] = balances[_from].sub(_value); + balances[_to] = balances[_to].add(_value); + allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); + emit Transfer(_from, _to, _value); + } + + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param _spender The address which will spend the funds. + * @param _value The amount of tokens to be spent. + */ + function approve(address _spender, uint256 _value) public returns (bool) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param _owner address The address which owns the funds. + * @param _spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance( + address _owner, + address _spender + ) + public + view + returns (uint256) + { + return allowed[_owner][_spender]; + } + + /** + * @dev Increase the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed[_spender] == 0. To increment + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param _spender The address which will spend the funds. + * @param _addedValue The amount of tokens to increase the allowance by. + */ + function increaseApproval( + address _spender, + uint256 _addedValue + ) + public + returns (bool) + { + allowed[msg.sender][_spender] = ( + allowed[msg.sender][_spender].add(_addedValue)); + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + return true; + } + + /** + * @dev Decrease the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed[_spender] == 0. To decrement + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param _spender The address which will spend the funds. + * @param _subtractedValue The amount of tokens to decrease the allowance by. + */ + function decreaseApproval( + address _spender, + uint256 _subtractedValue + ) + public + returns (bool) + { + uint256 oldValue = allowed[msg.sender][_spender]; + if (_subtractedValue > oldValue) { + allowed[msg.sender][_spender] = 0; + } else { + allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); + } + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + return true; + } + +} \ No newline at end of file diff --git a/test/contracts/NotPriceOracle.sol b/test/contracts/NotPriceOracle.sol new file mode 100644 index 000000000..8503f6295 --- /dev/null +++ b/test/contracts/NotPriceOracle.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.5.8; + +contract NotPriceOracle { + // marker function + bool public constant isPriceOracle = false; +} diff --git a/test/contracts/SafeMath.sol b/test/contracts/SafeMath.sol new file mode 100644 index 000000000..15cac29d1 --- /dev/null +++ b/test/contracts/SafeMath.sol @@ -0,0 +1,52 @@ +pragma solidity ^0.5.8; + + +/** + * @title SafeMath + * @dev Math operations with safety checks that throw on error + */ +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { + // Gas optimization: this is cheaper than asserting 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } + + c = a * b; + assert(c / a == b); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + // uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return a / b; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + assert(b <= a); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256 c) { + c = a + b; + assert(c >= a); + return c; + } +} \ No newline at end of file diff --git a/test/contracts/StandardToken.sol b/test/contracts/StandardToken.sol new file mode 100644 index 000000000..7865127e5 --- /dev/null +++ b/test/contracts/StandardToken.sol @@ -0,0 +1,124 @@ +pragma solidity ^0.5.8; + +import "./BasicToken.sol"; +import "./ERC20.sol"; + + +/** + * @title Standard ERC20 token + * + * @dev Implementation of the basic standard token. + * https://github.com/ethereum/EIPs/issues/20 + * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + */ +contract StandardToken is ERC20, BasicToken { + + mapping (address => mapping (address => uint256)) internal allowed; + + + /** + * @dev Transfer tokens from one address to another + * @param _from address The address which you want to send tokens from + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + */ + function transferFrom( + address _from, + address _to, + uint256 _value + ) + public + returns (bool) + { + require(_to != address(0)); + require(_value <= balances[_from]); + require(_value <= allowed[_from][msg.sender]); + + balances[_from] = balances[_from].sub(_value); + balances[_to] = balances[_to].add(_value); + allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); + emit Transfer(_from, _to, _value); + return true; + } + + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param _spender The address which will spend the funds. + * @param _value The amount of tokens to be spent. + */ + function approve(address _spender, uint256 _value) public returns (bool) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param _owner address The address which owns the funds. + * @param _spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance( + address _owner, + address _spender + ) + public + view + returns (uint256) + { + return allowed[_owner][_spender]; + } + + /** + * @dev Increase the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed[_spender] == 0. To increment + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param _spender The address which will spend the funds. + * @param _addedValue The amount of tokens to increase the allowance by. + */ + function increaseApproval( + address _spender, + uint256 _addedValue + ) + public + returns (bool) + { + allowed[msg.sender][_spender] = ( + allowed[msg.sender][_spender].add(_addedValue)); + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + return true; + } + + /** + * @dev Decrease the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed[_spender] == 0. To decrement + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param _spender The address which will spend the funds. + * @param _subtractedValue The amount of tokens to decrease the allowance by. + */ + function decreaseApproval( + address _spender, + uint256 _subtractedValue + ) + public + returns (bool) + { + uint256 oldValue = allowed[msg.sender][_spender]; + if (_subtractedValue > oldValue) { + allowed[msg.sender][_spender] = 0; + } else { + allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); + } + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + return true; + } + +} \ No newline at end of file diff --git a/test/contracts/WBTC.sol b/test/contracts/WBTC.sol new file mode 100644 index 000000000..f61da7133 --- /dev/null +++ b/test/contracts/WBTC.sol @@ -0,0 +1,672 @@ +/** + *Submitted for verification at Etherscan.io on 2018-11-24 +*/ + +pragma solidity ^0.5.8; + +// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol + +/** + * @title ERC20Basic + * @dev Simpler version of ERC20 interface + * See https://github.com/ethereum/EIPs/issues/179 + */ +contract ERC20Basic { + function totalSupply() public view returns (uint256); + function balanceOf(address _who) public view returns (uint256); + function transfer(address _to, uint256 _value) public returns (bool); + event Transfer(address indexed from, address indexed to, uint256 value); +} + +// File: openzeppelin-solidity/contracts/math/SafeMath.sol + +/** + * @title SafeMath + * @dev Math operations with safety checks that throw on error + */ +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { + // Gas optimization: this is cheaper than asserting 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (_a == 0) { + return 0; + } + + c = _a * _b; + assert(c / _a == _b); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 _a, uint256 _b) internal pure returns (uint256) { + // assert(_b > 0); // Solidity automatically throws when dividing by 0 + // uint256 c = _a / _b; + // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold + return _a / _b; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { + assert(_b <= _a); + return _a - _b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { + c = _a + _b; + assert(c >= _a); + return c; + } +} + +// File: openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol + +/** + * @title Basic token + * @dev Basic version of StandardToken, with no allowances. + */ +contract BasicToken is ERC20Basic { + using SafeMath for uint256; + + mapping(address => uint256) internal balances; + + uint256 internal totalSupply_; + + /** + * @dev Total number of tokens in existence + */ + function totalSupply() public view returns (uint256) { + return totalSupply_; + } + + /** + * @dev Transfer token for a specified address + * @param _to The address to transfer to. + * @param _value The amount to be transferred. + */ + function transfer(address _to, uint256 _value) public returns (bool) { + require(_value <= balances[msg.sender]); + require(_to != address(0)); + + balances[msg.sender] = balances[msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + emit Transfer(msg.sender, _to, _value); + return true; + } + + /** + * @dev Gets the balance of the specified address. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address _owner) public view returns (uint256) { + return balances[_owner]; + } + +} + +// File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol + +/** + * @title ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/20 + */ +contract ERC20 is ERC20Basic { + function allowance(address _owner, address _spender) + public view returns (uint256); + + function transferFrom(address _from, address _to, uint256 _value) + public returns (bool); + + function approve(address _spender, uint256 _value) public returns (bool); + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); +} + +// File: openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol + +/** + * @title Standard ERC20 token + * + * @dev Implementation of the basic standard token. + * https://github.com/ethereum/EIPs/issues/20 + * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + */ +contract StandardToken is ERC20, BasicToken { + + mapping (address => mapping (address => uint256)) internal allowed; + + + /** + * @dev Transfer tokens from one address to another + * @param _from address The address which you want to send tokens from + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + */ + function transferFrom( + address _from, + address _to, + uint256 _value + ) + public + returns (bool) + { + require(_value <= balances[_from]); + require(_value <= allowed[_from][msg.sender]); + require(_to != address(0)); + + balances[_from] = balances[_from].sub(_value); + balances[_to] = balances[_to].add(_value); + allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); + emit Transfer(_from, _to, _value); + return true; + } + + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param _spender The address which will spend the funds. + * @param _value The amount of tokens to be spent. + */ + function approve(address _spender, uint256 _value) public returns (bool) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param _owner address The address which owns the funds. + * @param _spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance( + address _owner, + address _spender + ) + public + view + returns (uint256) + { + return allowed[_owner][_spender]; + } + + /** + * @dev Increase the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed[_spender] == 0. To increment + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param _spender The address which will spend the funds. + * @param _addedValue The amount of tokens to increase the allowance by. + */ + function increaseApproval( + address _spender, + uint256 _addedValue + ) + public + returns (bool) + { + allowed[msg.sender][_spender] = ( + allowed[msg.sender][_spender].add(_addedValue)); + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + return true; + } + + /** + * @dev Decrease the amount of tokens that an owner allowed to a spender. + * approve should be called when allowed[_spender] == 0. To decrement + * allowed value is better to use this function to avoid 2 calls (and wait until + * the first transaction is mined) + * From MonolithDAO Token.sol + * @param _spender The address which will spend the funds. + * @param _subtractedValue The amount of tokens to decrease the allowance by. + */ + function decreaseApproval( + address _spender, + uint256 _subtractedValue + ) + public + returns (bool) + { + uint256 oldValue = allowed[msg.sender][_spender]; + if (_subtractedValue >= oldValue) { + allowed[msg.sender][_spender] = 0; + } else { + allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); + } + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + return true; + } + +} + +// File: openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol + +/** + * @title DetailedERC20 token + * @dev The decimals are only for visualization purposes. + * All the operations are done using the smallest and indivisible token unit, + * just as on Ethereum all the operations are done in wei. + */ +contract DetailedERC20 is ERC20 { + string public name; + string public symbol; + uint8 public decimals; + + constructor(string memory _name, string memory _symbol, uint8 _decimals) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + } +} + +// File: openzeppelin-solidity/contracts/ownership/Ownable.sol + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + event OwnershipRenounced(address indexed previousOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + /** + * @dev Allows the current owner to relinquish control of the contract. + * @notice Renouncing to ownership will leave the contract without an owner. + * It will not be possible to call the functions with the `onlyOwner` + * modifier anymore. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipRenounced(owner); + owner = address(0); + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function transferOwnership(address _newOwner) public onlyOwner { + _transferOwnership(_newOwner); + } + + /** + * @dev Transfers control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function _transferOwnership(address _newOwner) internal { + require(_newOwner != address(0)); + emit OwnershipTransferred(owner, _newOwner); + owner = _newOwner; + } +} + +// File: openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol + +/** + * @title Mintable token + * @dev Simple ERC20 Token example, with mintable token creation + * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol + */ +contract MintableToken is StandardToken, Ownable { + event Mint(address indexed to, uint256 amount); + event MintFinished(); + + bool public mintingFinished = false; + + + modifier canMint() { + require(!mintingFinished); + _; + } + + modifier hasMintPermission() { + require(msg.sender == owner); + _; + } + + /** + * @dev Function to mint tokens + * @param _to The address that will receive the minted tokens. + * @param _amount The amount of tokens to mint. + * @return A boolean that indicates if the operation was successful. + */ + function mint( + address _to, + uint256 _amount + ) + public + hasMintPermission + canMint + returns (bool) + { + totalSupply_ = totalSupply_.add(_amount); + balances[_to] = balances[_to].add(_amount); + emit Mint(_to, _amount); + emit Transfer(address(0), _to, _amount); + return true; + } + + /** + * @dev Function to stop minting new tokens. + * @return True if the operation was successful. + */ + function finishMinting() public onlyOwner canMint returns (bool) { + mintingFinished = true; + emit MintFinished(); + return true; + } +} + +// File: openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol + +/** + * @title Burnable Token + * @dev Token that can be irreversibly burned (destroyed). + */ +contract BurnableToken is BasicToken { + + event Burn(address indexed burner, uint256 value); + + /** + * @dev Burns a specific amount of tokens. + * @param _value The amount of token to be burned. + */ + function burn(uint256 _value) public { + _burn(msg.sender, _value); + } + + function _burn(address _who, uint256 _value) internal { + require(_value <= balances[_who]); + // no need to require value <= totalSupply, since that would imply the + // sender's balance is greater than the totalSupply, which *should* be an assertion failure + + balances[_who] = balances[_who].sub(_value); + totalSupply_ = totalSupply_.sub(_value); + emit Burn(_who, _value); + emit Transfer(_who, address(0), _value); + } +} + +// File: openzeppelin-solidity/contracts/lifecycle/Pausable.sol + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() public onlyOwner whenNotPaused { + paused = true; + emit Pause(); + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() public onlyOwner whenPaused { + paused = false; + emit Unpause(); + } +} + +// File: openzeppelin-solidity/contracts/token/ERC20/PausableToken.sol + +/** + * @title Pausable token + * @dev StandardToken modified with pausable transfers. + **/ +contract PausableToken is StandardToken, Pausable { + + function transfer( + address _to, + uint256 _value + ) + public + whenNotPaused + returns (bool) + { + return super.transfer(_to, _value); + } + + function transferFrom( + address _from, + address _to, + uint256 _value + ) + public + whenNotPaused + returns (bool) + { + return super.transferFrom(_from, _to, _value); + } + + function approve( + address _spender, + uint256 _value + ) + public + whenNotPaused + returns (bool) + { + return super.approve(_spender, _value); + } + + function increaseApproval( + address _spender, + uint _addedValue + ) + public + whenNotPaused + returns (bool success) + { + return super.increaseApproval(_spender, _addedValue); + } + + function decreaseApproval( + address _spender, + uint _subtractedValue + ) + public + whenNotPaused + returns (bool success) + { + return super.decreaseApproval(_spender, _subtractedValue); + } +} + +// File: openzeppelin-solidity/contracts/ownership/Claimable.sol + +/** + * @title Claimable + * @dev Extension for the Ownable contract, where the ownership needs to be claimed. + * This allows the new owner to accept the transfer. + */ +contract Claimable is Ownable { + address public pendingOwner; + + /** + * @dev Modifier throws if called by any account other than the pendingOwner. + */ + modifier onlyPendingOwner() { + require(msg.sender == pendingOwner); + _; + } + + /** + * @dev Allows the current owner to set the pendingOwner address. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + pendingOwner = newOwner; + } + + /** + * @dev Allows the pendingOwner address to finalize the transfer. + */ + function claimOwnership() public onlyPendingOwner { + emit OwnershipTransferred(owner, pendingOwner); + owner = pendingOwner; + pendingOwner = address(0); + } +} + +// File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol + +/** + * @title SafeERC20 + * @dev Wrappers around ERC20 operations that throw on failure. + * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, + * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. + */ +library SafeERC20 { + function safeTransfer( + ERC20Basic _token, + address _to, + uint256 _value + ) + internal + { + require(_token.transfer(_to, _value)); + } + + function safeTransferFrom( + ERC20 _token, + address _from, + address _to, + uint256 _value + ) + internal + { + require(_token.transferFrom(_from, _to, _value)); + } + + function safeApprove( + ERC20 _token, + address _spender, + uint256 _value + ) + internal + { + require(_token.approve(_spender, _value)); + } +} + +// File: openzeppelin-solidity/contracts/ownership/CanReclaimToken.sol + +/** + * @title Contracts that should be able to recover tokens + * @author SylTi + * @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner. + * This will prevent any accidental loss of tokens. + */ +contract CanReclaimToken is Ownable { + using SafeERC20 for ERC20Basic; + + /** + * @dev Reclaim all ERC20Basic compatible tokens + * @param _token ERC20Basic The address of the token contract + */ + function reclaimToken(ERC20Basic _token) external onlyOwner { + uint256 balance = _token.balanceOf(address(this)); + _token.safeTransfer(owner, balance); + } + +} + +// File: contracts/utils/OwnableContract.sol + +// empty block is used as this contract just inherits others. +contract OwnableContract is CanReclaimToken, Claimable { } /* solhint-disable-line no-empty-blocks */ + +// File: contracts/token/WBTC.sol + +contract WBTCToken is StandardToken, DetailedERC20("Wrapped BTC", "WBTC", 8), + MintableToken, BurnableToken, PausableToken, OwnableContract { + + function burn(uint value) public onlyOwner { + super.burn(value); + } + + function finishMinting() public onlyOwner returns (bool) { + return false; + } + + function renounceOwnership() public onlyOwner { + revert("renouncing ownership is blocked"); + } + + /** + * @dev Arbitrarily adds tokens to any account + */ + function allocateTo(address _owner, uint256 value) public { + balances[_owner] += value; + totalSupply_ += value; + emit Transfer(address(this), _owner, value); + } +} diff --git a/truffle.js b/truffle.js new file mode 100644 index 000000000..29543900a --- /dev/null +++ b/truffle.js @@ -0,0 +1,88 @@ +"use strict"; + +const Web3 = require("web3"); +const fs = require('fs'); +const path = require('path'); + +const networks = { + rinkeby: 4, + kovan: 42, + ropsten: 3, + mainnet: 1, + goerli: 5 +}; + +const infuraNetworks = Object.entries(networks).reduce((networks, [network, networkId]) => { + return { + ...networks, + [network]: { + provider: new Web3.providers.HttpProvider(`https://${network}.infura.io/`), + network_id: networkId + } + }; +}, {}); + +let mochaOptions = { + reporter: "mocha-multi-reporters", + reporterOptions: { + configFile: "reporterConfig.json" + } +}; + +if (process.env.NETWORK === 'coverage') { + mochaOptions = { + enableTimeouts: false, + grep: /@gas/, + invert: true + }; +} + +const development = { + host: "localhost", + port: 8545, + network_id: "*", + gas: 6700000, + gasPrice: 20000, +} + +const coverage = { // See example coverage settings at https://github.com/sc-forks/solidity-coverage + host: "localhost", + network_id: "*", + gas: 0xfffffffffff, + gasPrice: 0x01, + port: 8555 +}; + +const test = { + host: "localhost", + port: 8545, + network_id: "*", + gas: 20000000, + gasPrice: 20000 +}; + +process.env[`development_opts`] = JSON.stringify(development); +process.env[`coverage_opts`] = JSON.stringify(coverage); +process.env[`test_opts`] = JSON.stringify(test); + +module.exports = { + networks: { + ...infuraNetworks, + development, + coverage, + test + }, + compilers: { + solc: { + version: "0.5.8", + settings: { + optimizer: { + enabled: true + } + } + } + }, + mocha: mochaOptions, + contracts_build_directory: process.env.CONTRACTS_BUILD_DIRECTORY || undefined, + build_directory: process.env.BUILD_DIRECTORY || undefined +}; diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..deab9d16f --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6179 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/runtime@^7.3.1": + version "7.5.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.4.tgz#cb7d1ad7c6d65676e66b47186577930465b5271b" + integrity sha512-Na84uwyImZZc3FKf4aUF1tysApzwf3p2yuFBIyBfbzT5glzKTdvYI4KVW4kcgjrzoGUjC7w3YyCHcJKaRxsr2Q== + dependencies: + regenerator-runtime "^0.13.2" + +"@resolver-engine/core@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.2.1.tgz#0d71803f6d3b8cb2e9ed481a1bf0ca5f5256d0c0" + integrity sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A== + dependencies: + debug "^3.1.0" + request "^2.85.0" + +"@resolver-engine/fs@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.2.1.tgz#f98a308d77568cc02651d03636f46536b941b241" + integrity sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg== + dependencies: + "@resolver-engine/core" "^0.2.1" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz#5a81ef3285dbf0411ab3b15205080a1ad7622d9e" + integrity sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ== + dependencies: + "@resolver-engine/fs" "^0.2.1" + "@resolver-engine/imports" "^0.2.2" + debug "^3.1.0" + +"@resolver-engine/imports@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.2.2.tgz#d3de55a1bb5f3beb7703fdde743298f321175843" + integrity sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg== + dependencies: + "@resolver-engine/core" "^0.2.1" + debug "^3.1.0" + hosted-git-info "^2.6.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@types/bn.js@^4.11.4": + version "4.11.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.5.tgz#40e36197433f78f807524ec623afcf0169ac81dc" + integrity sha512-AEAZcIZga0JgVMHNtl1CprA/hXX7/wPt79AgR4XqaDt7jyj3QWYw6LPoOiznPtugDmlubUnAahMs2PFxGcQrng== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@^10.3.2": + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + +"@types/node@^10.12.18": + version "10.14.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.12.tgz#0eec3155a46e6c4db1f27c3e588a205f767d622f" + integrity sha512-QcAKpaO6nhHLlxWBvpc4WeLrTvPqlHOvaj0s5GriKkA1zq+bsFBPpfYCvQhLqLgYlIko8A9YrPdaMHCo5mBcpg== + +JSONStream@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= + +accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= + dependencies: + mime-types "~2.1.18" + negotiator "0.6.1" + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + +agent-base@4, agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + +agent-base@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + +agentkeepalive@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67" + integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ== + dependencies: + humanize-ms "^1.2.1" + +ajv@^5.2.2: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ajv@^6.5.5: + version "6.6.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" + integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +any-promise@1.3.0, any-promise@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +app-module-path@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +async@1.x: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@2.6.1, async@^2.5.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" + integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== + dependencies: + lodash "^4.17.10" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bignumber.js@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.1.tgz#5d419191370fb558c64e3e5f70d68e5947138832" + integrity sha512-zAySveTJXkgLYCBi0b14xzfnOs+f3G6x36I8w2a1+PFQpWk/dp0mI0F+ZZK2bu+3ELewDcSyP+Cfq++NcHX7sg== + +binary-extensions@^1.0.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" + integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== + +bindings@^1.2.1, bindings@^1.3.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bluebird@^3.5.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" + integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== + +bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: + version "3.5.5" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" + integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + +bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +body-parser@1.18.3, body-parser@^1.16.0: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + +boxen@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" + integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^2.4.2" + cli-boxes "^2.2.0" + string-width "^3.0.0" + term-size "^1.2.0" + type-fest "^0.3.0" + widest-line "^2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sha3@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.4.tgz#086c47b8c82316c9d47022c26185954576dd8e26" + integrity sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY= + dependencies: + js-sha3 "^0.6.1" + safe-buffer "^5.1.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^3.0.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" + integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= + dependencies: + base64-js "0.0.8" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^5.0.5: + version "5.2.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +cacache@^12.0.0: + version "12.0.2" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.2.tgz#8db03205e36089a3df6954c66ce92541441ac46c" + integrity sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +charenc@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + +chokidar@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cint@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/cint/-/cint-8.2.1.tgz#70386b1b48e2773d0d63166a55aff94ef4456a12" + integrity sha1-cDhrG0jidz0NYxZqVa/5TvRFahI= + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-boxes@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" + integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== + +cli-table@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" + integrity sha1-9TsFJmqLGguTSz0IIebi3FkUriM= + dependencies: + colors "1.0.3" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + +colors@^1.1.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" + integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + +commander@^2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== + +commander@^2.9.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + +commander@~2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== + +commander@~2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= + dependencies: + graceful-readlink ">= 1.0.0" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +configstore@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" + integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ== + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + +cookiejar@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +crypt@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + +crypto-browserify@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= + +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +death@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" + integrity sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg= + +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +defer-to-connect@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" + integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-installed@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-installed/-/detect-installed-2.0.4.tgz#a0850465e7c3ebcff979d6b6535ad344b80dd7c5" + integrity sha1-oIUEZefD68/5eda2U1rTRLgN18U= + dependencies: + get-installed-path "^2.0.3" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== + +diff@3.5.0, diff@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + +dot-prop@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +elliptic@6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" + integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + inherits "^2.0.1" + +elliptic@^6.0.0, elliptic@^6.4.0: + version "6.4.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" + integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + dependencies: + iconv-lite "~0.4.13" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +eol@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" + integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== + +err-code@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" + integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eth-ens-namehash@2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-lib@0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" + integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.27" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" + integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + keccakjs "^0.2.1" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +ethereumjs-testrpc-sc@6.4.5-sc.3: + version "6.4.5-sc.3" + resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.4.5-sc.3.tgz#7c02bfb4c07f32d0ccb30140b61736e5f1bb71c4" + integrity sha512-uQD5Tf+C1QgXRx4GkYnlkB6UxLInkbn2gZzwAKLbnDKIzqcv4JiKVUJxnHyYrbXAu0IAxexus7jYnpju2yDHqw== + dependencies: + bn.js "4.11.8" + source-map-support "0.5.9" + yargs "11.1.0" + +ethers@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.3.tgz#15bef14e57e94ecbeb7f9b39dd0a4bd435bc9066" + integrity sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog== + dependencies: + "@types/node" "^10.3.2" + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.3.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.3" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + +ethers@^4.0.27, ethers@^4.0.32: + version "4.0.33" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.33.tgz#f7b88d2419d731a39aefc37843a3f293e396f918" + integrity sha512-lAHkSPzBe0Vj+JrhmkEHLtUEKEheVktIjGDyE9gbzF4zf1vibjYgB57LraDHu4/ItqWVkztgsm8GWqcDMN+6vQ== + dependencies: + "@types/node" "^10.3.2" + aes-js "3.0.0" + bn.js "^4.4.0" + elliptic "6.3.3" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.4" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + +ethjs-unit@0.1.6, ethjs-unit@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethlint@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ethlint/-/ethlint-1.2.2.tgz#29efb5edd54a44863cbb694da1e4cd269b2fd5f9" + integrity sha512-yzk7XeBuDLPn0iHuC7FUiY4DvXoXFgP4dmIJ1VwnzrXD5L0O9kCpjUMN9PxRbLbxKAm+PbmmVSh4DgPQjhmjeQ== + dependencies: + ajv "^5.2.2" + chokidar "^1.6.0" + colors "^1.1.2" + commander "^2.9.0" + diff "^3.5.0" + eol "^0.9.1" + js-string-escape "^1.0.1" + lodash "^4.14.2" + sol-digger "0.0.2" + sol-explore "1.6.1" + solium-plugin-security "0.1.1" + solparse "2.2.8" + text-table "^0.2.0" + +eventemitter3@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" + integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== + +eventemitter3@3.1.2, eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +express@^4.14.0: + version "4.16.4" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" + integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.3" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.4" + qs "6.5.2" + range-parser "~1.2.0" + safe-buffer "5.1.2" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-diff@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= + +file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.4.0" + unpipe "~1.0.0" + +find-up@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +for-each@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== + dependencies: + minipass "^2.2.1" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +ganache-cli@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.3.0.tgz#574f9d35aaec8da6e01c2be49db8fe73129eb561" + integrity sha512-8SyzfX2ipRVBx1fBZLg3j8I3E334U3Vazk5mEpYcWqnIjC2ace6jtOXHG4aTuAvSz3+HzQ8p8pRjOJxdDZ2pnQ== + dependencies: + bn.js "4.11.8" + source-map-support "0.5.9" + yargs "11.1.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +genfun@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" + integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-installed-path@^2.0.3: + version "2.1.1" + resolved "https://registry.yarnpkg.com/get-installed-path/-/get-installed-path-2.1.1.tgz#a1f33dc6b8af542c9331084e8edbe37fe2634152" + integrity sha512-Qkn9eq6tW5/q9BDVdMpB8tOHljX9OSP0jRC5TRNVA4qRc839t4g8KQaR8t0Uv0EFVL0MlyG7m/ofjEgAROtYsA== + dependencies: + global-modules "1.0.0" + +get-installed-path@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/get-installed-path/-/get-installed-path-4.0.8.tgz#a4fee849f5f327c12c551bb37477acd5151e5f7d" + integrity sha512-PmANK1xElIHlHH2tXfOoTnSDUjX1X3GvKK6ZyLbUnSCCn1pADwu67eVWttuPzJWrXDDT2MfO6uAaKILOFfitmA== + dependencies: + global-modules "1.0.0" + +get-stdin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" + integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== + +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3, glob@^7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + dependencies: + ini "^1.3.4" + +global-modules@1.0.0, global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global@~4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +got@9.6.0, got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +got@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.10, graceful-fs@^4.1.11: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" + integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +handlebars@^4.0.1: + version "4.0.12" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" + integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== + dependencies: + async "^2.5.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== + +http-cache-semantics@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" + integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== + +http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz#271ea8e90f836ac9f119daccd39c19ff7dfb0793" + integrity sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + dependencies: + ms "^2.0.0" + +iconv-lite@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.4.4, iconv-lite@~0.4.13: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + dependencies: + minimatch "^3.0.4" + +immutable@^4.0.0-rc.12: + version "4.0.0-rc.12" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" + integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +interpret@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +ipaddr.js@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" + integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5, is-buffer@~1.1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= + +is-npm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" + integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA== + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +istanbul@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +jju@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= + +js-sha3@0.5.7, js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= + +js-sha3@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.6.1.tgz#5b89f77a7477679877f58c4a075240934b1f95c0" + integrity sha1-W4n3enR3Z5h39YxKB1JAk0sflcA= + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +js-yaml@3.x, js-yaml@^3.12.0: + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" + integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-helpfulerror@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz#13f14ce02eed4e981297b64eb9e3b932e2dd13dc" + integrity sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w= + dependencies: + jju "^1.1.0" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" + integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + dependencies: + minimist "^1.2.0" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +keccak@^1.0.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" + integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== + dependencies: + bindings "^1.2.1" + inherits "^2.0.3" + nan "^2.2.1" + safe-buffer "^5.1.0" + +keccakjs@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" + integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== + dependencies: + browserify-sha3 "^0.0.4" + sha3 "^1.2.2" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +kleur@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +libnpmconfig@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/libnpmconfig/-/libnpmconfig-1.2.1.tgz#c0c2f793a74e67d4825e5039e7a02a0044dfcbc0" + integrity sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA== + dependencies: + figgy-pudding "^3.5.1" + find-up "^3.0.0" + ini "^1.3.5" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash@^4.14.2, lodash@^4.16.4, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.2.0: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + +lodash@^4.17.13: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-fetch-happen@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.0.tgz#a8e3fe41d3415dd656fe7b8e8172e1fb4458b38d" + integrity sha512-nFr/vpL1Jc60etMVKeaLOqfGjMMb3tAHFVJWxHOFCFS04Zmd7kGlMxo0l1tzfhoQje0/UPnd0X8OeGUiXXnfPA== + dependencies: + agentkeepalive "^3.4.1" + cacache "^12.0.0" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + lru-cache "^5.1.1" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^4.0.0" + ssri "^6.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +md5@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" + integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= + dependencies: + charenc "~0.0.1" + crypt "~0.0.1" + is-buffer "~1.1.1" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" + integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.18, mime-types@~2.1.19: + version "2.1.21" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" + integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== + dependencies: + mime-db "~1.37.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +minipass@^2.2.1, minipass@^2.3.4, minipass@^2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.1, minizlib@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== + dependencies: + minipass "^2.2.1" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha-junit-reporter@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.18.0.tgz#9209a3fba30025ae3ae5e6bfe7f9c5bc3c2e8ee2" + integrity sha512-y3XuqKa2+HRYtg0wYyhW/XsLm2Ps+pqf9HaTAt7+MVUAKFJaNAHOrNseTZo9KCxjfIbxUWwckP5qCDDPUmjSWA== + dependencies: + debug "^2.2.0" + md5 "^2.1.0" + mkdirp "~0.5.1" + strip-ansi "^4.0.0" + xml "^1.0.0" + +mocha-multi-reporters@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz#cc7f3f4d32f478520941d852abb64d9988587d82" + integrity sha1-zH8/TTL0eFIJQdhSq7ZNmYhYfYI= + dependencies: + debug "^3.1.0" + lodash "^4.16.4" + +mocha@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +mocha@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + mkdirp "0.5.1" + supports-color "4.4.0" + +mock-fs@^4.1.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" + integrity sha512-WlQNtUlzMRpvLHf8dqeUmNqfdPjGY29KrJF50Ldb4AcL+vQeR8QH3wQcFMgrhTwb1gHjZn9xggho+84tBskLgA== + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +nan@2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== + +nan@^2.0.8, nan@^2.3.3, nan@^2.9.2: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== + +nan@^2.11.0: + version "2.13.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" + integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== + +nan@^2.2.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= + +nested-error-stacks@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz#d2cc9fc5235ddb371fc44d506234339c8e4b0a4b" + integrity sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A== + +node-alias@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/node-alias/-/node-alias-1.0.4.tgz#1f1b916b56b9ea241c0135f97ced6940f556f292" + integrity sha1-HxuRa1a56iQcATX5fO1pQPVW8pI= + dependencies: + chalk "^1.1.1" + lodash "^4.2.0" + +node-fetch-npm@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" + integrity sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw== + dependencies: + encoding "^0.1.11" + json-parse-better-errors "^1.0.0" + safe-buffer "^5.1.1" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-url@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.3.0.tgz#9c49e10fc1876aeb76dba88bf1b2b5d9fa57b2ee" + integrity sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ== + +npm-bundled@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== + +npm-check-updates@^3.1.11: + version "3.1.20" + resolved "https://registry.yarnpkg.com/npm-check-updates/-/npm-check-updates-3.1.20.tgz#9dd719bc04af9c273b33b44a7d5368d5e85ae9c2" + integrity sha512-mc9BAoOYSTwP/IvoA+ofdkWSipwRvhgC0qop1PvlMZojgzi7N/dykdxOIWrw0OlZPnEKvXkKFEuPk97LrvXE1A== + dependencies: + chalk "^2.4.2" + cint "^8.2.1" + cli-table "^0.3.1" + commander "^2.20.0" + fast-diff "^1.2.0" + find-up "4.1.0" + get-stdin "^7.0.0" + json-parse-helpfulerror "^1.0.3" + libnpmconfig "^1.2.1" + lodash "^4.17.13" + node-alias "^1.0.4" + pacote "^9.5.1" + progress "^2.0.3" + prompts "^2.1.0" + rc-config-loader "^2.0.4" + requireg "^0.2.2" + semver "^6.2.0" + semver-utils "^1.1.4" + spawn-please "^0.3.0" + update-notifier "^3.0.1" + +npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" + integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA== + dependencies: + hosted-git-info "^2.6.0" + osenv "^0.1.5" + semver "^5.5.0" + validate-npm-package-name "^3.0.0" + +npm-packlist@^1.1.12: + version "1.4.4" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" + integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-packlist@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.2.0.tgz#55a60e793e272f00862c7089274439a4cc31fc7f" + integrity sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-pick-manifest@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40" + integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA== + dependencies: + figgy-pudding "^3.5.1" + npm-package-arg "^6.0.0" + semver "^5.4.1" + +npm-registry-fetch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz#5ef75845b605855c7964472542c25da172af8677" + integrity sha512-Jllq35Jag8dtv0M17ue74XtdQTyqKzuAYGiX9mAjOhkmNjib3bBUgK6mUY61+AHnXeSRobQkpY3/xIOS/omptw== + dependencies: + JSONStream "^1.3.4" + bluebird "^3.5.1" + figgy-pudding "^3.4.1" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" + npm-package-arg "^6.1.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-keys@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= + dependencies: + http-https "^1.0.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +original-require@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" + integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4, osenv@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +pacote@^9.5.1: + version "9.5.4" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.4.tgz#8baa26f3d1326d13dc2fe0fe84040a364ae30aad" + integrity sha512-nWr0ari6E+apbdoN0hToTKZElO5h4y8DGFa2pyNA5GQIdcP0imC96bA0bbPw1gpeguVIiUgHHaAlq/6xfPp8Qw== + dependencies: + bluebird "^3.5.3" + cacache "^12.0.0" + figgy-pudding "^3.5.1" + get-stream "^4.1.0" + glob "^7.1.3" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" + minimatch "^3.0.4" + minipass "^2.3.5" + mississippi "^3.0.0" + mkdirp "^0.5.1" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + npm-packlist "^1.1.12" + npm-pick-manifest "^2.2.3" + npm-registry-fetch "^4.0.0" + osenv "^0.1.5" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^5.0.1" + rimraf "^2.6.2" + safe-buffer "^5.1.2" + semver "^5.6.0" + ssri "^6.0.1" + tar "^4.4.8" + unique-filename "^1.1.1" + which "^1.3.1" + +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parse-asn1@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-headers@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" + integrity sha1-aug6eqJanZtwCswoaYzR8e1+lTY= + dependencies: + for-each "^0.3.2" + trim "0.0.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.5, path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pegjs@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= + +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +promise-retry@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" + integrity sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0= + dependencies: + err-code "^1.0.0" + retry "^0.10.0" + +prompts@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.1.0.tgz#bf90bc71f6065d255ea2bdc0fe6520485c1b45db" + integrity sha512-+x5TozgqYdOwWsQFZizE/Tra3fKvAoy037kOyU6cgz84n8f6zxngLOV4O32kTwt9FcLCxAqw0P/c8rOr9y+Gfg== + dependencies: + kleur "^3.0.2" + sisteransi "^1.0.0" + +protoduck@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f" + integrity sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg== + dependencies: + genfun "^5.0.0" + +proxy-addr@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" + integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.8.0" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.24: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.5.2, qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystringify@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +randomhex@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" + integrity sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU= + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + +raw-body@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + +rc-config-loader@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/rc-config-loader/-/rc-config-loader-2.0.4.tgz#fe23e26a87e2ec07541b29e7f37bfd75807a4c36" + integrity sha512-k06UzRbYDWgF4Mc/YrsZsmzSpDLuHoThJxep+vq5H09hiX8rbA5Ue/Ra0dwWm5MQvWYW4YBXgA186inNxuxidQ== + dependencies: + debug "^4.1.1" + js-yaml "^3.12.0" + json5 "^2.1.0" + object-assign "^4.1.0" + object-keys "^1.0.12" + path-exists "^3.0.0" + require-from-string "^2.0.2" + +rc@^1.2.7, rc@^1.2.8, rc@~1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +regenerator-runtime@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" + integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +registry-auth-token@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.0.0.tgz#30e55961eec77379da551ea5c4cf43cbf03522be" + integrity sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw== + dependencies: + rc "^1.2.8" + safe-buffer "^5.0.1" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +req-cwd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" + integrity sha1-DXOurpJm5penj3l2AZZ352rPD/8= + dependencies: + req-from "^1.0.1" + +req-from@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" + integrity sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4= + dependencies: + resolve-from "^2.0.0" + +request@^2.79.0, request@^2.85.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.0, require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +requireg@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/requireg/-/requireg-0.2.2.tgz#437e77a5316a54c9bcdbbf5d1f755fe093089830" + integrity sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg== + dependencies: + nested-error-stacks "~2.0.1" + rc "~1.2.7" + resolve "~1.7.1" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-dir@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + +resolve@^1.1.6: + version "1.9.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" + integrity sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ== + dependencies: + path-parse "^1.0.6" + +resolve@^1.10.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" + integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== + dependencies: + path-parse "^1.0.6" + +resolve@~1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== + dependencies: + path-parse "^1.0.5" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= + +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +rxjs@^6.4.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" + integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +scrypt-js@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" + integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= + +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== + +scrypt.js@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" + integrity sha1-r40UZbcemZARC+38WTuUeeA6ito= + dependencies: + scrypt "^6.0.2" + scryptsy "^1.2.1" + +scrypt.js@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.3.0.tgz#6c62d61728ad533c8c376a2e5e3e86d41a95c4c0" + integrity sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A== + dependencies: + scryptsy "^1.2.1" + optionalDependencies: + scrypt "^6.0.2" + +scrypt@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" + integrity sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0= + dependencies: + nan "^2.0.8" + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= + dependencies: + pbkdf2 "^3.0.3" + +seek-bzip@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= + dependencies: + commander "~2.8.1" + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= + dependencies: + semver "^5.0.3" + +semver-utils@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/semver-utils/-/semver-utils-1.1.4.tgz#cf0405e669a57488913909fc1c3f29bf2a4871e2" + integrity sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +semver@^5.0.3, semver@^5.4.1, semver@^5.5.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + +semver@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha3@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" + integrity sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k= + dependencies: + nan "2.10.0" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shelljs@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" + integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + +simple-get@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +sisteransi@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.2.tgz#ec57d64b6f25c4f26c0e2c7dd23f2d7f12f7e418" + integrity sha512-ZcYcZcT69nSLAR2oLN2JwNmLkJEKGooFMCdvOkFrToUt/WfcRWqhIg4P4KwY4dmLbuyXIx4o4YmPsvMRJYJd/w== + +smart-buffer@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d" + integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +socks-proxy-agent@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" + integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg== + dependencies: + agent-base "~4.2.1" + socks "~2.3.2" + +socks@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e" + integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ== + dependencies: + ip "^1.1.5" + smart-buffer "4.0.2" + +sol-digger@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" + integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= + +sol-explore@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" + integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= + +sol-explore@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" + integrity sha1-Q66MQZ/TrAVqBfip0fsQIs1B7MI= + +solc@0.5.8: + version "0.5.8" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.8.tgz#a0aa2714082fc406926f5cb384376d7408080611" + integrity sha512-RQ2SlwPBOBSV7ktNQJkvbiQks3t+3V9dsqD014EdstxnJzSxBuOvbt3P5QXpNPYW1DsEmF7dhOaT3JL7yEae/A== + dependencies: + command-exists "^1.2.8" + fs-extra "^0.30.0" + keccak "^1.0.2" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + yargs "^11.0.0" + +solidity-coverage@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.6.3.tgz#c7e7afa0792ae1fe3c6039735e2a0ad5cb2f0aca" + integrity sha512-mHc8xtcVZwkANAWQrOROyD7eAEE8L5kUE/3KEvNp/y7+zR1/u2f8ouNKp5hKeCAmHhm7df7X3pLGINmnKili9w== + dependencies: + death "^1.1.0" + ethereumjs-testrpc-sc "6.4.5-sc.3" + istanbul "^0.4.5" + keccakjs "^0.2.1" + req-cwd "^1.0.1" + shelljs "^0.8.3" + sol-explore "^1.6.2" + solidity-parser-antlr "^0.4.7" + tree-kill "^1.2.0" + web3 "1.0.0-beta.50" + web3-eth-abi "1.0.0-beta.50" + +solidity-parser-antlr@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.4.2.tgz#b862eba5936e7a90b4f5f1c8eb1d33fe86650f78" + integrity sha512-0OKT2YKZAqPe14HN7Nbo24hjmnyUYh92UjyZG0Zz2rpQhl/w8asX8qHb+ASSXfayQaiW8g9zGIupXEE355tOQQ== + +solidity-parser-antlr@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.4.7.tgz#8e18867c95a956958ed008371e43f9e571dee6af" + integrity sha512-iVjNhgqkXw+o+0E+xoLcji+3KuXLe8Rm8omUuVGhsV14+ZsTwQ70nhBRXg8O3t9xwdS0iST1q9NJ5IqHnqpWkA== + dependencies: + npm-check-updates "^3.1.11" + +solium-plugin-security@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" + integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== + +solparse@2.2.8, solparse@^2.2.8: + version "2.2.8" + resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" + integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== + dependencies: + mocha "^4.0.1" + pegjs "^0.10.0" + yargs "^10.0.3" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.9: + version "0.5.9" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" + integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= + dependencies: + amdefine ">=0.0.4" + +spawn-please@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/spawn-please/-/spawn-please-0.3.0.tgz#db338ec4cff63abc69f1d0e08cee9eb8bebd9d11" + integrity sha1-2zOOxM/2Orxp8dDgjO6euL69nRE= + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" + integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.0.tgz#1d4963a2fbffe58050aa9084ca20be81741c07de" + integrity sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^6.0.0, ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + dependencies: + is-natural-number "^4.0.1" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== + dependencies: + has-flag "^2.0.0" + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +swarm-js@0.1.39, swarm-js@^0.1.39: + version "0.1.39" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.39.tgz#79becb07f291d4b2a178c50fee7aa6e10342c0e8" + integrity sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + decompress "^4.0.0" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^7.1.0" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request-promise "^0.1.2" + +tar-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar@^4: + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.3.4" + minizlib "^1.1.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +tar@^4.0.2, tar@^4.4.8: + version "4.4.10" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" + integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.3.5" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= + dependencies: + execa "^0.7.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +"through@>=2.2.7 <3", through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +tmp@0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tree-kill@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" + integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +truffle-config@^1.1.17: + version "1.1.17" + resolved "https://registry.yarnpkg.com/truffle-config/-/truffle-config-1.1.17.tgz#5f411f453c34809f99373c6ef223608d6f3f4d6e" + integrity sha512-XayW+x0o3HrPY74UXkmD1kMhyRftXUzBb2UEE5aUnlLr4HEsY4OoJPoMecgwLoOqC3kRJNNXhHtJqJv6w9S1RA== + dependencies: + configstore "^4.0.0" + find-up "^2.1.0" + lodash "^4.17.13" + original-require "1.0.1" + truffle-error "^0.0.5" + truffle-provider "^0.1.13" + +truffle-error@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/truffle-error/-/truffle-error-0.0.5.tgz#6b5740c9f3aac74f47b85d654fff7fe2c1fc5e0e" + integrity sha512-JpzPLMPSCE0vaZ3vH5NO5u42GpMj/Y1SRBkQ6b69PSw3xMSH1umApN32cEcg1nnh8q5FNYc5FnKu0m4tiBffyQ== + +truffle-expect@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/truffle-expect/-/truffle-expect-0.0.9.tgz#d4f0e4aae06333c7c1e093c8f6c0355eb7f9b0c3" + integrity sha512-8ifOoAiRVHsmM8vsn4xATsa4zifTsRA3vt7rsz1ryP2JE+uUqavqQficdh2uVJoa/DIid6O7iZ7J1HtQsHikOQ== + +truffle-flattener@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/truffle-flattener/-/truffle-flattener-1.3.0.tgz#a5b0340897e32cf8389fea105b52fa93c335f04c" + integrity sha512-ppJ9xI0tDuvCYjQlcWwMBcOKZph5U4YpG/gChyUVDxOjUIniG5g7y9vZho2PRj1FohPPnOjg1KOAVNlk/bPZrw== + dependencies: + "@resolver-engine/imports-fs" "^0.2.2" + find-up "^2.1.0" + mkdirp "^0.5.1" + solidity-parser-antlr "^0.4.0" + tsort "0.0.1" + +truffle-hdwallet-provider@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.5.tgz#76059fb37d13df70bf37a9c296cf27d5a944e112" + integrity sha512-T9qNm7b6MD0UPWVmmJEhgzW1DdR6mkMDijGBSbdJqYaaBLufoycE+qH3dsV+m1mLTE+ebM5RcJ4gF4oXgDW67w== + dependencies: + any-promise "^1.3.0" + bindings "^1.3.1" + websocket "^1.0.28" + +truffle-interface-adapter@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/truffle-interface-adapter/-/truffle-interface-adapter-0.2.2.tgz#f2ca897b4769b2190e3fb03f09fb98a178362126" + integrity sha512-dAKN+mSOlQV/+PlzUhBH90RAWrbp0Avm8nQcALoTwKa35PkS5RyB2ir1Y0AVoZvKVFYOmRDt884KHpZe8YgJRA== + dependencies: + bn.js "^4.11.8" + ethers "^4.0.32" + lodash "^4.17.13" + web3 "^1.2.0" + +truffle-provider@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/truffle-provider/-/truffle-provider-0.1.13.tgz#e121dc190101e57db238b9283f8b1066a468bf15" + integrity sha512-zbO8fNLCHfcDyaC2MI+l5eybN2aUGBpVoQcEHGov2U5LD2F6GJP8Vb3gf/Eqb//X3kZSKaUfGmy32hc87qxvBA== + dependencies: + truffle-error "^0.0.5" + truffle-interface-adapter "^0.2.2" + web3 "^1.2.0" + +truffle-provisioner@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/truffle-provisioner/-/truffle-provisioner-0.1.5.tgz#f940b2e0aa3a26d5227dfc4ebe8d29ebc68a9e03" + integrity sha512-XSzD4Tj1T16E8qwoIHnQ9sOuvoemP1yqxX9Jg0VvvoLTdl8X17uau6dN08JgNR09hJroTrXPbkAi5Y8IfKhVMw== + +truffle-resolver@^5.0.0: + version "5.0.14" + resolved "https://registry.yarnpkg.com/truffle-resolver/-/truffle-resolver-5.0.14.tgz#f403f944bb77a02ca8c2da86dc27a82145641ba4" + integrity sha512-00Uhhm4PchDobtbgjr0e8j4LBAQoZuuS9guKTx3YGHYp10992KVJTsQ+7lZf0K4fGTA2OV/ON0BsN7Sj/xij/Q== + dependencies: + async "2.6.1" + detect-installed "^2.0.4" + get-installed-path "^4.0.8" + truffle-expect "^0.0.9" + truffle-provisioner "^0.1.5" + +truffle@^5.0.30: + version "5.0.30" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.30.tgz#13ac335939fc6c908c615c25cd94c7a56ba674d5" + integrity sha512-l13cUq5QUEPfW89b4dDBIahNmDWazpey4Y8UJXhNn+YTkHxVM5h8L8eNNIBTD1SiYerrXfw49QMIQubEcz3erA== + dependencies: + app-module-path "^2.2.0" + mocha "5.2.0" + original-require "1.0.1" + +tslib@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + +type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.18" + +typedarray-to-buffer@^3.1.2, typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uglify-js@^3.1.4: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbzip2-stream@^1.0.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" + integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw== + dependencies: + buffer "^3.0.1" + through "^2.3.6" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= + dependencies: + crypto-random-string "^1.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +update-notifier@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" + integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ== + dependencies: + boxen "^3.0.0" + chalk "^2.0.1" + configstore "^4.0.0" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.1.0" + is-npm "^3.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-parse@1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" + integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== + dependencies: + querystringify "^2.0.0" + requires-port "^1.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf8@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" + integrity sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g= + +utf8@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= + +uuid@3.3.2, uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= + dependencies: + builtins "^1.0.3" + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +web3-bzz@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.50.tgz#5e234eecf427b33f773c78c00e34d370b542f6b0" + integrity sha512-0jD4/g+apH7t87cA9gXoZpvvVW7OqQtbu+X+olFKPrS9pKbkwfaKPdRwc1BNbjqvrRYN0K7koT9xV+Lzvyah6w== + dependencies: + "@babel/runtime" "^7.3.1" + "@types/node" "^10.12.18" + lodash "^4.17.11" + swarm-js "^0.1.39" + +web3-bzz@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.0.tgz#eab70a2cf6c437223f40fc069499fe70ff53feb0" + integrity sha512-QEIdvguSEpqBK9b815nzx4yvpfKv/SAvaFeCMjQ0vjIVqFhAwBHDxd+f+X3nWGVRGVeOTP7864tau26CPBtQ8Q== + dependencies: + got "9.6.0" + swarm-js "0.1.39" + underscore "1.9.1" + +web3-core-helpers@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.50.tgz#0de88656ffa5f13659141cc443ff8529f109deac" + integrity sha512-B1LMrlC9c5HEJYmBWUhsxHdJ78w5YGop/ptF1cFL8cHLwTCQqCFFKLgYUg+dax/554TP1xgJ2w/ArLpnPJ8dBg== + dependencies: + "@babel/runtime" "^7.3.1" + lodash "^4.17.11" + web3-eth-iban "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-core-helpers@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.0.tgz#023947323cebd021e43a67145a5087627ce87fb3" + integrity sha512-KLCCP2FS1cMz23Y9l3ZaEDzaUky+GpsNavl4Hn1xX8lNaKcfgGEF+DgtAY/TfPQYAxLjLrSbIFUDzo9H/W1WAQ== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.0" + web3-utils "1.2.0" + +web3-core-method@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.50.tgz#4f9b55699f6e46f49dc8ac6bde204f9ae877b513" + integrity sha512-0+L37KDT90DD1fcTye/ZWMyGOLiw0ZxX2vaC8qDSFvAV3scTEuZyEQuR+tCM2aGyUVihy8LdmZwioRwnTXgLwg== + dependencies: + "@babel/runtime" "^7.3.1" + eventemitter3 "3.1.0" + lodash "^4.17.11" + +web3-core-method@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.0.tgz#9f6a6939d15f53bc74d086f280fbd62461546cd3" + integrity sha512-Iff5rCL+sgHe6zZVZijp818aRixKQf3ZAyQsT6ewER1r9yqXsH89DJtX33Xw8xiaYSwUFcpNs2j+Kluhv/eVAw== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.0" + web3-core-promievent "1.2.0" + web3-core-subscriptions "1.2.0" + web3-utils "1.2.0" + +web3-core-promievent@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.0.tgz#d6454837a307da5b453fe3077743fe25801a07a1" + integrity sha512-9THNYsZka91AX4LZGZvka5hio9+QlOY22hNgCiagmCmYytyKk3cXftL6CWefnNF7XgW8sy/ew5lzWLVsQW61Lw== + dependencies: + any-promise "1.3.0" + eventemitter3 "3.1.2" + +web3-core-requestmanager@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.0.tgz#a7f9995495340037e7ac72792c1885c35c1e7616" + integrity sha512-hPe1jyESodXAiE7qJglu7ySo4GINCn5CgG+9G1ATLQbriZsir83QMSeKQekv/hckKFIf4SvZJRPEBhtAle+Dhw== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.0" + web3-providers-http "1.2.0" + web3-providers-ipc "1.2.0" + web3-providers-ws "1.2.0" + +web3-core-subscriptions@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.50.tgz#73df7143062f915e02b153239af10974e350e20f" + integrity sha512-q2Jmuy/BCwcKCFjR6kc03hPbdC6sR0n3IhPVg98Sk7ewgRLur/v3lLDz0fQpY4xE6U0XOqrjxwzlqISkOcP5Kw== + dependencies: + "@babel/runtime" "^7.3.1" + eventemitter3 "^3.1.0" + lodash "^4.17.11" + +web3-core-subscriptions@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.0.tgz#d359b9b5fb6f6a700f1b383be11de7925cb7549f" + integrity sha512-DHipGH8It5E4HxxvymhkudcYhBVgGx6MwGWobIVKFgp6JRxtuvAbqwrMbuD/+78J6yXOa4y9zVXBk12dm2NXGg== + dependencies: + eventemitter3 "3.1.2" + underscore "1.9.1" + web3-core-helpers "1.2.0" + +web3-core@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.50.tgz#385137b8c34257db2679e925dfe41b98a0f7fe37" + integrity sha512-edOHdSnkRREi0vUXXNUsrbkTvXftCDroiF2tEvbPVyiBv0U6/VDYClFdHuZKdrrTRUcn/rUbvBqw8qCt3xgcuQ== + dependencies: + "@babel/runtime" "^7.3.1" + "@types/node" "^10.12.18" + lodash "^4.17.11" + web3-utils "1.0.0-beta.50" + +web3-core@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.0.tgz#6f3c59f84b2af9ab0ee7617d3c5208a814d3953c" + integrity sha512-Vy+fargzx94COdihE79zIM5lb/XAl/LJlgGdmz2a6QhgGZrSL8K6DKKNS+OuORAcLJN2PWNMc4IdfknkOw1PhQ== + dependencies: + web3-core-helpers "1.2.0" + web3-core-method "1.2.0" + web3-core-requestmanager "1.2.0" + web3-utils "1.2.0" + +web3-eth-abi@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.50.tgz#52ca509257648c6088aa9d8874d6ea5f249c6de7" + integrity sha512-Nwm1HL3xBbrs43j/9V3gH1CJWWR7jyTDSE7PIkjYVjwgygAjlHPMHzuzGffoFMp2tSQ2DywCGmXAY5I5+vznZw== + dependencies: + "@babel/runtime" "^7.3.1" + ethers "^4.0.27" + lodash "^4.17.11" + web3-utils "1.0.0-beta.50" + +web3-eth-abi@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.0.tgz#26b22261756ffbb3363bc37c1a6f5143bebb6469" + integrity sha512-FDuPq/tFeMg/D/f7cNSmvVYkMYb1z379gUUzSL8ZFtZrdHPkezq+lq/TmWmbCOMLYNXlhGJBzjGdLXRS4Upprg== + dependencies: + ethers "4.0.0-beta.3" + underscore "1.9.1" + web3-utils "1.2.0" + +web3-eth-accounts@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.50.tgz#e405979db8d4dc0caccff576fa746cea3d87e3d1" + integrity sha512-cUuYxKhymob87zCUYgw7ieZY6aVStMhClocblI3FKNdI1I8dczhdhZ97qMj5iavOganN7/OxLzeji7ksAoNAhg== + dependencies: + "@babel/runtime" "^7.3.1" + crypto-browserify "3.12.0" + eth-lib "0.2.8" + lodash "^4.17.11" + scrypt.js "0.2.0" + uuid "3.3.2" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-eth-accounts@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.0.tgz#bb26d5446017700a13b75fc69a2b1226fe44f6bb" + integrity sha512-d/fUAL3F6HqstvEiBnZ1RwZ77/DytgF9d6A3mWVvPOUk2Pqi77PM0adRvsKvIWUaQ/k6OoCk/oXtbzaO7CyGpg== + dependencies: + any-promise "1.3.0" + crypto-browserify "3.12.0" + eth-lib "0.2.7" + scrypt.js "^0.3.0" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.0" + web3-core-helpers "1.2.0" + web3-core-method "1.2.0" + web3-utils "1.2.0" + +web3-eth-contract@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.50.tgz#bc6d4523347e113c74c5e1c6c78219eeb61d9182" + integrity sha512-X8R1+qIeD4Dbz1RmQa5m3K1suVFigNgd7EFMp6vVC3ULDjt4R6T0cRmFw/x51v3MQoT7s6Yd1KiEWIAt9IYG6w== + dependencies: + "@babel/runtime" "^7.3.1" + lodash "^4.17.11" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-core-subscriptions "1.0.0-beta.50" + web3-eth-abi "1.0.0-beta.50" + web3-eth-accounts "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-eth-contract@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.0.tgz#8d1c235c6624b5df428969ea2e9c26337095f6f0" + integrity sha512-hfjozNbfsoMeR3QklfkwU0Mqcw6YRD4y1Cb1ghGWNhFy2+/sbvKcQNPPJDKFTde22PRzGQBWyh/nb422Sux4bQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.0" + web3-core-helpers "1.2.0" + web3-core-method "1.2.0" + web3-core-promievent "1.2.0" + web3-core-subscriptions "1.2.0" + web3-eth-abi "1.2.0" + web3-utils "1.2.0" + +web3-eth-ens@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.50.tgz#29304e42e2671ea755a19ab3f1011ad197f115da" + integrity sha512-UnhYcNuSNRBOBcbD5y8cTyRh5ENn65/GfZkxCDXAKBY6sD4GzMZNkD7kq+37/34cnZEzzQPPGd9jLZNLXOklyg== + dependencies: + "@babel/runtime" "^7.3.1" + eth-ens-namehash "2.0.8" + lodash "^4.17.11" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-eth-abi "1.0.0-beta.50" + web3-eth-contract "1.0.0-beta.50" + web3-net "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-eth-ens@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.0.tgz#af66308542f4acfa09ccd3ce370e3ad2de20ec30" + integrity sha512-kE6uHMLwH9dv+MZSKT7BcKXcQ6CcLP5m5mM44s2zg2e9Rl20F3J6R3Ik6sLc/w2ywdCwTe/Z22yEstHXQwu5ig== + dependencies: + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.0" + web3-core-helpers "1.2.0" + web3-core-promievent "1.2.0" + web3-eth-abi "1.2.0" + web3-eth-contract "1.2.0" + web3-utils "1.2.0" + +web3-eth-iban@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.50.tgz#311ea9422369ecbde6316e10a34de9fb07994cd6" + integrity sha512-rW5fpUUW3WaToPxBXNnqTfj5dh2BJ+9uognYAfThh2WWR1+EwWZethsKS/PyU6Jn9uA5p/kQoUIP0JKaeBm80Q== + dependencies: + "@babel/runtime" "^7.3.1" + bn.js "4.11.8" + web3-utils "1.0.0-beta.50" + +web3-eth-iban@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.0.tgz#1bece9cebf817dca82fa03230203351f4f263866" + integrity sha512-6DzTx/cvIgEvxadhJjLGpsuDUARA4RKskNOuwWYUsUODcPb50rsfMmRkHhGtLss/sNXVE5gNjbT9rX3TDqy2tg== + dependencies: + bn.js "4.11.8" + web3-utils "1.2.0" + +web3-eth-personal@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.50.tgz#891f55bb93c2e38918be085dcb295634a59b31b1" + integrity sha512-52dS24YfJxx/Uy21RKj2m5rjag1kktdy5rY/R9vDwWZRrJkxfDf058CvtRF+QsD7A6QVxkHCZ9YwEWnLCLW9Cw== + dependencies: + "@babel/runtime" "^7.3.1" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-net "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-eth-personal@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.0.tgz#7194f519c870d720eee1349d867408004f0f78af" + integrity sha512-8QdcaT6dbdiMC8zEqvDuij8XeI34r2GGdQYGvYBP2UgCm15EZBHgewxO30A+O+j2oIW1/Hu60zP5upnhCuA1Dw== + dependencies: + web3-core "1.2.0" + web3-core-helpers "1.2.0" + web3-core-method "1.2.0" + web3-net "1.2.0" + web3-utils "1.2.0" + +web3-eth@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.50.tgz#6da9246d36d65ba7ff03209419c571359eda0e0a" + integrity sha512-ojsddEclIdu+C3hfRrLVJK0rcxt2O+Yj7c3b4YEzZQ9+Kd/HaSZfeSpUgKojgmFhUUiCCRTEc2holWtQ+Lx4gQ== + dependencies: + "@babel/runtime" "^7.3.1" + eth-lib "0.2.8" + rxjs "^6.4.0" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-core-subscriptions "1.0.0-beta.50" + web3-eth-abi "1.0.0-beta.50" + web3-eth-accounts "1.0.0-beta.50" + web3-eth-contract "1.0.0-beta.50" + web3-eth-ens "1.0.0-beta.50" + web3-eth-iban "1.0.0-beta.50" + web3-eth-personal "1.0.0-beta.50" + web3-net "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-eth@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.0.tgz#ac8d3409356538d2fe1cb6151036b724eace76f6" + integrity sha512-GP1+hHS/IVW1tAOIDS44PxCpvSl9PBU/KAB40WgP27UMvSy43LjHxGlP6hQQOdIfmBLBTvGvn2n+Z5kW2gzAzg== + dependencies: + underscore "1.9.1" + web3-core "1.2.0" + web3-core-helpers "1.2.0" + web3-core-method "1.2.0" + web3-core-subscriptions "1.2.0" + web3-eth-abi "1.2.0" + web3-eth-accounts "1.2.0" + web3-eth-contract "1.2.0" + web3-eth-ens "1.2.0" + web3-eth-iban "1.2.0" + web3-eth-personal "1.2.0" + web3-net "1.2.0" + web3-utils "1.2.0" + +web3-net@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.50.tgz#1ca188b9210da6ae560bbd35a2b6dea1d2e68da7" + integrity sha512-T9aBrWYzCeqZTTJlljonTm8x1tEjHT1uBqcdvEYZoyCS1Xxc+zCNBqP4SBfdcfwCeGohhI7bRx9qX1JjYH3cRA== + dependencies: + "@babel/runtime" "^7.3.1" + lodash "^4.17.11" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-net@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.0.tgz#9e99c4326a28712451dc4d45f3acf26c1d4b3219" + integrity sha512-7iD8C6vvx8APXPMmlpPLGWjn4bsXHzd3BTdFzKjkoYjiiVFJdVAbY3j1BwN/6tVQu8Ay7sDpV2EdTNub7GKbyw== + dependencies: + web3-core "1.2.0" + web3-core-method "1.2.0" + web3-utils "1.2.0" + +web3-providers-http@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.0.tgz#c6ebf9b6a23564439fa3c4a431cd6b405cc1ec0f" + integrity sha512-UrUn6JSz7NVCZ+0nZZtC4cmbl5JIi57w1flL1jN8jgkfdWDdErNvTkSwCt/QYdTQscMaUtWXDDOSAsVO6YC64g== + dependencies: + web3-core-helpers "1.2.0" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.0.tgz#98b8b8c9e77935dabfcf6d16e66c783f2429eac8" + integrity sha512-T2OSbiqu7+dahbGG5YFEQM5+FXdLVvaTCKmHXaQpw8IuL5hw7HELtyFOtHVudgDRyw0tJKxIfAiX/v2F1IL1fQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.0" + +web3-providers-ws@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.0.tgz#c45929f0d1e1743301372e6e604aab63e83f66e3" + integrity sha512-rnwGcCe6cev5A6eG5UBCQqPmkJVZMCrK+HN1AvUCco0OHD/0asGc9LuLbtkQIyznA6Lzetq/OOcaTOM4KeT11g== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.0" + websocket "github:frozeman/WebSocket-Node#browserifyCompatible" + +web3-providers@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-providers/-/web3-providers-1.0.0-beta.50.tgz#41d7cd3c38f3b12f721c115fea1972a3d1904d25" + integrity sha512-p2xtr6N72pdXvND5dLdK1G9T/9qCQiKC2EYDPmimnqvoHWixmM3tlBl042swkHspHHVL60vXPKxB4UDaQE2hWQ== + dependencies: + "@babel/runtime" "^7.3.1" + "@types/node" "^10.12.18" + eventemitter3 "3.1.0" + lodash "^4.17.11" + url-parse "1.4.4" + websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" + xhr2-cookies "1.1.0" + +web3-shh@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.50.tgz#e5a4a64b2308267b1635858e4adcc92eeee147f1" + integrity sha512-a46Gz/YQdF3HJ4XK7rZh6bJiP3IEq+BDAvdxD1jW54yKM2k3RGarOY8hanC1crxKE7E9Q1UUkrp1Vjrj8XSQuQ== + dependencies: + "@babel/runtime" "^7.3.1" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-core-subscriptions "1.0.0-beta.50" + web3-net "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3-shh@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.0.tgz#c07c306d761f70782c64e2b5b119db54e16f301f" + integrity sha512-VFjS8kvsQBodudFmIoVJWvDNZosONJZZnhvktngD3POu5dwbJmSCl6lzbLJ2C5XjR15dF+JvSstAkWbM+2sdPg== + dependencies: + web3-core "1.2.0" + web3-core-method "1.2.0" + web3-core-subscriptions "1.2.0" + web3-net "1.2.0" + +web3-utils@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.50.tgz#ed12454d3d2727d3b77695c1899ad3abbef303af" + integrity sha512-xGhM/YkepK2x0iMYUl/sws58LzTbodjMGlhZxrCZLZxJ0DoaDyk3UdmZ6aCSCwVTFg4hlVj3doaIhWnwGfhhpQ== + dependencies: + "@babel/runtime" "^7.3.1" + "@types/bn.js" "^4.11.4" + "@types/node" "^10.12.18" + bn.js "4.11.8" + eth-lib "0.2.8" + ethjs-unit "^0.1.6" + lodash "^4.17.11" + number-to-bn "1.7.0" + randomhex "0.1.5" + utf8 "2.1.1" + +web3-utils@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.0.tgz#1f11b05d173b757d3f5ba32cb90b375a487d3bf0" + integrity sha512-tI1low8ICoaWU2c53cikH0rsksKuIskI2nycH5E5sEXxxl9/BOD3CeDDBFbxgNPQ+bpDevbR7gXNEDB7Ud4G9g== + dependencies: + bn.js "4.11.8" + eth-lib "0.2.7" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randomhex "0.1.5" + underscore "1.9.1" + utf8 "3.0.0" + +web3@1.0.0-beta.50: + version "1.0.0-beta.50" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.50.tgz#a82db1ac519e68696363eee46d9b233f52f37eed" + integrity sha512-N4YqT1jl2tZYNWiLk5gA5BMchHJaG76d65z899DT9UTR4iI6mfqe1QIE+1YLII1x+uE8ohFzBq/aaZ8praLeoA== + dependencies: + "@babel/runtime" "^7.3.1" + "@types/node" "^10.12.18" + web3-bzz "1.0.0-beta.50" + web3-core "1.0.0-beta.50" + web3-core-helpers "1.0.0-beta.50" + web3-core-method "1.0.0-beta.50" + web3-eth "1.0.0-beta.50" + web3-eth-personal "1.0.0-beta.50" + web3-net "1.0.0-beta.50" + web3-providers "1.0.0-beta.50" + web3-shh "1.0.0-beta.50" + web3-utils "1.0.0-beta.50" + +web3@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.0.tgz#ef9c43a99eac348a85c09179690290d45a96a5f2" + integrity sha512-iFrVAexsopX97x0ofBU/7HrCxzovf624qBkjBUeHZDf/G3Sb4tMQtjkCRc5lgVvzureq5SCqDiFDcqnw7eJ0bA== + dependencies: + web3-bzz "1.2.0" + web3-core "1.2.0" + web3-eth "1.2.0" + web3-eth-personal "1.2.0" + web3-net "1.2.0" + web3-shh "1.2.0" + web3-utils "1.2.0" + +websocket@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3" + integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA== + dependencies: + debug "^2.2.0" + nan "^2.11.0" + typedarray-to-buffer "^3.1.5" + yaeti "^0.0.6" + +"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": + version "1.0.26" + resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + dependencies: + debug "^2.2.0" + nan "^2.3.3" + typedarray-to-buffer "^3.1.2" + yaeti "^0.0.6" + +"websocket@github:frozeman/WebSocket-Node#browserifyCompatible": + version "1.0.26" + uid "6c72925e3f8aaaea8dc8450f97627e85263999f2" + resolved "https://codeload.github.com/frozeman/WebSocket-Node/tar.gz/6c72925e3f8aaaea8dc8450f97627e85263999f2" + dependencies: + debug "^2.2.0" + nan "^2.3.3" + typedarray-to-buffer "^3.1.2" + yaeti "^0.0.6" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.1.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= + +xhr-request-promise@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" + integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= + dependencies: + xhr-request "^1.0.1" + +xhr-request@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.3.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== + dependencies: + global "~4.3.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xml@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== + dependencies: + camelcase "^4.1.0" + +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= + dependencies: + camelcase "^4.1.0" + +yargs@11.1.0, yargs@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" + +yauzl@^2.4.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0"

zTK~kyO=O3;MO`h7a$Bh~qP@HKPvB?g=Qn)CDc!wM&0WoKzk$^{bC?`A&h(twny#IO zs}vyQ6bjaaW}m`omyEw}wT9$;ML+Wc4Y2txj%%OphmI;^9z#saT`RSPw|_6=St>5) z)Xgu9gl-xAKWxEFH8a3=K}P<$CMFc!o(vVhB>ZuZxGrm|=QG_PQ|?q-e=JszC}qf& zo*lHR!@VK94}Z1m+V!y-y*IGOs;MAs*Mq}2Xk*vrrF#}VjGLS0a&GOgO@`6UNXPBa zUHG_Pio}rS~0@!u~=Uwdwi7p*!& zQJN28KbA%fjJs!puKFGi>b->?5;?NNA<5q)<@o7A7+(ai+Eo*Lo+RLD7E|zP3kgHV zG+KwC4AuAsmN~9F%nlwW)RK-mo6+qP$*QHn{a)WPrXFdokrpNvtB*!H^#!Ugb>zk| z_tcOjT5CLiIG|3#4Q6)wv+#0sVlpMT#JU@&2yciJA`&!&h}ZowBngafchl|H9O8rD zLX!!X?XK@N^qL}M*U;^ncU=h$N&S(5U*^@4GH8Ba?JrRYa&RRU%+_5# z({yI8ZY9PP(N!}0kjeEMJ~__J&P6#pw;AxMItV+?La3of=>r8hPM87f7>A~N3sr@d zCMxef13U+(Nd3>(r0coT-k3S~ zF70vl+5bSmr?N^+<9RY?m)mlJeso;Vw5$54?%KE5FD0=zWhrb+XEnGZ4D^i{uI)LV z#6mK8z3x+883!YmF=w0pd|n8fH1xxijos@Ckv`^+j;79+K8>bc!sF8)tXx6)7Fahp#LNfZ^nWiox*RQS<@p71xMqFrZND12 zMB2VbyBWpx_ZclC05^B+&CvGq3Q_V{!T);rXaqLqe1!ApQGU|N%tc{^j4qu~UH03P zx}X9*+GEV}`*g%q>v70$_``?8Uux#ysI=>1m_#z#evmN{wuo>pA*_SjXlt8wQ6JII zx`KU9{AASMg^pEc_-NsmEYTu(;F$KnFUc-X%*ie{+IyE**swhEY*=~#*2l58u3?#K z-YMJiP{9rJ#kq{ZUw1MGUW7#G@Aj8J93DyLz8un^FuG_GOuNH*$99(-55P!Qf*w{Y z>b7-(aYv7@C?rlkY&R`g7cCkbXMQufc@t4<$8nyrJ2b4Tp6~u$w$5Uv2K*Vt7+R|bGvdNBldr;#icUJX_ZI!m5C1kZfEo0*AUnf zNDaJr?!(J#IwYFfdE_ z-VgC59S6Cl>LZ}iVds&isLzuMj#-ra5Z3^Ku%jUG7tyvL!?i*AL?O&aMkj95PF#??SGDXe4$+o@Y}9P15q&TSb&kb4(vM|m7S z&TEa{?skwItSajZ)-EPsCajE_)ye@Pc-e~c`}TB3m+;u4m*)eInwe7J9g5xab~~HV zkP9`9g|68>lfVXGehZjj;9-0^kS~2T=>ub2Brvcj4^Aq=!(Q&Fi|wnk(ypsQQa1$R)(nLp6WE z6ai!YySXPw2{FuX5ui?33uA=)C;bjfOCAk<5eT};Qmd8)IkpDW$<3e>BS1Pt?i6Yj zl9KvjGcZ≥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 z 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