Address Contract Partially Verified
Address
0x2F4EeD3305178e7fbD3618A479a9FC8f2dB41011
Balance
0 ETH
Nonce
1
Code Size
16713 bytes
Creator
0x043500BB...db00 at tx 0xf455e719...2f94e4
Indexed Transactions
0 (1 on-chain, 1.5% indexed)
Contract Bytecode
16713 bytes
0x608060405234801561001057600080fd5b50600436106102775760003560e01c80638129fc1c11610160578063c662ff24116100d8578063e49fba6b1161008c578063f64f329e11610071578063f64f329e146108e2578063f7384d5014610908578063fc9156821461092e57610277565b8063e49fba6b146108b4578063f2fde38b146108bc57610277565b8063d6eebe4c116100bd578063d6eebe4c1461086e578063d9180a0014610876578063d9caed121461087e57610277565b8063c662ff241461080c578063d449a8321461083257610277565b80639b8617801161012f578063b9c3da0f11610114578063b9c3da0f146107a8578063c4d66de8146107de578063c4ee03041461080457610277565b80639b8617801461077a578063b002249d146107a057610277565b80638129fc1c146106af5780638293744b146106b75780638da5cb5b1461076a5780638f32d59b1461077257610277565b806359e8dc97116101f35780636c6874d9116101c2578063715018a6116101a7578063715018a6146105f957806371dc760f146106015780637300c1eb146106a757610277565b80636c6874d9146104ac57806370a08231146105d357610277565b806359e8dc97146104385780635e40b14914610464578063628cb95e1461046c57806366c0bd241461048657610277565b8063426ac8831161024a5780634437152a1161022f5780634437152a146103c757806345cdf0bf146103ed57806357e2ad4a1461040a57610277565b8063426ac883146103a157806343cdf1f7146103bd57610277565b806316f0115b1461027c578063208e509f146102a057806326599a1e146102f8578063372500ab14610300575b600080fd5b610284610936565b604080516001600160a01b039092168252519081900360200190f35b6102a8610945565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102e45781810151838201526020016102cc565b505050509050019250505060405180910390f35b610284610c01565b610308610c10565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561034c578181015183820152602001610334565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561038b578181015183820152602001610373565b5050505090500194505050505060405180910390f35b6103a9610ecf565b604080519115158252519081900360200190f35b6103c5610ed4565b005b6103c5600480360360208110156103dd57600080fd5b50356001600160a01b0316610ee6565b6103c56004803603602081101561040357600080fd5b5035610ff0565b6103c56004803603604081101561042057600080fd5b506001600160a01b0381358116916020013516611082565b6103c56004803603604081101561044e57600080fd5b506001600160a01b038135169060200135611584565b61028461176d565b61047461177c565b60408051918252519081900360200190f35b6104746004803603602081101561049c57600080fd5b50356001600160a01b0316611801565b6103c5600480360360408110156104c257600080fd5b8101906020810181356401000000008111156104dd57600080fd5b8201836020820111156104ef57600080fd5b8035906020019184602083028401116401000000008311171561051157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561056157600080fd5b82018360208201111561057357600080fd5b8035906020019184602083028401116401000000008311171561059557600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061188d945050505050565b610474600480360360208110156105e957600080fd5b50356001600160a01b0316611ae5565b6103c5611c37565b6102846004803603602081101561061757600080fd5b81019060208101813564010000000081111561063257600080fd5b82018360208201111561064457600080fd5b8035906020019184600183028401116401000000008311171561066657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611cf2945050505050565b610284611f75565b6103c5611f84565b6103c5600480360360408110156106cd57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156106f857600080fd5b82018360208201111561070a57600080fd5b8035906020019184602083028401116401000000008311171561072c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612036945050505050565b6102846121ef565b6103a96121fe565b6103a96004803603602081101561079057600080fd5b50356001600160a01b0316612224565b6102a861227f565b6103c5600480360360608110156107be57600080fd5b506001600160a01b038135811691602081013590911690604001356122e1565b6103c5600480360360208110156107f457600080fd5b50356001600160a01b03166123d7565b6102846124d6565b6103c56004803603602081101561082257600080fd5b50356001600160a01b03166124e5565b6108586004803603602081101561084857600080fd5b50356001600160a01b0316612534565b6040805160ff9092168252519081900360200190f35b610284612549565b6102a8612558565b6103c56004803603606081101561089457600080fd5b506001600160a01b038135811691602081013590911690604001356125b4565b6104746128a0565b6103c5600480360360208110156108d257600080fd5b50356001600160a01b03166128a6565b6103a9600480360360208110156108f857600080fd5b50356001600160a01b0316612908565b6103a96004803603602081101561091e57600080fd5b50356001600160a01b0316612921565b610474612935565b6066546001600160a01b031681565b60606000606a60009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561099757600080fd5b505afa1580156109ab573d6000803e3d6000fd5b505050506040513d60208110156109c157600080fd5b5051606b54604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290519293506000926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610a2d57600080fd5b505afa158015610a41573d6000803e3d6000fd5b505050506040513d6020811015610a5757600080fd5b5051604080517f18160ddd00000000000000000000000000000000000000000000000000000000815290519192506000916001600160a01b038516916318160ddd916004808301926020929190829003018186803b158015610ab857600080fd5b505afa158015610acc573d6000803e3d6000fd5b505050506040513d6020811015610ae257600080fd5b5051606e546040805182815260208381028201019091529192508015610b12578160200160208202803883390190505b50935060005b606e54811015610bfa57606954604080517f065a80d8000000000000000000000000000000000000000000000000000000008152600f84810b900b600482015290516000926001600160a01b03169163065a80d8916024808301926020929190829003018186803b158015610b8c57600080fd5b505afa158015610ba0573d6000803e3d6000fd5b505050506040513d6020811015610bb657600080fd5b50519050610bda83610bce838763ffffffff61293b16565b9063ffffffff61299b16565b868381518110610be657fe5b602090810291909101015250600101610b18565b5050505090565b606a546001600160a01b031681565b606080610c23610c1e6129dd565b612908565b610c5e5760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b610c666129e1565b6060610c70612558565b905060608151604051908082528060200260200182016040528015610c9f578160200160208202803883390190505b5090506000805b8351811015610dc1576000848281518110610cbd57fe5b602002602001015190506000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015610d1f57600080fd5b505afa158015610d33573d6000803e3d6000fd5b505050506040513d6020811015610d4957600080fd5b50516001600160a01b038316600090815260686020526040902054909150811115610db7576001600160a01b038216600090815260686020526040902054600190940193610d9e90829063ffffffff612a4516565b858481518110610daa57fe5b6020026020010181815250505b5050600101610ca6565b5080604051908082528060200260200182016040528015610dec578160200160208202803883390190505b50945080604051908082528060200260200182016040528015610e19578160200160208202803883390190505b5093508015610ec8576000805b8451811015610ec5576000848281518110610e3d57fe5b60200260200101511115610ebd57848181518110610e5757fe5b6020026020010151878381518110610e6b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110610e9757fe5b6020026020010151868381518110610eab57fe5b60209081029190910101526001909101905b600101610e26565b50505b5050509091565b600181565b610ee4610edf6129dd565b612a87565b565b610eee6121fe565b610f3f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610f845760405162461bcd60e51b8152600401808060200182810382526022815260200180613ee16022913960400191505060405180910390fd5b606680546001600160a01b0383167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116811790915560408051918252517f5b36800c27524690807962bd42525a44e68b3f860e8f9e0204f27e777d2f46059181900360200190a150565b610ffb610c1e6129dd565b6110365760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b670de0b6b3a764000081101561107d5760405162461bcd60e51b8152600401808060200182810382526028815260200180613f036028913960400191505060405180910390fd5b606f55565b61108d610c1e6129dd565b6110c85760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b606a546001600160a01b03161561118a5760005b606e548110156111885760006001600160a01b0316606e82815481106110fe57fe5b6000918252602090912001546001600160a01b03161461118057611142606e828154811061112857fe5b6000918252602090912001546001600160a01b0316612acf565b6000606e828154811061115157fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001016110dc565b505b606a80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038481169190911791829055604080517f7165485d00000000000000000000000000000000000000000000000000000000815290519290911691637165485d91600480820192602092909190829003018186803b15801561121757600080fd5b505afa15801561122b573d6000803e3d6000fd5b505050506040513d602081101561124157600080fd5b5051606980547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03928316179055606a54604080517ffc0c546a0000000000000000000000000000000000000000000000000000000081529051919092169163fc0c546a916004808301926020929190829003018186803b1580156112cd57600080fd5b505afa1580156112e1573d6000803e3d6000fd5b505050506040513d60208110156112f757600080fd5b5051606d80547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b0393841617909155606b805490911691831691909117905561134981612bb0565b606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03928316179055606a54606d546113b29290811691167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612c1d565b606b54606d546113f5916001600160a01b0391821691167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff63ffffffff612c1d16565b60005b606e5481101561152b57606a54604080517fb739953e000000000000000000000000000000000000000000000000000000008152600f84810b900b600482015290516000926001600160a01b03169163b739953e916024808301926020929190829003018186803b15801561146c57600080fd5b505afa158015611480573d6000803e3d6000fd5b505050506040513d602081101561149657600080fd5b5051606e80549192508291849081106114ab57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506114e281612d77565b606a54611522906001600160a01b0383811691167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff63ffffffff612c1d16565b506001016113f8565b50606954606a54606b54604080516001600160a01b039485168152928416602084015292168183015290517fd71f0c89a7bf4774a6a82f62f1e8d3851b58d3d2572c7871782384796b256eac9181900360600190a15050565b61158f610c1e6129dd565b6115ca5760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b60606115d4612ed5565b6040519080825280602002602001820160405280156115fd578160200160208202803883390190505b50905060005b606e5481101561175457606e818154811061161a57fe5b60009182526020918290200154604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b03909216926370a0823192602480840193829003018186803b15801561168257600080fd5b505afa158015611696573d6000803e3d6000fd5b505050506040513d60208110156116ac57600080fd5b505182518390839081106116bc57fe5b602002602001018181525050836001600160a01b0316606e82815481106116df57fe5b6000918252602090912001546001600160a01b0316141561174c578282828151811061170757fe5b6020026020010151101561174c5760405162461bcd60e51b81526004018080602001828103825260338152602001806140206033913960400191505060405180910390fd5b600101611603565b50611760816000612eda565b611768612f73565b505050565b606c546001600160a01b031681565b60006060611788610945565b90506000805b606e548110156117f9576117ef6117e2606e83815481106117ab57fe5b9060005260206000200160009054906101000a90046001600160a01b03168584815181106117d557fe5b6020026020010151613087565b839063ffffffff61312216565b915060010161178e565b509150505b90565b6000805b606e5481101561185057826001600160a01b0316606e828154811061182657fe5b6000918252602090912001546001600160a01b03161415611848579050611888565b600101611805565b5060405162461bcd60e51b81526004018080602001828103825260268152602001806140b96026913960400191505060405180910390fd5b919050565b611898610c1e6129dd565b6118d35760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b80518251146119135760405162461bcd60e51b8152600401808060200182810382526041815260200180613f2b6041913960600191505060405180910390fd5b61191b612ed5565b8151146119595760405162461bcd60e51b8152600401808060200182810382526040815260200180613df46040913960400191505060405180910390fd5b6060611963612ed5565b60405190808252806020026020018201604052801561198c578160200160208202803883390190505b50905060005b606e548110156117545760006119ba8583815181106119ad57fe5b6020026020010151611801565b9050606e81815481106119c957fe5b60009182526020918290200154604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b03909216926370a0823192602480840193829003018186803b158015611a3157600080fd5b505afa158015611a45573d6000803e3d6000fd5b505050506040513d6020811015611a5b57600080fd5b50518351849083908110611a6b57fe5b602002602001018181525050838281518110611a8357fe5b6020026020010151838281518110611a9757fe5b60200260200101511015611adc5760405162461bcd60e51b81526004018080602001828103825260338152602001806140206033913960400191505060405180910390fd5b50600101611992565b600080611af183611801565b90506000611afd61317c565b90506000606d60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b4f57600080fd5b505afa158015611b63573d6000803e3d6000fd5b505050506040513d6020811015611b7957600080fd5b5051606954604080517f065a80d8000000000000000000000000000000000000000000000000000000008152600f87810b900b600482015290519293506000926001600160a01b039092169163065a80d891602480820192602092909190829003018186803b158015611beb57600080fd5b505afa158015611bff573d6000803e3d6000fd5b505050506040513d6020811015611c1557600080fd5b50519050611c2d82610bce838663ffffffff61293b16565b9695505050505050565b611c3f6121fe565b611c90576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6066546000906001600160a01b0316611d52576040805162461bcd60e51b815260206004820152600f60248201527f4d6f64756c653a206e6f20706f6f6c0000000000000000000000000000000000604482015290519081900360640190fd5b6066546040516020602482018181528551604484015285516000946060946001600160a01b03909116938893928392606401918501908083838b5b83811015611da5578181015183820152602001611d8d565b50505050905090810190601f168015611dd25780820380516001836020036101000a031916815260200191505b50604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f693ec85e00000000000000000000000000000000000000000000000000000000178152905182519295509350839250908083835b60208310611e9757805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611e5a565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611ef7576040519150601f19603f3d011682016040523d82523d6000602084013e611efc565b606091505b509150915081611f0d578060208201fd5b6000818060200190516020811015611f2457600080fd5b505190506001600160a01b038116611f6d5760405162461bcd60e51b8152600401808060200182810382526022815260200180613ffe6022913960400191505060405180910390fd5b949350505050565b606d546001600160a01b031681565b600054610100900460ff1680611f9d5750611f9d613211565b80611fab575060005460ff16155b611fe65760405162461bcd60e51b815260040180806020018281038252602e815260200180613fd0602e913960400191505060405180910390fd5b600054610100900460ff16158015612011576000805460ff1961ff0019909116610100171660011790555b61202161201c6129dd565b613217565b8015612033576000805461ff00191690555b50565b612041610c1e6129dd565b61207c5760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b612084612ed5565b8151146120c25760405162461bcd60e51b815260040180806020018281038252602c815260200180613e8e602c913960400191505060405180910390fd5b60606120cc612ed5565b6040519080825280602002602001820160405280156120f5578160200160208202803883390190505b50905060005b606e548110156121385782818151811061211157fe5b602002602001015182828151811061212557fe5b60209081029190910101526001016120fb565b612140613320565b61216a827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613419565b612172612f73565b5060005b606e548110156121e9576000606e828154811061218f57fe5b9060005260206000200160009054906101000a90046001600160a01b031690506121e0858584815181106121bf57fe5b6020026020010151836001600160a01b03166134339092919063ffffffff16565b50600101612176565b50505050565b6033546001600160a01b031690565b6033546000906001600160a01b03166122156129dd565b6001600160a01b031614905090565b6000805b606e5481101561227657826001600160a01b0316606e828154811061224957fe5b6000918252602090912001546001600160a01b0316141561226e576001915050611888565b600101612228565b50600092915050565b6060606e8054806020026020016040519081016040528092919081815260200182805480156122d757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122b9575b5050505050905090565b6122ec610c1e6129dd565b6123275760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b61233083612921565b612381576040805162461bcd60e51b815260206004820152601e60248201527f50726f746f636f6c426173653a206e6f742072657761726420746f6b656e0000604482015290519081900360640190fd5b6001600160a01b0383166000908152606860205260409020546123aa908263ffffffff612a4516565b6001600160a01b03841660008181526068602052604090209190915561176890838363ffffffff61343316565b600054610100900460ff16806123f057506123f0613211565b806123fe575060005460ff16155b6124395760405162461bcd60e51b815260040180806020018281038252602e815260200180613fd0602e913960400191505060405180910390fd5b600054610100900460ff16158015612464576000805460ff1961ff0019909116610100171660011790555b61246d826134b3565b612475612ed5565b60405190808252806020026020018201604052801561249e578160200160208202803883390190505b5080516124b391606e91602090910190613d1c565b50670e043da617250000606f5580156124d2576000805461ff00191690555b5050565b6069546001600160a01b031681565b6124f0610c1e6129dd565b61252b5760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b6120338161356e565b60706020526000908152604090205460ff1681565b606b546001600160a01b031681565b604080516001808252818301909252606091829190602080830190803883395050606c5482519293506001600160a01b03169183915060009061259757fe5b6001600160a01b0390921660209283029190910190910152905090565b6125bf610c1e6129dd565b6125fa5760405162461bcd60e51b815260040180806020018281038252603c815260200180614053603c913960400191505060405180910390fd5b600061260583611801565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290519192506000916001600160a01b038616916370a08231916024808301926020929190829003018186803b15801561266a57600080fd5b505afa15801561267e573d6000803e3d6000fd5b505050506040513d602081101561269457600080fd5b5051905060006126aa848363ffffffff612a4516565b905060006126b88683613087565b905060006126c461177c565b905060006126d061317c565b90506000612709670de0b6b3a7640000610bce85610bce606f546126fd8a8961293b90919063ffffffff16565b9063ffffffff61293b16565b9050612714816135b6565b606a54604080517f517a55a300000000000000000000000000000000000000000000000000000000815260048101849052600f8a810b900b6024820152604481018890526001606482015290516001600160a01b039092169163517a55a39160848082019260009290919082900301818387803b15801561279457600080fd5b505af11580156127a8573d6000803e3d6000fd5b5050604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516001600160a01b038d1693506370a0823192506024808301926020929190829003018186803b15801561280b57600080fd5b505afa15801561281f573d6000803e3d6000fd5b505050506040513d602081101561283557600080fd5b50519550878610156128785760405162461bcd60e51b8152600401808060200182810382526034815260200180613e346034913960400191505060405180910390fd5b886128936001600160a01b0382168c8b63ffffffff61343316565b5050505050505050505050565b606e5490565b6128ae6121fe565b6128ff576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6120338161361c565b600061291b60678363ffffffff6136d516565b92915050565b606c546001600160a01b0390811691161490565b606f5481565b60008261294a5750600061291b565b8282028284828161295757fe5b04146129945760405162461bcd60e51b8152600401808060200182810382526021815260200180613f8d6021913960400191505060405180910390fd5b9392505050565b600061299483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061373c565b3390565b606b60009054906101000a90046001600160a01b03166001600160a01b0316633d18b9126040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612a3157600080fd5b505af11580156121e9573d6000803e3d6000fd5b600061299483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506137de565b612a9860678263ffffffff61383816565b6040516001600160a01b038216907f626bf7c6846fdc6e3f94a7c861b91118b5c0506bc3dc892b70f7d42bd619118790600090a250565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b158015612b3257600080fd5b505afa158015612b46573d6000803e3d6000fd5b505050506040513d6020811015612b5c57600080fd5b505190508015612b7857612b7882612b726129dd565b836125b4565b6040516001600160a01b038316907fb02d270f645215800cec778b856004c753ad0c8c6ca520a91a8399acf4c63d4b90600090a25050565b6000816001600160a01b031663e7d279986040518163ffffffff1660e01b815260040160206040518083038186803b158015612beb57600080fd5b505afa158015612bff573d6000803e3d6000fd5b505050506040513d6020811015612c1557600080fd5b505192915050565b801580612cbc5750604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612c8e57600080fd5b505afa158015612ca2573d6000803e3d6000fd5b505050506040513d6020811015612cb857600080fd5b5051155b612cf75760405162461bcd60e51b81526004018080602001828103825260368152602001806140df6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905261176890849061389f565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905182916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015612ddb57600080fd5b505afa158015612def573d6000803e3d6000fd5b505050506040513d6020811015612e0557600080fd5b505190508015612e1957612e198382611584565b826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612e5257600080fd5b505afa158015612e66573d6000803e3d6000fd5b505050506040513d6020811015612e7c57600080fd5b50516001600160a01b038416600081815260706020526040808220805460ff191660ff90951694909417909355915190917f158412daecdc1456d01568828bcdb18464cc7f1ce0215ddbc3f3cfede9d1e63d91a2505050565b600490565b606a546001600160a01b031663029b2f34612ef484613a75565b836040518363ffffffff1660e01b81526004018083600460200280838360005b83811015612f2c578181015183820152602001612f14565b5050505090500182815260200192505050600060405180830381600087803b158015612f5757600080fd5b505af1158015612f6b573d6000803e3d6000fd5b505050505050565b606d54604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015612fd757600080fd5b505afa158015612feb573d6000803e3d6000fd5b505050506040513d602081101561300157600080fd5b5051606b54604080517fa694fc3a0000000000000000000000000000000000000000000000000000000081526004810184905290519293506001600160a01b039091169163a694fc3a9160248082019260009290919082900301818387803b15801561306c57600080fd5b505af1158015613080573d6000803e3d6000fd5b5050505050565b6001600160a01b03821660009081526070602052604081205460ff1660128114156130b5578291505061291b565b60128111156130fb576130f3837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee8301600a0a63ffffffff61299b16565b91505061291b565b601281101561311b576130f3836012839003600a0a63ffffffff61293b16565b5092915050565b600082820183811015612994576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b606b54604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156131e057600080fd5b505afa1580156131f4573d6000803e3d6000fd5b505050506040513d602081101561320a57600080fd5b5051905090565b303b1590565b600054610100900460ff16806132305750613230613211565b8061323e575060005460ff16155b6132795760405162461bcd60e51b815260040180806020018281038252602e815260200180613fd0602e913960400191505060405180910390fd5b600054610100900460ff161580156132a4576000805460ff1961ff0019909116610100171660011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156124d2576000805461ff00191690555050565b606b54604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561338457600080fd5b505afa158015613398573d6000803e3d6000fd5b505050506040513d60208110156133ae57600080fd5b5051606b54604080517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905290519293506001600160a01b0390911691632e1a7d4d9160248082019260009290919082900301818387803b15801561306c57600080fd5b606a546001600160a01b03166318a7bd76612ef484613a75565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261176890849061389f565b600054610100900460ff16806134cc57506134cc613211565b806134da575060005460ff16155b6135155760405162461bcd60e51b815260040180806020018281038252602e815260200180613fd0602e913960400191505060405180910390fd5b600054610100900460ff16158015613540576000805460ff1961ff0019909116610100171660011790555b61354982613b21565b6135596135546129dd565b613bbf565b80156124d2576000805461ff00191690555050565b61357f60678263ffffffff613c6216565b6040516001600160a01b038216907fd2a1587d372a888fc8427f6f206845b51ddf76976073d43f23e512ad1f22483590600090a250565b606b54604080517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905290516001600160a01b0390921691632e1a7d4d9160248082019260009290919082900301818387803b15801561306c57600080fd5b6001600160a01b0381166136615760405162461bcd60e51b8152600401808060200182810382526026815260200180613e686026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60006001600160a01b03821661371c5760405162461bcd60e51b8152600401808060200182810382526022815260200180613fae6022913960400191505060405180910390fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b600081836137c85760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561378d578181015183820152602001613775565b50505050905090810190601f1680156137ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816137d457fe5b0495945050505050565b600081848411156138305760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561378d578181015183820152602001613775565b505050900390565b61384282826136d5565b61387d5760405162461bcd60e51b8152600401808060200182810382526021815260200180613f6c6021913960400191505060405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6138b1826001600160a01b0316613ce3565b613902576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061395e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613921565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146139c0576040519150601f19603f3d011682016040523d82523d6000602084013e6139c5565b606091505b509150915081613a1c576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156121e957808060200190516020811015613a3857600080fd5b50516121e95760405162461bcd60e51b815260040180806020018281038252602a81526020018061408f602a913960400191505060405180910390fd5b613a7d613d99565b6004825114613abd5760405162461bcd60e51b8152600401808060200182810382526027815260200180613eba6027913960400191505060405180910390fd5b613ac5613d99565b506040805160808101825260008082526020820181905291810182905260608101829052905b600481101561311b57838181518110613b0057fe5b6020026020010151828260048110613b1457fe5b6020020152600101613aeb565b600054610100900460ff1680613b3a5750613b3a613211565b80613b48575060005460ff16155b613b835760405162461bcd60e51b815260040180806020018281038252602e815260200180613fd0602e913960400191505060405180910390fd5b600054610100900460ff16158015613bae576000805460ff1961ff0019909116610100171660011790555b613bb6611f84565b61355982610ee6565b600054610100900460ff1680613bd85750613bd8613211565b80613be6575060005460ff16155b613c215760405162461bcd60e51b815260040180806020018281038252602e815260200180613fd0602e913960400191505060405180910390fd5b600054610100900460ff16158015613c4c576000805460ff1961ff0019909116610100171660011790555b613c5582612908565b613559576135598261356e565b613c6c82826136d5565b15613cbe576040805162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611f6d575050151592915050565b828054828255906000526020600020908101928215613d89579160200282015b82811115613d8957825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909116178255602090920191600190910190613d3c565b50613d95929150613db7565b5090565b60405180608001604052806004906020820280388339509192915050565b6117fe91905b80821115613d955780547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600101613dbd56fe437572766546695950726f746f636f6c3a20616d6f756e747320636f756e7420646f6573206e6f74206d61746368207265676973746572656420746f6b656e73437572766546695950726f746f636f6c3a206661696c656420746f20776974686472617720726571756972656420616d6f756e744f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373437572766546695950726f746f636f6c3a2077726f6e6720616d6f756e7473206172726179206c656e6774684375727665466950726f746f636f6c5f535553443a2077726f6e6720746f6b656e20636f756e744d6f64756c653a20706f6f6c20616464726573732063616e2774206265207a65726f43757276654669594d6f64756c653a206d756c7469706c6965722073686f756c64206265203e2031437572766546695950726f746f636f6c3a20636f756e74206f6620746f6b656e7320646f6573206e6f74206d6174636820636f756e74206f6620616d6f756e7473526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65644d6f64756c653a20726571756573746564206d6f64756c65206e6f7420666f756e64437572766546695950726f746f636f6c3a2072657175657374656420616d6f756e74206973206e6f74206465706f7369746564446566694f70657261746f72526f6c653a2063616c6c657220646f6573206e6f7420686176652074686520446566694f70657261746f7220726f6c655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564437572766546695950726f746f636f6c3a20746f6b656e206e6f7420726567697374657265645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a265627a7a72315820712d731aded802f9e7b3e25140a76c16372674fab0def8b2b02eccdf4884111864736f6c63430005110032
Verified Source Code Partial Match
Compiler: v0.5.17+commit.d19bba13
EVM: istanbul
Optimization: Yes (10000 runs)
CurveFiProtocol_SUSD.sol 1360 lines
// File: @openzeppelin\contracts-ethereum-package\contracts\token\ERC20\IERC20.sol
pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: 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
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: @openzeppelin\upgrades\contracts\Initializable.sol
pragma solidity >=0.4.24 <0.7.0;
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly { cs := extcodesize(self) }
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}
// File: @openzeppelin\contracts-ethereum-package\contracts\token\ERC20\ERC20Detailed.sol
pragma solidity ^0.5.0;
/**
* @dev Optional functions from the ERC20 standard.
*/
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
* these values are immutable: they can only be set once during
* construction.
*/
function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
// File: @openzeppelin\contracts-ethereum-package\contracts\math\SafeMath.sol
pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File: @openzeppelin\contracts-ethereum-package\contracts\utils\Address.sol
pragma solidity ^0.5.5;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* _Available since v2.4.0._
*/
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*
* _Available since v2.4.0._
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-call-value
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
// File: @openzeppelin\contracts-ethereum-package\contracts\token\ERC20\SafeERC20.sol
pragma solidity ^0.5.0;
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* 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 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File: contracts\interfaces\defi\IDefiProtocol.sol
pragma solidity ^0.5.12;
interface IDefiProtocol {
/**
* @notice Transfer tokens from sender to DeFi protocol
* @param token Address of token
* @param amount Value of token to deposit
* @return new balances of each token
*/
function handleDeposit(address token, uint256 amount) external;
function handleDeposit(address[] calldata tokens, uint256[] calldata amounts) external;
/**
* @notice Transfer tokens from DeFi protocol to beneficiary
* @param token Address of token
* @param amount Denormalized value of token to withdraw
* @return new balances of each token
*/
function withdraw(address beneficiary, address token, uint256 amount) external;
/**
* @notice Transfer tokens from DeFi protocol to beneficiary
* @param amounts Array of amounts to withdraw, in order of supportedTokens()
* @return new balances of each token
*/
function withdraw(address beneficiary, uint256[] calldata amounts) external;
/**
* @notice Claim rewards. Reward tokens will be stored on protocol balance.
* @return tokens and their amounts received
*/
function claimRewards() external returns(address[] memory tokens, uint256[] memory amounts);
/**
* @notice Withdraw reward tokens to user
* @dev called by SavingsModule
* @param token Reward token to withdraw
* @param user Who should receive tokens
* @param amount How many tokens to send
*/
function withdrawReward(address token, address user, uint256 amount) external;
/**
* @dev This function is not view because on some protocols
* (Compound, RAY with Compound oportunity) it may cause storage writes
*/
function balanceOf(address token) external returns(uint256);
/**
* @notice Balance of all tokens supported by protocol
* @dev This function is not view because on some protocols
* (Compound, RAY with Compound oportunity) it may cause storage writes
*/
function balanceOfAll() external returns(uint256[] memory);
/**
* @notice Returns normalized (to USD with 18 decimals) summary balance
* of pool using all tokens in this protocol
*/
function normalizedBalance() external returns(uint256);
function supportedTokens() external view returns(address[] memory);
function supportedTokensCount() external view returns(uint256);
function supportedRewardTokens() external view returns(address[] memory);
function isSupportedRewardToken(address token) external view returns(bool);
/**
* @notice Returns if this protocol can swap all it's normalizedBalance() to specified token
*/
function canSwapToToken(address token) external view returns(bool);
}
// File: contracts\interfaces\defi\ICurveFiDeposit.sol
pragma solidity ^0.5.12;
contract ICurveFiDeposit {
function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount) external;
function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_uamount, bool donate_dust) external;
function withdraw_donated_dust() external;
function coins(int128 i) external view returns (address);
function underlying_coins (int128 i) external view returns (address);
function curve() external view returns (address);
function token() external view returns (address);
function calc_withdraw_one_coin (uint256 _token_amount, int128 i) external view returns (uint256);
}
// File: contracts\interfaces\defi\ICurveFiSwap.sol
pragma solidity ^0.5.12;
interface ICurveFiSwap {
function balances(int128 i) external view returns(uint256);
function A() external view returns(uint256);
function fee() external view returns(uint256);
function coins(int128 i) external view returns (address);
}
// File: contracts\interfaces\defi\ICurveFiRewards.sol
pragma solidity ^0.5.16;
interface ICurveFiRewards {
function stake(uint256 amount) external;
function withdraw(uint256 amount) external;
function getReward() external;
function earned(address account) external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
}
// File: contracts\interfaces\defi\ICErc20.sol
pragma solidity ^0.5.12;
/**
* Most important functions of Compound CErc20 token.
* Source: https://github.com/compound-finance/compound-protocol/blob/master/contracts/CTokenInterfaces.sol
*
* Original interface name: CErc20Interface
* but we use our naming covention.
*/
//solhint-disable func-order
contract ICErc20 {
/*** User Interface of CTokenInterface ***/
function transfer(address dst, uint amount) external returns (bool);
function transferFrom(address src, address dst, uint amount) external returns (bool);
function approve(address spender, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function balanceOfUnderlying(address owner) external returns (uint256);
function exchangeRateCurrent() external returns (uint256);
function exchangeRateStored() external view returns (uint256);
function accrueInterest() external returns (uint256);
/*** User Interface of CErc20Interface ***/
function mint(uint mintAmount) external returns (uint256);
function redeem(uint redeemTokens) external returns (uint256);
function redeemUnderlying(uint redeemAmount) external returns (uint256);
}
// File: contracts\interfaces\defi\IComptroller.sol
pragma solidity ^0.5.16;
contract IComptroller {
function claimComp(address holder) public;
function getCompAddress() public view returns (address);
}
// File: @openzeppelin\contracts-ethereum-package\contracts\GSN\Context.sol
pragma solidity ^0.5.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
contract Context is Initializable {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File: @openzeppelin\contracts-ethereum-package\contracts\ownership\Ownable.sol
pragma solidity ^0.5.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be aplied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Initializable, Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function initialize(address sender) public initializer {
_owner = sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* > Note: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
// File: contracts\common\Base.sol
pragma solidity ^0.5.12;
/**
* Base contract for all modules
*/
contract Base is Initializable, Context, Ownable {
address constant ZERO_ADDRESS = address(0);
function initialize() public initializer {
Ownable.initialize(_msgSender());
}
}
// File: contracts\core\ModuleNames.sol
pragma solidity ^0.5.12;
/**
* @dev List of module names
*/
contract ModuleNames {
// Pool Modules
string internal constant MODULE_ACCESS = "access";
string internal constant MODULE_SAVINGS = "savings";
string internal constant MODULE_INVESTING = "investing";
string internal constant MODULE_STAKING = "staking";
string internal constant MODULE_DCA = "dca";
// External Modules (used to store addresses of external contracts)
string internal constant CONTRACT_RAY = "ray";
}
// File: contracts\common\Module.sol
pragma solidity ^0.5.12;
/**
* Base contract for all modules
*/
contract Module is Base, ModuleNames {
event PoolAddressChanged(address newPool);
address public pool;
function initialize(address _pool) public initializer {
Base.initialize();
setPool(_pool);
}
function setPool(address _pool) public onlyOwner {
require(_pool != ZERO_ADDRESS, "Module: pool address can't be zero");
pool = _pool;
emit PoolAddressChanged(_pool);
}
function getModuleAddress(string memory module) public view returns(address){
require(pool != ZERO_ADDRESS, "Module: no pool");
(bool success, bytes memory result) = pool.staticcall(abi.encodeWithSignature("get(string)", module));
//Forward error from Pool contract
if (!success) assembly {
revert(add(result, 32), result)
}
address moduleAddress = abi.decode(result, (address));
// string memory error = string(abi.encodePacked("Module: requested module not found - ", module));
// require(moduleAddress != ZERO_ADDRESS, error);
require(moduleAddress != ZERO_ADDRESS, "Module: requested module not found");
return moduleAddress;
}
}
// File: @openzeppelin\contracts-ethereum-package\contracts\access\Roles.sol
pragma solidity ^0.5.0;
/**
* @title Roles
* @dev Library for managing addresses assigned to a Role.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev Give an account access to this role.
*/
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
/**
* @dev Remove an account's access to this role.
*/
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
/**
* @dev Check if an account has this role.
* @return bool
*/
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
// File: contracts\modules\defi\DefiOperatorRole.sol
pragma solidity ^0.5.12;
contract DefiOperatorRole is Initializable, Context {
using Roles for Roles.Role;
event DefiOperatorAdded(address indexed account);
event DefiOperatorRemoved(address indexed account);
Roles.Role private _operators;
function initialize(address sender) public initializer {
if (!isDefiOperator(sender)) {
_addDefiOperator(sender);
}
}
modifier onlyDefiOperator() {
require(isDefiOperator(_msgSender()), "DefiOperatorRole: caller does not have the DefiOperator role");
_;
}
function addDefiOperator(address account) public onlyDefiOperator {
_addDefiOperator(account);
}
function renounceDefiOperator() public {
_removeDefiOperator(_msgSender());
}
function isDefiOperator(address account) public view returns (bool) {
return _operators.has(account);
}
function _addDefiOperator(address account) internal {
_operators.add(account);
emit DefiOperatorAdded(account);
}
function _removeDefiOperator(address account) internal {
_operators.remove(account);
emit DefiOperatorRemoved(account);
}
}
// File: contracts\modules\defi\ProtocolBase.sol
pragma solidity ^0.5.12;
contract ProtocolBase is Module, DefiOperatorRole, IDefiProtocol {
uint256 constant MAX_UINT256 = uint256(-1);
event RewardTokenClaimed(address indexed token, uint256 amount);
using SafeMath for uint256;
using SafeERC20 for IERC20;
mapping(address=>uint256) rewardBalances; //Mapping of already claimed amounts of reward tokens
function initialize(address _pool) public initializer {
Module.initialize(_pool);
DefiOperatorRole.initialize(_msgSender());
}
function supportedRewardTokens() public view returns(address[] memory);
function isSupportedRewardToken(address token) public view returns(bool);
function cliamRewardsFromProtocol() internal;
function claimRewards() public onlyDefiOperator returns(address[] memory tokens, uint256[] memory amounts){
cliamRewardsFromProtocol();
// Check what we received
address[] memory rewardTokens = supportedRewardTokens();
uint256[] memory rewardAmounts = new uint256[](rewardTokens.length);
uint256 receivedRewardTokensCount;
for(uint256 i = 0; i < rewardTokens.length; i++) {
address rtkn = rewardTokens[i];
uint256 newBalance = IERC20(rtkn).balanceOf(address(this));
if(newBalance > rewardBalances[rtkn]) {
receivedRewardTokensCount++;
rewardAmounts[i] = newBalance.sub(rewardBalances[rtkn]);
}
}
//Fill result arrays
tokens = new address[](receivedRewardTokensCount);
amounts = new uint256[](receivedRewardTokensCount);
if(receivedRewardTokensCount > 0) {
uint256 j;
for(uint256 i = 0; i < rewardTokens.length; i++) {
if(rewardAmounts[i] > 0) {
tokens[j] = rewardTokens[i];
amounts[j] = rewardAmounts[i];
j++;
}
}
}
}
function withdrawReward(address token, address user, uint256 amount) public onlyDefiOperator {
require(isSupportedRewardToken(token), "ProtocolBase: not reward token");
rewardBalances[token] = rewardBalances[token].sub(amount);
IERC20(token).safeTransfer(user, amount);
}
}
// File: contracts\modules\defi\CurveFiProtocol.sol
pragma solidity ^0.5.12;
contract CurveFiProtocol is ProtocolBase {
// Withdrawing one token form Curve.fi pool may lead to small amount of pool token may left unused on Deposit contract.
// If DONATE_DUST = true, it will be left there and donated to curve.fi, otherwise we will use gas to transfer it back.
bool public constant DONATE_DUST = true;
uint256 constant MAX_UINT256 = uint256(-1);
using SafeMath for uint256;
using SafeERC20 for IERC20;
event CurveFiSetup(address swap, address deposit, address rewardsController);
event TokenRegistered(address indexed token);
event TokenUnregistered(address indexed token);
ICurveFiSwap public curveFiSwap;
ICurveFiDeposit public curveFiDeposit;
ICurveFiRewards public curveFiRewards;
IERC20 public curveFiRewardToken;
IERC20 public curveFiToken;
address[] internal _registeredTokens;
uint256 public slippageMultiplier; //Multiplier to work-around slippage & fees when witharawing one token
mapping(address => uint8) public decimals;
function nCoins() internal returns(uint256);
function deposit_add_liquidity(uint256[] memory amounts, uint256 min_mint_amount) internal;
function deposit_remove_liquidity_imbalance(uint256[] memory amounts, uint256 max_burn_amount) internal;
function reward_rewardToken(address rewardsController) internal returns(address);
function initialize(address _pool) public initializer {
ProtocolBase.initialize(_pool);
_registeredTokens = new address[](nCoins());
slippageMultiplier = 1.01*1e18; //Max slippage - 1%, if more - tx will fail
}
function setCurveFi(address deposit, address rewardsController) public onlyDefiOperator {
if (address(curveFiDeposit) != address(0)) {
//We need to unregister tokens first
for (uint256 i=0; i < _registeredTokens.length; i++){
if (_registeredTokens[i] != address(0)) {
_unregisterToken(_registeredTokens[i]);
_registeredTokens[i] = address(0);
}
}
}
curveFiDeposit = ICurveFiDeposit(deposit);
curveFiSwap = ICurveFiSwap(curveFiDeposit.curve());
curveFiToken = IERC20(curveFiDeposit.token());
curveFiRewards = ICurveFiRewards(rewardsController);
curveFiRewardToken = IERC20(reward_rewardToken(rewardsController));
IERC20(curveFiToken).safeApprove(address(curveFiDeposit), MAX_UINT256);
IERC20(curveFiToken).safeApprove(address(curveFiRewards), MAX_UINT256);
for (uint256 i=0; i < _registeredTokens.length; i++){
address token = curveFiDeposit.underlying_coins(int128(i));
_registeredTokens[i] = token;
_registerToken(token);
IERC20(token).safeApprove(address(curveFiDeposit), MAX_UINT256);
}
emit CurveFiSetup(address(curveFiSwap), address(curveFiDeposit), address(curveFiRewards));
}
function setSlippageMultiplier(uint256 _slippageMultiplier) public onlyDefiOperator {
require(_slippageMultiplier >= 1e18, "CurveFiYModule: multiplier should be > 1");
slippageMultiplier = _slippageMultiplier;
}
function handleDeposit(address token, uint256 amount) public onlyDefiOperator {
uint256[] memory amounts = new uint256[](nCoins());
for (uint256 i=0; i < _registeredTokens.length; i++){
amounts[i] = IERC20(_registeredTokens[i]).balanceOf(address(this)); // Check balance which is left after previous withdrawal
//amounts[i] = (_registeredTokens[i] == token)?amount:0;
if (_registeredTokens[i] == token) {
require(amounts[i] >= amount, "CurveFiYProtocol: requested amount is not deposited");
}
}
deposit_add_liquidity(amounts, 0);
stakeCurveFiToken();
}
function handleDeposit(address[] memory tokens, uint256[] memory amounts) public onlyDefiOperator {
require(tokens.length == amounts.length, "CurveFiYProtocol: count of tokens does not match count of amounts");
require(amounts.length == nCoins(), "CurveFiYProtocol: amounts count does not match registered tokens");
uint256[] memory amnts = new uint256[](nCoins());
for (uint256 i=0; i < _registeredTokens.length; i++){
uint256 idx = getTokenIndex(tokens[i]);
amnts[idx] = IERC20(_registeredTokens[idx]).balanceOf(address(this)); // Check balance which is left after previous withdrawal
require(amnts[idx] >= amounts[i], "CurveFiYProtocol: requested amount is not deposited");
}
deposit_add_liquidity(amnts, 0);
stakeCurveFiToken();
}
/**
* @dev With this function beneficiary will recieve exact amount he asked.
* Slippage + fee is paid from his account in SavingsModule
*/
function withdraw(address beneficiary, address token, uint256 amount) public onlyDefiOperator {
uint256 tokenIdx = getTokenIndex(token);
uint256 available = IERC20(token).balanceOf(address(this));
uint256 wAmount = amount.sub(available); //Count tokens left after previous withdrawal
// count shares for proportional withdraw
uint256 nAmount = normalizeAmount(token, wAmount);
uint256 nBalance = normalizedBalance();
uint256 poolShares = curveFiTokenBalance();
uint256 withdrawShares = poolShares.mul(nAmount).mul(slippageMultiplier).div(nBalance).div(1e18); //Increase required amount to some percent, so that we definitely have enough to withdraw
unstakeCurveFiToken(withdrawShares);
curveFiDeposit.remove_liquidity_one_coin(withdrawShares, int128(tokenIdx), wAmount, DONATE_DUST);
available = IERC20(token).balanceOf(address(this));
require(available >= amount, "CurveFiYProtocol: failed to withdraw required amount");
IERC20 ltoken = IERC20(token);
ltoken.safeTransfer(beneficiary, amount);
}
function withdraw(address beneficiary, uint256[] memory amounts) public onlyDefiOperator {
require(amounts.length == nCoins(), "CurveFiYProtocol: wrong amounts array length");
uint256[] memory amnts = new uint256[](nCoins());
uint256 i;
for (i = 0; i < _registeredTokens.length; i++){
amnts[i] = amounts[i];
}
unstakeCurveFiToken();
deposit_remove_liquidity_imbalance(amnts, MAX_UINT256);
stakeCurveFiToken();
for (i = 0; i < _registeredTokens.length; i++){
IERC20 ltoken = IERC20(_registeredTokens[i]);
ltoken.safeTransfer(beneficiary, amounts[i]);
}
}
function supportedRewardTokens() public view returns(address[] memory) {
address[] memory rtokens = new address[](1);
rtokens[0] = address(curveFiRewardToken);
return rtokens;
}
function isSupportedRewardToken(address token) public view returns(bool) {
return(token == address(curveFiRewardToken));
}
function cliamRewardsFromProtocol() internal {
curveFiRewards.getReward();
}
function balanceOf(address token) public returns(uint256) {
uint256 tokenIdx = getTokenIndex(token);
uint256 cfBalance = curveFiTokenBalance();
uint256 cfTotalSupply = curveFiToken.totalSupply();
uint256 tokenCurveFiBalance = curveFiSwap.balances(int128(tokenIdx));
return tokenCurveFiBalance.mul(cfBalance).div(cfTotalSupply);
}
function balanceOfAll() public returns(uint256[] memory balances) {
IERC20 cfToken = IERC20(curveFiDeposit.token());
uint256 cfBalance = curveFiRewards.balanceOf(address(this));
uint256 cfTotalSupply = cfToken.totalSupply();
balances = new uint256[](_registeredTokens.length);
for (uint256 i=0; i < _registeredTokens.length; i++){
uint256 tcfBalance = curveFiSwap.balances(int128(i));
balances[i] = tcfBalance.mul(cfBalance).div(cfTotalSupply);
}
}
function normalizedBalance() public returns(uint256) {
uint256[] memory balances = balanceOfAll();
uint256 summ;
for (uint256 i=0; i < _registeredTokens.length; i++){
summ = summ.add(normalizeAmount(_registeredTokens[i], balances[i]));
}
return summ;
}
function supportedTokens() public view returns(address[] memory){
return _registeredTokens;
}
function supportedTokensCount() public view returns(uint256) {
return _registeredTokens.length;
}
function getTokenIndex(address token) public view returns(uint256) {
for (uint256 i=0; i < _registeredTokens.length; i++){
if (_registeredTokens[i] == token){
return i;
}
}
revert("CurveFiYProtocol: token not registered");
}
function canSwapToToken(address token) public view returns(bool) {
for (uint256 i=0; i < _registeredTokens.length; i++){
if (_registeredTokens[i] == token){
return true;
}
}
return false;
}
function normalizeAmount(address token, uint256 amount) internal view returns(uint256) {
uint256 _decimals = uint256(decimals[token]);
if (_decimals == 18) {
return amount;
} else if (_decimals > 18) {
return amount.div(10**(_decimals-18));
} else if (_decimals < 18) {
return amount.mul(10**(18-_decimals));
}
}
function denormalizeAmount(address token, uint256 amount) internal view returns(uint256) {
uint256 _decimals = uint256(decimals[token]);
if (_decimals == 18) {
return amount;
} else if (_decimals > 18) {
return amount.mul(10**(_decimals-18));
} else if (_decimals < 18) {
return amount.div(10**(18-_decimals));
}
}
function curveFiTokenBalance() internal view returns(uint256) {
return curveFiRewards.balanceOf(address(this));
}
function stakeCurveFiToken() private {
uint256 cftBalance = curveFiToken.balanceOf(address(this));
curveFiRewards.stake(cftBalance);
}
function unstakeCurveFiToken(uint256 amount) private {
curveFiRewards.withdraw(amount);
}
function unstakeCurveFiToken() private {
uint256 balance = curveFiRewards.balanceOf(address(this));
curveFiRewards.withdraw(balance);
}
function _registerToken(address token) private {
IERC20 ltoken = IERC20(token);
uint256 currentBalance = ltoken.balanceOf(address(this));
if (currentBalance > 0) {
handleDeposit(token, currentBalance);
}
decimals[token] = ERC20Detailed(token).decimals();
emit TokenRegistered(token);
}
function _unregisterToken(address token) private {
uint256 balance = IERC20(token).balanceOf(address(this));
//TODO: ensure there is no interest on this token which is wating to be withdrawn
if (balance > 0){
withdraw(token, _msgSender(), balance); //This updates withdrawalsSinceLastDistribution
}
emit TokenUnregistered(token);
}
}
// File: contracts\interfaces\defi\ICurveFiDeposit_SUSD.sol
pragma solidity ^0.5.12;
contract ICurveFiDeposit_SUSD {
function add_liquidity (uint256[4] calldata uamounts, uint256 min_mint_amount) external;
function remove_liquidity (uint256 _amount, uint256[4] calldata min_uamounts) external;
function remove_liquidity_imbalance (uint256[4] calldata uamounts, uint256 max_burn_amount) external;
}
// File: contracts\interfaces\defi\ICurveFiRewards_SUSD.sol
pragma solidity ^0.5.16;
interface ICurveFiRewards_SUSD {
function snx() external view returns (address);
}
// File: contracts\modules\defi\CurveFiProtocol_SUSD.sol
pragma solidity ^0.5.12;
contract CurveFiProtocol_SUSD is CurveFiProtocol {
uint256 private constant N_COINS = 4;
function nCoins() internal returns(uint256) {
return N_COINS;
}
function reward_rewardToken(address rewardsController) internal returns(address){
return ICurveFiRewards_SUSD(rewardsController).snx();
}
function convertArray(uint256[] memory amounts) internal pure returns(uint256[N_COINS] memory) {
require(amounts.length == N_COINS, "CurveFiProtocol_SUSD: wrong token count");
uint256[N_COINS] memory amnts = [uint256(0), uint256(0), uint256(0), uint256(0)];
for(uint256 i=0; i < N_COINS; i++){
amnts[i] = amounts[i];
}
return amnts;
}
function deposit_add_liquidity(uint256[] memory amounts, uint256 min_mint_amount) internal {
ICurveFiDeposit_SUSD(address(curveFiDeposit)).add_liquidity(convertArray(amounts), min_mint_amount);
}
function deposit_remove_liquidity_imbalance(uint256[] memory amounts, uint256 max_burn_amount) internal {
ICurveFiDeposit_SUSD(address(curveFiDeposit)).remove_liquidity_imbalance(convertArray(amounts), max_burn_amount);
}
}
Read Contract
DONATE_DUST 0x426ac883 → bool
canSwapToToken 0x9b861780 → bool
curveFiDeposit 0x26599a1e → address
curveFiRewardToken 0x5e40b149 → address
curveFiRewards 0xd6eebe4c → address
curveFiSwap 0xc4ee0304 → address
curveFiToken 0x7300c1eb → address
decimals 0xd449a832 → uint8
getModuleAddress 0x71dc760f → address
getTokenIndex 0x66c0bd24 → uint256
isDefiOperator 0xf64f329e → bool
isOwner 0x8f32d59b → bool
isSupportedRewardToken 0xf7384d50 → bool
owner 0x8da5cb5b → address
pool 0x16f0115b → address
slippageMultiplier 0xfc915682 → uint256
supportedRewardTokens 0xd9180a00 → address[]
supportedTokens 0xb002249d → address[]
supportedTokensCount 0xe49fba6b → uint256
Write Contract 18 functions
These functions modify contract state and require a wallet transaction to execute.
addDefiOperator 0xc662ff24
address account
balanceOf 0x70a08231
address token
returns: uint256
balanceOfAll 0x208e509f
No parameters
returns: uint256[]
claimRewards 0x372500ab
No parameters
returns: address[], uint256[]
handleDeposit 0x59e8dc97
address token
uint256 amount
handleDeposit 0x6c6874d9
address[] tokens
uint256[] amounts
initialize 0x8129fc1c
No parameters
initialize 0xc4d66de8
address _pool
normalizedBalance 0x628cb95e
No parameters
returns: uint256
renounceDefiOperator 0x43cdf1f7
No parameters
renounceOwnership 0x715018a6
No parameters
setCurveFi 0x57e2ad4a
address deposit
address rewardsController
setPool 0x4437152a
address _pool
setSlippageMultiplier 0x45cdf0bf
uint256 _slippageMultiplier
transferOwnership 0xf2fde38b
address newOwner
withdraw 0x8293744b
address beneficiary
uint256[] amounts
withdraw 0xd9caed12
address beneficiary
address token
uint256 amount
withdrawReward 0xb9c3da0f
address token
address user
uint256 amount
Token Balances (1) $1.47
View Transfers →| Token | Balance | Price | Value |
|---|---|---|---|
| DAI | 1.4744 | $0.9997 | $1.47 |
Recent Transactions
This address has 1 on-chain transactions, but only 1.5% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →