Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x39AA39c021dfbaE8faC545936693aC917d5E7563
Balance 0 ETH
Nonce 1
Code Size 18970 bytes
Indexed Transactions 0 (1 on-chain, 1.3% indexed)
External Etherscan · Sourcify

Contract Bytecode

18970 bytes
0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80638f840ddd1161015c578063c37f68e2116100ce578063f3fdb15a11610087578063f3fdb15a14610708578063f5e3c46214610710578063f851a44014610746578063f8f9da281461074e578063fca7820b14610756578063fe9c44ae146107735761028a565b8063c37f68e214610626578063c5ebeaec14610672578063db006a751461068f578063dd62ed3e146106ac578063e9c714f2146106da578063f2b3abbd146106e25761028a565b8063a9059cbb11610120578063a9059cbb14610586578063aa5af0fd146105b2578063ae9d70b0146105ba578063b2a02ff1146105c2578063b71d1a0c146105f8578063bd6d894d1461061e5761028a565b80638f840ddd1461052b57806395d89b411461053357806395dd91931461053b578063a0712d6814610561578063a6afed951461057e5761028a565b80633af9e66911610200578063675d972c116101b9578063675d972c146104c85780636c540baf146104d05780636f307dc3146104d857806370a08231146104e057806373acee9814610506578063852a12e31461050e5761028a565b80633af9e669146104475780633b1d21a21461046d5780634576b5db1461047557806347bd37181461049b5780635fe3b567146104a3578063601a0bf1146104ab5761028a565b806318160ddd1161025257806318160ddd146103a9578063182df0f5146103b157806323b872dd146103b95780632608f818146103ef578063267822471461041b578063313ce5671461043f5761028a565b806306fdde031461028f578063095ea7b31461030c5780630e7527021461034c578063173b99041461037b57806317bfdfbc14610383575b600080fd5b61029761077b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d15781810151838201526020016102b9565b50505050905090810190601f1680156102fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103386004803603604081101561032257600080fd5b506001600160a01b038135169060200135610808565b604080519115158252519081900360200190f35b6103696004803603602081101561036257600080fd5b5035610875565b60408051918252519081900360200190f35b610369610888565b6103696004803603602081101561039957600080fd5b50356001600160a01b031661088e565b610369610951565b610369610957565b610338600480360360608110156103cf57600080fd5b506001600160a01b038135811691602081013590911690604001356109bd565b6103696004803603604081101561040557600080fd5b506001600160a01b038135169060200135610a29565b610423610a3c565b604080516001600160a01b039092168252519081900360200190f35b610369610a4b565b6103696004803603602081101561045d57600080fd5b50356001600160a01b0316610a51565b610369610abf565b6103696004803603602081101561048b57600080fd5b50356001600160a01b0316610ace565b610369610c23565b610423610c29565b610369600480360360208110156104c157600080fd5b5035610c38565b610369610cc6565b610369610ccc565b610423610cd2565b610369600480360360208110156104f657600080fd5b50356001600160a01b0316610ce1565b610369610cfc565b6103696004803603602081101561052457600080fd5b5035610db6565b610369610dc1565b610297610dc7565b6103696004803603602081101561055157600080fd5b50356001600160a01b0316610e1f565b6103696004803603602081101561057757600080fd5b5035610e7f565b610369610e8a565b6103386004803603604081101561059c57600080fd5b506001600160a01b038135169060200135611286565b6103696112f1565b6103696112f7565b610369600480360360608110156105d857600080fd5b506001600160a01b038135811691602081013590911690604001356115d1565b6103696004803603602081101561060e57600080fd5b50356001600160a01b031661188e565b610369611915565b61064c6004803603602081101561063c57600080fd5b50356001600160a01b03166119d0565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6103696004803603602081101561068857600080fd5b5035611a65565b610369600480360360208110156106a557600080fd5b5035611a70565b610369600480360360408110156106c257600080fd5b506001600160a01b0381358116916020013516611a7b565b610369611aa6565b610369600480360360208110156106f857600080fd5b50356001600160a01b0316611b95565b610423611bcf565b6103696004803603606081101561072657600080fd5b506001600160a01b03813581169160208101359160409091013516611bde565b610423611beb565b610369611bfa565b6103696004803603602081101561076c57600080fd5b5035611cd9565b610338611d13565b60018054604080516020600284861615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156108005780601f106107d557610100808354040283529160200191610800565b820191906000526020600020905b8154815290600101906020018083116107e357829003601f168201915b505050505081565b3360008181526010602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b600061088082611d18565b90505b919050565b60095481565b60008054600101808255816108a1610e8a565b146108f65760408051600160e51b62461bcd02815260206004820152601660248201527f61636372756520696e746572657374206661696c656400000000000000000000604482015290519081900360640190fd5b6108ff83610e1f565b91505b600054811461094b5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b50919050565b600e5481565b6000806000610964611d54565b9092509050600082600381111561097757fe5b146109b657604051600160e51b62461bcd0281526004018080602001828103825260358152602001806149626035913960400191505060405180910390fd5b9150505b90565b60008054600101808255816109d433878787611e02565b1491505b6000548114610a215760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b509392505050565b6000610a358383612116565b9392505050565b6005546001600160a01b031681565b60035481565b6000610a5b6146bb565b6040518060200160405280610a6e611915565b90526001600160a01b0384166000908152600f6020526040812054919250908190610a9a9084906121a6565b90925090506000826003811115610aad57fe5b14610ab757600080fd5b949350505050565b6000610ac96121fa565b905090565b6004546000906001600160a01b03163314610af657610aef6001603f61227d565b9050610883565b60065460408051600160e11b623f1ee902815290516001600160a01b0392831692851691627e3dd2916004808301926020929190829003018186803b158015610b3e57600080fd5b505afa158015610b52573d6000803e3d6000fd5b505050506040513d6020811015610b6857600080fd5b5051610bbe5760408051600160e51b62461bcd02815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d9281900390910190a160009392505050565b600c5481565b6006546001600160a01b031681565b6000805460010180825581610c4b610e8a565b90508015610c7157610c69816010811115610c6257fe5b603061227d565b925050610902565b610c7a846122e3565b925050600054811461094b5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b60085481565b600a5481565b6012546001600160a01b031681565b6001600160a01b03166000908152600f602052604090205490565b6000805460010180825581610d0f610e8a565b14610d645760408051600160e51b62461bcd02815260206004820152601660248201527f61636372756520696e746572657374206661696c656400000000000000000000604482015290519081900360640190fd5b600c5491506000548114610db25760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b5090565b600061088082612467565b600d5481565b6002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156108005780601f106107d557610100808354040283529160200191610800565b6000806000610e2d846124a4565b90925090506000826003811115610e4057fe5b14610a3557604051600160e51b62461bcd0281526004018080602001828103825260378152602001806148366037913960400191505060405180910390fd5b600061088082612558565b6000610e946146ce565b6007546001600160a01b03166315f24053610ead6121fa565b600c54600d546040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b158015610ef457600080fd5b505afa158015610f08573d6000803e3d6000fd5b505050506040513d6040811015610f1e57600080fd5b50805160209182015160408401819052918301526601c6bf526340001015610f905760408051600160e51b62461bcd02815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b602081015115610fb357610fab600560028360200151612593565b9150506109ba565b610fbb6125f9565b60608201819052600a54610fcf91906125fd565b6080830181905282826003811115610fe357fe5b6003811115610fee57fe5b905250600090508151600381111561100257fe5b1461100957fe5b611029604051806020016040528083604001518152508260800151612620565b60a083018190528282600381111561103d57fe5b600381111561104857fe5b905250600090508151600381111561105c57fe5b1461107d57610fab600960068360000151600381111561107857fe5b612593565b61108d8160a00151600c546121a6565b60c08301819052828260038111156110a157fe5b60038111156110ac57fe5b90525060009050815160038111156110c057fe5b146110dc57610fab600960018360000151600381111561107857fe5b6110ec8160c00151600c54612688565b60e083018190528282600381111561110057fe5b600381111561110b57fe5b905250600090508151600381111561111f57fe5b1461113b57610fab600960048360000151600381111561107857fe5b61115c60405180602001604052806009548152508260c00151600d546126ae565b61010083018190528282600381111561117157fe5b600381111561117c57fe5b905250600090508151600381111561119057fe5b146111ac57610fab600960058360000151600381111561107857fe5b6111bf8160a00151600b54600b546126ae565b6101208301819052828260038111156111d457fe5b60038111156111df57fe5b90525060009050815160038111156111f357fe5b1461120f57610fab600960038360000151600381111561107857fe5b606080820151600a55610120820151600b81905560e0830151600c819055610100840151600d5560c08401516040805191825260208201939093528083019190915290517f875352fb3fadeb8c0be7cbbe8ff761b308fa7033470cd0287f02f3436fd76cb9929181900390910190a1600091505090565b600080546001018082558161129d33338787611e02565b1491505b60005481146112ea5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b5092915050565b600b5481565b600080611302610957565b60075490915060009081906001600160a01b03166315f240536113236121fa565b600c54600d546040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b15801561136a57600080fd5b505afa15801561137e573d6000803e3d6000fd5b505050506040513d604081101561139457600080fd5b508051602090910151909250905081156113e257604051600160e51b62461bcd0281526004018080602001828103825260318152602001806148d56031913960400191505060405180910390fd5b60006113ec6146bb565b611406604051806020016040528087815250600e54612620565b9092509050600082600381111561141957fe5b1461145857604051600160e51b62461bcd02815260040180806020018281038252603181526020018061486d6031913960400191505060405180910390fd5b60006114626146bb565b61146e600c548461270a565b9092509050600082600381111561148157fe5b146114c057604051600160e51b62461bcd0281526004018080602001828103825260318152602001806147b16031913960400191505060405180910390fd5b60006114ca6146bb565b6114fa6040518060200160405280670de0b6b3a76400008152506040518060200160405280600954815250612769565b9092509050600082600381111561150d57fe5b1461154c57604051600160e51b62461bcd02815260040180806020018281038252603c815260200180614926603c913960400191505060405180910390fd5b60006115566146bb565b61156f60405180602001604052808b81525084876127a3565b9092509050600082600381111561158257fe5b146115c157604051600160e51b62461bcd0281526004018080602001828103825260318152602001806148056031913960400191505060405180910390fd5b519a505050505050505050505090565b6000805460010180825560065460408051600160e01b63d02f73510281523060048201523360248201526001600160a01b03888116604483015287811660648301526084820187905291518593929092169163d02f73519160a48082019260209290919082900301818787803b15801561164a57600080fd5b505af115801561165e573d6000803e3d6000fd5b505050506040513d602081101561167457600080fd5b5051905080156116935761168b6003601b83612593565b9250506109d8565b856001600160a01b0316856001600160a01b031614156116b95761168b6006601c61227d565b6001600160a01b0385166000908152600f6020526040812054819081906116e090886125fd565b909350915060008360038111156116f357fe5b146117165761170b6009601a85600381111561107857fe5b9550505050506109d8565b6001600160a01b0389166000908152600f60205260409020546117399088612688565b9093509050600083600381111561174c57fe5b146117645761170b6009601985600381111561107857fe5b6001600160a01b038089166000818152600f60209081526040808320879055938d168083529184902085905583518b815293519193600080516020614906833981519152929081900390910190a360065460408051600160e01b636d35bf910281523060048201523360248201526001600160a01b038c811660448301528b81166064830152608482018b905291519190921691636d35bf919160a480830192600092919082900301818387803b15801561181e57600080fd5b505af1158015611832573d6000803e3d6000fd5b506000925061183f915050565b9550505050506000548114610a215760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b6004546000906001600160a01b031633146118af57610aef6001604561227d565b600580546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a16000610a35565b6000805460010180825581611928610e8a565b1461197d5760408051600160e51b62461bcd02815260206004820152601660248201527f61636372756520696e746572657374206661696c656400000000000000000000604482015290519081900360640190fd5b611985610957565b91506000548114610db25760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b6001600160a01b0381166000908152600f60205260408120548190819081908180806119fb896124a4565b935090506000816003811115611a0d57fe5b14611a2b5760095b975060009650869550859450611a5e9350505050565b611a33611d54565b925090506000816003811115611a4557fe5b14611a51576009611a15565b5060009650919450925090505b9193509193565b6000610880826127ed565b600061088082612828565b6001600160a01b03918216600090815260106020908152604080832093909416825291909152205490565b6005546000906001600160a01b031633141580611ac1575033155b15611ad957611ad26001600061227d565b90506109ba565b60048054600580546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600554604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600080611ba0610e8a565b90508015611bc657611bbe816010811115611bb757fe5b604061227d565b915050610883565b610a358361285e565b6007546001600160a01b031681565b6000610ab78484846129d1565b6004546001600160a01b031681565b600754600090819081906001600160a01b03166315f24053611c1a6121fa565b600c54600d546040518463ffffffff1660e01b8152600401808481526020018381526020018281526020019350505050604080518083038186803b158015611c6157600080fd5b505afa158015611c75573d6000803e3d6000fd5b505050506040513d6040811015611c8b57600080fd5b508051602090910151909250905081156109b657604051600160e51b62461bcd02815260040180806020018281038252603781526020018061489e6037913960400191505060405180910390fd5b6000805460010180825581611cec610e8a565b90508015611d0a57610c69816010811115611d0357fe5b604661227d565b610c7a84612adf565b600181565b6000805460010180825581611d2b610e8a565b90508015611d4957610c69816010811115611d4257fe5b603661227d565b610c7a333386612b82565b600080600e5460001415611d6f575050600854600090611dfe565b6000611d796121fa565b90506000611d856146bb565b6000611d9684600c54600d54612fde565b935090506000816003811115611da857fe5b14611dbc57945060009350611dfe92505050565b611dc883600e5461301c565b925090506000816003811115611dda57fe5b14611dee57945060009350611dfe92505050565b5051600094509250611dfe915050565b9091565b60065460408051600160e31b6317b9b84b0281523060048201526001600160a01b03868116602483015285811660448301526064820185905291516000938493169163bdcdc25891608480830192602092919082900301818787803b158015611e6a57600080fd5b505af1158015611e7e573d6000803e3d6000fd5b505050506040513d6020811015611e9457600080fd5b505190508015611eb357611eab6003604a83612593565b915050610ab7565b836001600160a01b0316856001600160a01b03161415611ed957611eab6002604b61227d565b60006001600160a01b038781169087161415611ef85750600019611f20565b506001600160a01b038086166000908152601060209081526040808320938a16835292905220545b600080600080611f3085896125fd565b90945092506000846003811115611f4357fe5b14611f6157611f546009604b61227d565b9650505050505050610ab7565b6001600160a01b038a166000908152600f6020526040902054611f8490896125fd565b90945091506000846003811115611f9757fe5b14611fa857611f546009604c61227d565b6001600160a01b0389166000908152600f6020526040902054611fcb9089612688565b90945090506000846003811115611fde57fe5b14611fef57611f546009604d61227d565b6001600160a01b03808b166000908152600f6020526040808220859055918b168152208190556000198514612047576001600160a01b03808b166000908152601060209081526040808320938f168352929052208390555b886001600160a01b03168a6001600160a01b03166000805160206149068339815191528a6040518082815260200191505060405180910390a360065460408051600160e11b63352b4a3f0281523060048201526001600160a01b038d811660248301528c81166044830152606482018c905291519190921691636a56947e91608480830192600092919082900301818387803b1580156120e657600080fd5b505af11580156120fa573d6000803e3d6000fd5b5060009250612107915050565b9b9a5050505050505050505050565b6000805460010180825581612129610e8a565b9050801561214f5761214781601081111561214057fe5b603561227d565b9250506112a1565b61215a338686612b82565b92505060005481146112ea5760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b60008060006121b36146bb565b6121bd8686612620565b909250905060008260038111156121d057fe5b146121e157509150600090506121f3565b60006121ec826130cc565b9350935050505b9250929050565b60125460408051600160e01b6370a0823102815230600482015290516000926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b15801561224b57600080fd5b505afa15801561225f573d6000803e3d6000fd5b505050506040513d602081101561227557600080fd5b505191505090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360108111156122ac57fe5b83604d8111156122b857fe5b604080519283526020830191909152600082820152519081900360600190a1826010811115610a3557fe5b600454600090819081906001600160a01b03163314612311576123086001603161227d565b92505050610883565b6123196125f9565b600a541461232d57612308600a603361227d565b836123366121fa565b101561234857612308600e603261227d565b600d5484111561235e576123086002603461227d565b50600d54838103908111156123a757604051600160e51b62461bcd0281526004018080602001828103825260248152602001806149cb6024913960400191505060405180910390fd5b600d8190556004546123c2906001600160a01b0316856130db565b915060008260108111156123d257fe5b1461241157604051600160e51b62461bcd0281526004018080602001828103825260238152602001806147e26023913960400191505060405180910390fd5b600454604080516001600160a01b03909216825260208201869052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e9181900360600190a16000949350505050565b600080546001018082558161247a610e8a565b9050801561249857610c6981601081111561249157fe5b602761227d565b610c7a3360008661319a565b6001600160a01b0381166000908152601160205260408120805482918291829182916124db57506000945084935061255392505050565b6124eb8160000154600b546136af565b909450925060008460038111156124fe57fe5b14612513575091935060009250612553915050565b6125218382600101546136ee565b9094509150600084600381111561253457fe5b14612549575091935060009250612553915050565b5060009450925050505b915091565b600080546001018082558161256b610e8a565b9050801561258957610c6981601081111561258257fe5b601e61227d565b610c7a3385613719565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08460108111156125c257fe5b84604d8111156125ce57fe5b604080519283526020830191909152818101859052519081900360600190a1836010811115610ab757fe5b4390565b6000808383116126145750600090508183036121f3565b506003905060006121f3565b600061262a6146bb565b60008061263b8660000151866136af565b9092509050600082600381111561264e57fe5b1461266d575060408051602081019091526000815290925090506121f3565b60408051602081019091529081526000969095509350505050565b6000808383018481106126a0576000925090506121f3565b5060029150600090506121f3565b60008060006126bb6146bb565b6126c58787612620565b909250905060008260038111156126d857fe5b146126e95750915060009050612702565b6126fb6126f5826130cc565b86612688565b9350935050505b935093915050565b60006127146146bb565b600080612729670de0b6b3a7640000876136af565b9092509050600082600381111561273c57fe5b1461275b575060408051602081019091526000815290925090506121f3565b6121ec81866000015161301c565b60006127736146bb565b600080612788866000015186600001516125fd565b60408051602081019091529081529097909650945050505050565b60006127ad6146bb565b60006127b76146bb565b6127c18787613b67565b909250905060008260038111156127d457fe5b146127e3579092509050612702565b6126fb8186613b67565b6000805460010180825581612800610e8a565b9050801561281e57610c6981601081111561281757fe5b600861227d565b610c7a3385613c50565b600080546001018082558161283b610e8a565b9050801561285257610c6981601081111561249157fe5b610c7a3385600061319a565b60045460009081906001600160a01b0316331461288157611bbe6001604261227d565b6128896125f9565b600a541461289d57611bbe600a604161227d565b600760009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156128ee57600080fd5b505afa158015612902573d6000803e3d6000fd5b505050506040513d602081101561291857600080fd5b505161296e5760408051600160e51b62461bcd02815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a16000610a35565b60008054600101808255816129e4610e8a565b90508015612a025761168b8160108111156129fb57fe5b600f61227d565b836001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612a3d57600080fd5b505af1158015612a51573d6000803e3d6000fd5b505050506040513d6020811015612a6757600080fd5b505190508015612a875761168b816010811115612a8057fe5b601061227d565b612a9333878787613fbf565b9250506000548114610a215760408051600160e51b62461bcd02815260206004820152600a6024820152600160b21b691c994b595b9d195c995902604482015290519081900360640190fd5b6004546000906001600160a01b03163314612b0057610aef6001604761227d565b612b086125f9565b600a5414612b1c57610aef600a604861227d565b670de0b6b3a7640000821115612b3857610aef6002604961227d565b6009805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a16000610a35565b60065460408051600160e11b63120045310281523060048201526001600160a01b0386811660248301528581166044830152606482018590529151600093849316916324008a6291608480830192602092919082900301818787803b158015612bea57600080fd5b505af1158015612bfe573d6000803e3d6000fd5b505050506040513d6020811015612c1457600080fd5b505190508015612c3357612c2b6003603883612593565b915050610a35565b612c3b6125f9565b600a5414612c4f57612c2b600a603961227d565b612c57614728565b6001600160a01b0385166000908152601160205260409020600101546060820152612c81856124a4565b6080830181905260208301826003811115612c9857fe5b6003811115612ca357fe5b9052506000905081602001516003811115612cba57fe5b14612cdf57612cd6600960378360200151600381111561107857fe5b92505050610a35565b600019841415612cf85760808101516040820152612d00565b604081018490525b612d0e8682604001516144b3565b81906010811115612d1b57fe5b90816010811115612d2857fe5b905250600081516010811115612d3a57fe5b14612d4c578051612cd690603c61227d565b612d5e816080015182604001516125fd565b60a0830181905260208301826003811115612d7557fe5b6003811115612d8057fe5b9052506000905081602001516003811115612d9757fe5b14612db357612cd66009603a8360200151600381111561107857fe5b612dc3600c5482604001516125fd565b60c0830181905260208301826003811115612dda57fe5b6003811115612de557fe5b9052506000905081602001516003811115612dfc57fe5b14612e1857612cd66009603b8360200151600381111561107857fe5b612e268682604001516145ea565b81906010811115612e3357fe5b90816010811115612e4057fe5b905250600081516010811115612e5257fe5b14612ea75760408051600160e51b62461bcd02815260206004820152601f60248201527f726570617920626f72726f77207472616e7366657220696e206661696c656400604482015290519081900360640190fd5b60a080820180516001600160a01b03808916600081815260116020908152604091829020948555600b5460019095019490945560c0870151600c8190558188015195518251948e16855294840192909252828101949094526060820192909252608081019190915290517f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a1929181900390910190a160065460408083015160608401518251600160e01b631ededc910281523060048201526001600160a01b038b811660248301528a81166044830152606482019390935260848101919091529151921691631ededc919160a48082019260009290919082900301818387803b158015612fb357600080fd5b505af1158015612fc7573d6000803e3d6000fd5b5060009250612fd4915050565b9695505050505050565b600080600080612fee8787612688565b9092509050600082600381111561300157fe5b146130125750915060009050612702565b6126fb81866125fd565b60006130266146bb565b60008061303b86670de0b6b3a76400006136af565b9092509050600082600381111561304e57fe5b1461306d575060408051602081019091526000815290925090506121f3565b60008061307a83886136ee565b9092509050600082600381111561308d57fe5b146130af575060408051602081019091526000815290945092506121f3915050565b604080516020810190915290815260009890975095505050505050565b51670de0b6b3a7640000900490565b60125460408051600160e01b63a9059cbb0281526001600160a01b03858116600483015260248201859052915160009392909216918391839163a9059cbb91604480820192869290919082900301818387803b15801561313a57600080fd5b505af115801561314e573d6000803e3d6000fd5b505050503d60008114613168576020811461317257600080fd5b600019915061317e565b60206000803e60005191505b508061318f5760109250505061086f565b506000949350505050565b60008215806131a7575081155b6131e557604051600160e51b62461bcd0281526004018080602001828103825260348152602001806149976034913960400191505060405180910390fd5b6131ed614728565b6131f5611d54565b604083018190526020830182600381111561320c57fe5b600381111561321757fe5b905250600090508160200151600381111561322e57fe5b1461324a57612c2b6009602b8360200151600381111561107857fe5b83156132cb57606081018490526040805160208101825290820151815261327190856121a6565b608083018190526020830182600381111561328857fe5b600381111561329357fe5b90525060009050816020015160038111156132aa57fe5b146132c657612c2b600960298360200151600381111561107857fe5b613344565b6132e783604051806020016040528084604001518152506146a4565b60608301819052602083018260038111156132fe57fe5b600381111561330957fe5b905250600090508160200151600381111561332057fe5b1461333c57612c2b6009602a8360200151600381111561107857fe5b608081018390525b600654606082015160408051600160e01b63eabe7d910281523060048201526001600160a01b03898116602483015260448201939093529051600093929092169163eabe7d919160648082019260209290919082900301818787803b1580156133ac57600080fd5b505af11580156133c0573d6000803e3d6000fd5b505050506040513d60208110156133d657600080fd5b5051905080156133ed57612cd66003602883612593565b6133f56125f9565b600a541461340957612cd6600a602c61227d565b613419600e5483606001516125fd565b60a084018190526020840182600381111561343057fe5b600381111561343b57fe5b905250600090508260200151600381111561345257fe5b1461346e57612cd66009602e8460200151600381111561107857fe5b6001600160a01b0386166000908152600f6020526040902054606083015161349691906125fd565b60c08401819052602084018260038111156134ad57fe5b60038111156134b857fe5b90525060009050826020015160038111156134cf57fe5b146134eb57612cd66009602d8460200151600381111561107857fe5b81608001516134f86121fa565b101561350a57612cd6600e602f61227d565b6135188683608001516130db565b8290601081111561352557fe5b9081601081111561353257fe5b90525060008251601081111561354457fe5b146135995760408051600160e51b62461bcd02815260206004820152601a60248201527f72656465656d207472616e73666572206f7574206661696c6564000000000000604482015290519081900360640190fd5b60a0820151600e5560c08201516001600160a01b0387166000818152600f6020908152604091829020939093556060850151815190815290513093600080516020614906833981519152928290030190a36080820151606080840151604080516001600160a01b038b168152602081019490945283810191909152517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299281900390910190a16006546080830151606084015160408051600160e01b6351dff9890281523060048201526001600160a01b038b81166024830152604482019490945260648101929092525191909216916351dff98991608480830192600092919082900301818387803b158015612fb357600080fd5b600080836136c2575060009050806121f3565b838302838582816136cf57fe5b04146136e3575060029150600090506121f3565b6000925090506121f3565b6000808261370257506001905060006121f3565b600083858161370d57fe5b04915091509250929050565b60065460408051600160e01b634ef4c3e10281523060048201526001600160a01b03858116602483015260448201859052915160009384931691634ef4c3e191606480830192602092919082900301818787803b15801561377957600080fd5b505af115801561378d573d6000803e3d6000fd5b505050506040513d60208110156137a357600080fd5b5051905080156137c2576137ba6003601f83612593565b91505061086f565b6137ca6125f9565b600a54146137de576137ba600a602261227d565b6137e6614766565b6137f085856144b3565b819060108111156137fd57fe5b9081601081111561380a57fe5b90525060008151601081111561381c57fe5b1461383757805161382e90602661227d565b9250505061086f565b61383f611d54565b604083018190526020830182600381111561385657fe5b600381111561386157fe5b905250600090508160200151600381111561387857fe5b146138945761382e600960218360200151600381111561107857fe5b6138b084604051806020016040528084604001518152506146a4565b60608301819052602083018260038111156138c757fe5b60038111156138d257fe5b90525060009050816020015160038111156138e957fe5b146139055761382e600960208360200151600381111561107857fe5b613915600e548260600151612688565b608083018190526020830182600381111561392c57fe5b600381111561393757fe5b905250600090508160200151600381111561394e57fe5b1461396a5761382e600960248360200151600381111561107857fe5b6001600160a01b0385166000908152600f602052604090205460608201516139929190612688565b60a08301819052602083018260038111156139a957fe5b60038111156139b457fe5b90525060009050816020015160038111156139cb57fe5b146139e75761382e600960238360200151600381111561107857fe5b6139f185856145ea565b819060108111156139fe57fe5b90816010811115613a0b57fe5b905250600081516010811115613a1d57fe5b14613a2f57805161382e90602561227d565b6080810151600e5560a08101516001600160a01b0386166000818152600f602090815260409182902093909355606080850151825193845293830188905282820193909352517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f929181900390910190a1606081015160408051918252516001600160a01b0387169130916000805160206149068339815191529181900360200190a3600654606082015160408051600160e01b6341c728b90281523060048201526001600160a01b038981166024830152604482018990526064820193909352905191909216916341c728b991608480830192600092919082900301818387803b158015613b3d57600080fd5b505af1158015613b51573d6000803e3d6000fd5b5060009250613b5e915050565b95945050505050565b6000613b716146bb565b600080613b86866000015186600001516136af565b90925090506000826003811115613b9957fe5b14613bb8575060408051602081019091526000815290925090506121f3565b600080613bcd6706f05b59d3b2000084612688565b90925090506000826003811115613be057fe5b14613c02575060408051602081019091526000815290945092506121f3915050565b600080613c1783670de0b6b3a76400006136ee565b90925090506000826003811115613c2a57fe5b14613c3157fe5b604080516020810190915290815260009a909950975050505050505050565b60065460408051600160e21b63368f51530281523060048201526001600160a01b0385811660248301526044820185905291516000938493169163da3d454c91606480830192602092919082900301818787803b158015613cb057600080fd5b505af1158015613cc4573d6000803e3d6000fd5b505050506040513d6020811015613cda57600080fd5b505190508015613cf1576137ba6003600e83612593565b613cf96125f9565b600a5414613d0c576137ba600a8061227d565b82613d156121fa565b1015613d27576137ba600e600961227d565b613d2f614780565b613d38856124a4565b6040830181905260208301826003811115613d4f57fe5b6003811115613d5a57fe5b9052506000905081602001516003811115613d7157fe5b14613d8d5761382e600960078360200151600381111561107857fe5b613d9b816040015185612688565b6060830181905260208301826003811115613db257fe5b6003811115613dbd57fe5b9052506000905081602001516003811115613dd457fe5b14613df05761382e6009600c8360200151600381111561107857fe5b613dfc600c5485612688565b6080830181905260208301826003811115613e1357fe5b6003811115613e1e57fe5b9052506000905081602001516003811115613e3557fe5b14613e515761382e6009600b8360200151600381111561107857fe5b613e5b85856130db565b81906010811115613e6857fe5b90816010811115613e7557fe5b905250600081516010811115613e8757fe5b14613edc5760408051600160e51b62461bcd02815260206004820152601a60248201527f626f72726f77207472616e73666572206f7574206661696c6564000000000000604482015290519081900360640190fd5b606080820180516001600160a01b038816600081815260116020908152604091829020938455600b54600190940193909355608080870151600c819055945182519384529383018a9052828201939093529381019290925291517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab80929181900390910190a160065460408051600160e01b635c7786050281523060048201526001600160a01b0388811660248301526044820188905291519190921691635c77860591606480830192600092919082900301818387803b158015613b3d57600080fd5b60065460408051600160e11b632fe3f38f0281523060048201526001600160a01b0384811660248301528781166044830152868116606483015260848201869052915160009384931691635fc7e71e9160a480830192602092919082900301818787803b15801561402f57600080fd5b505af1158015614043573d6000803e3d6000fd5b505050506040513d602081101561405957600080fd5b50519050801561407057611eab6003601283612593565b6140786125f9565b600a541461408c57611eab600a601661227d565b6140946125f9565b836001600160a01b0316636c540baf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156140cd57600080fd5b505afa1580156140e1573d6000803e3d6000fd5b505050506040513d60208110156140f757600080fd5b50511461410a57611eab600a601161227d565b856001600160a01b0316856001600160a01b0316141561413057611eab6006601761227d565b8361414157611eab6007601561227d565b60001984141561415757611eab6007601461227d565b60065460408051600160e01b63c488847b0281523060048201526001600160a01b038681166024830152604482018890528251600094859492169263c488847b926064808301939192829003018186803b1580156141b457600080fd5b505afa1580156141c8573d6000803e3d6000fd5b505050506040513d60408110156141de57600080fd5b50805160209091015190925090508115614209576141ff6004601384612593565b9350505050610ab7565b846001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561425f57600080fd5b505afa158015614273573d6000803e3d6000fd5b505050506040513d602081101561428957600080fd5b505181111561429e576141ff600d601d61227d565b60006142ab898989612b82565b905080156142d4576142c98160108111156142c257fe5b601861227d565b945050505050610ab7565b60408051600160e01b63b2a02ff10281526001600160a01b038b811660048301528a8116602483015260448201859052915160009289169163b2a02ff191606480830192602092919082900301818787803b15801561433257600080fd5b505af1158015614346573d6000803e3d6000fd5b505050506040513d602081101561435c57600080fd5b5051905080156143b65760408051600160e51b62461bcd02815260206004820152601460248201527f746f6b656e207365697a757265206661696c6564000000000000000000000000604482015290519081900360640190fd5b604080516001600160a01b03808d168252808c1660208301528183018b9052891660608201526080810185905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a160065460408051600160e01b6347ef3b3b0281523060048201526001600160a01b038a811660248301528d811660448301528c81166064830152608482018c905260a48201879052915191909216916347ef3b3b9160c480830192600092919082900301818387803b15801561448457600080fd5b505af1158015614498573d6000803e3d6000fd5b50600092506144a5915050565b9a9950505050505050505050565b60125460408051600160e11b636eb1769f0281526001600160a01b038581166004830152306024830152915160009392909216918491839163dd62ed3e91604480820192602092909190829003018186803b15801561451157600080fd5b505afa158015614525573d6000803e3d6000fd5b505050506040513d602081101561453b57600080fd5b5051101561454d57600c91505061086f565b82816001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156145a457600080fd5b505afa1580156145b8573d6000803e3d6000fd5b505050506040513d60208110156145ce57600080fd5b505110156145e057600d91505061086f565b5060009392505050565b60125460408051600160e01b6323b872dd0281526001600160a01b0385811660048301523060248301526044820185905291516000939290921691839183916323b872dd91606480820192869290919082900301818387803b15801561464f57600080fd5b505af1158015614663573d6000803e3d6000fd5b505050503d6000811461467d576020811461468757600080fd5b6000199150614693565b60206000803e60005191505b508061318f57600f9250505061086f565b60008060006146b16146bb565b6121bd868661270a565b6040518060200160405280600081525090565b6040805161014081019091528060008152602001600081526020016000815260200160008152602001600081526020016147066146bb565b8152602001600081526020016000815260200160008152602001600081525090565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160c0810190915280600081526020016000614706565b6040805160a08101909152806000815260200160008152602001600081526020016000815260200160008152509056fe737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720626f72726f7773506572206661696c6564726564756365207265736572766573207472616e73666572206f7574206661696c6564737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720737570706c7952617465206661696c6564626f72726f7742616c616e636553746f7265643a20626f72726f7742616c616e636553746f726564496e7465726e616c206661696c6564737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720756e6465726c79696e67206661696c6564626f72726f7752617465506572426c6f636b3a20696e746572657374526174654d6f64656c2e626f72726f7752617465206661696c6564737570706c7952617465506572426c6f636b3a2063616c63756c6174696e6720626f72726f7752617465206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef737570706c7952617465506572426c6f636b3a2063616c63756c6174696e67206f6e654d696e757352657365727665466163746f72206661696c656465786368616e67655261746553746f7265643a2065786368616e67655261746553746f726564496e7465726e616c206661696c65646f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726f72656475636520726573657276657320756e657870656374656420756e646572666c6f77a165627a7a72305820ae92d0e3e70b657d01891c7457bc6c8a5ce2401a1a8857f346a2fa9af46271450029

Verified Source Code Partial Match

Compiler: v0.5.8+commit.23d335f2 EVM: petersburg Optimization: Yes (200 runs)
CErc20.sol 2587 lines
// File: contracts/ComptrollerInterface.sol

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);
}

// File: contracts/ErrorReporter.sol

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);
    }
}

// File: contracts/CarefulMath.sol

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);
    }
}

// File: contracts/Exponential.sol

pragma solidity ^0.5.8;


/**
 * @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 returns true if Exp is exactly zero
     */
    function isZeroExp(Exp memory value) pure internal returns (bool) {
        return value.mantissa == 0;
    }
}

// File: contracts/EIP20Interface.sol

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);
}

// File: contracts/EIP20NonStandardInterface.sol

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);
}

// File: contracts/ReentrancyGuard.sol

pragma solidity ^0.5.8;

/**
 * @title Helps contracts guard against reentrancy attacks.
 * @author Remco Bloemen <remco@2π.com>, Eenae <[email protected]>
 * @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");
    }
}

// File: contracts/InterestRateModel.sol

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);
}

// File: contracts/CToken.sol

pragma solidity ^0.5.8;








/**
 * @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;
    ...

// [truncated — 105705 bytes total]

Read Contract

accrualBlockNumber 0x6c540baf → uint256
admin 0xf851a440 → address
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
borrowBalanceStored 0x95dd9193 → uint256
borrowIndex 0xaa5af0fd → uint256
borrowRatePerBlock 0xf8f9da28 → uint256
comptroller 0x5fe3b567 → address
decimals 0x313ce567 → uint256
exchangeRateStored 0x182df0f5 → uint256
getAccountSnapshot 0xc37f68e2 → uint256, uint256, uint256, uint256
getCash 0x3b1d21a2 → uint256
initialExchangeRateMantissa 0x675d972c → uint256
interestRateModel 0xf3fdb15a → address
isCToken 0xfe9c44ae → bool
name 0x06fdde03 → string
pendingAdmin 0x26782247 → address
reserveFactorMantissa 0x173b9904 → uint256
supplyRatePerBlock 0xae9d70b0 → uint256
symbol 0x95d89b41 → string
totalBorrows 0x47bd3718 → uint256
totalReserves 0x8f840ddd → uint256
totalSupply 0x18160ddd → uint256
underlying 0x6f307dc3 → address

Write Contract 22 functions

These functions modify contract state and require a wallet transaction to execute.

_acceptAdmin 0xe9c714f2
No parameters
returns: uint256
_reduceReserves 0x601a0bf1
uint256 reduceAmount
returns: uint256
_setComptroller 0x4576b5db
address newComptroller
returns: uint256
_setInterestRateModel 0xf2b3abbd
address newInterestRateModel
returns: uint256
_setPendingAdmin 0xb71d1a0c
address newPendingAdmin
returns: uint256
_setReserveFactor 0xfca7820b
uint256 newReserveFactorMantissa
returns: uint256
accrueInterest 0xa6afed95
No parameters
returns: uint256
approve 0x095ea7b3
address spender
uint256 amount
returns: bool
balanceOfUnderlying 0x3af9e669
address owner
returns: uint256
borrow 0xc5ebeaec
uint256 borrowAmount
returns: uint256
borrowBalanceCurrent 0x17bfdfbc
address account
returns: uint256
exchangeRateCurrent 0xbd6d894d
No parameters
returns: uint256
liquidateBorrow 0xf5e3c462
address borrower
uint256 repayAmount
address cTokenCollateral
returns: uint256
mint 0xa0712d68
uint256 mintAmount
returns: uint256
redeem 0xdb006a75
uint256 redeemTokens
returns: uint256
redeemUnderlying 0x852a12e3
uint256 redeemAmount
returns: uint256
repayBorrow 0x0e752702
uint256 repayAmount
returns: uint256
repayBorrowBehalf 0x2608f818
address borrower
uint256 repayAmount
returns: uint256
seize 0xb2a02ff1
address liquidator
address borrower
uint256 seizeTokens
returns: uint256
totalBorrowsCurrent 0x73acee98
No parameters
returns: uint256
transfer 0xa9059cbb
address dst
uint256 amount
returns: bool
transferFrom 0x23b872dd
address src
address dst
uint256 amount
returns: bool

Token Balances (1) $8,838,170.84

View Transfers →
TokenBalancePriceValue
USDC 8839019.3813 $0.9999 $8,838,170.84

Recent Transactions

This address has 1 on-chain transactions, but only 1.3% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →