Address Contract Partially Verified
Address
0x425e0EC09f9Bcdfd20283Bf23251cCB74D118813
Balance
0 ETH
Nonce
1
Code Size
11510 bytes
Creator
0xF89a56f4...22c9 at tx 0x51dd374d...56daaa
Indexed Transactions
0
Contract Bytecode
11510 bytes
0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806380ea3de11161010f578063bc5920ba116100a2578063dd62ed3e11610071578063dd62ed3e146103a8578063de114190146103bb578063f0a10b1a146103c3578063fae7d15c146103d6576101e5565b8063bc5920ba14610367578063c1bbe0de1461036f578063cd6dc68714610382578063d5f8fcfa14610395576101e5565b8063981b24d0116100de578063981b24d0146103265780639cadb3a014610339578063a9059cbb14610341578063ac04f24314610354576101e5565b806380ea3de1146102f05780638da5cb5b1461030357806390c95b7d1461030b57806395d89b411461031e576101e5565b806329a2293d116101875780634ee2cd7e116101565780634ee2cd7e146102ad5780636c8381f8146102c057806370a08231146102d5578063715018a6146102e8576101e5565b806329a2293d146102755780632def662014610288578063313ce567146102905780633ccfd60b146102a5576101e5565b8063095ea7b3116101c3578063095ea7b31461022557806313af40351461024557806318160ddd1461025a57806323b872dd14610262576101e5565b8063032370dc146101ea57806304646a491461020857806306fdde0314610210575b600080fd5b6101f26103e9565b6040516101ff9190612c68565b60405180910390f35b6101f26103f1565b6102186103f8565b6040516101ff9190612609565b6102386102333660046124c2565b610486565b6040516101ff91906125fe565b61025861025336600461242e565b6104a9565b005b6101f2610582565b610238610270366004612482565b6105a1565b6101f261028336600461242e565b6105bb565b6102586105ce565b6102986107a7565b6040516101ff9190612c71565b6102586107b1565b6101f26102bb3660046124c2565b61089c565b6102c86108b4565b6040516101ff91906125ad565b6101f26102e336600461242e565b6108c3565b6102586108e1565b6102586102fe366004612561565b610960565b6102c86109b8565b6101f261031936600461242e565b6109c7565b6102186109da565b6101f2610334366004612561565b610a35565b6102c8610a43565b61023861034f3660046124c2565b610a53565b61025861036236600461250d565b610a6d565b610258610c59565b6102c861037d366004612561565b610d1c565b6102586103903660046124c2565b610d44565b6102386103a336600461242e565b610e8e565b6101f26103b636600461244a565b610efe565b6101f2610f06565b6102586103d136600461242e565b610f0b565b6102586103e436600461242e565b610fdc565b610105545b90565b6101075481565b60fe805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561047e5780601f106104535761010080835404028352916020019161047e565b820191906000526020600020905b81548152906001019060200180831161046157829003601f168201915b505050505081565b600060405162461bcd60e51b81526004016104a0906129b3565b60405180910390fd5b6104b161109c565b6098546001600160a01b039081169116146104de5760405162461bcd60e51b81526004016104a090612b67565b6001600160a01b0381166105045760405162461bcd60e51b81526004016104a090612923565b6098546001600160a01b03828116911614156105325760405162461bcd60e51b81526004016104a090612beb565b6099546001600160a01b03828116911614156105605760405162461bcd60e51b81526004016104a090612709565b609980546001600160a01b0319166001600160a01b0392909216919091179055565b600061059c6105976105926110a0565b6110a4565b6110da565b905090565b600060405162461bcd60e51b81526004016104a0906126aa565b6101036020526000908152604090205481565b60006105d861109c565b90506105e26110de565b6001600160a01b03811660009081526101046020908152604091829020825191820190925290548152610614906110da565b156106315760405162461bcd60e51b81526004016104a0906127ce565b610639612383565b60405180602001604052806106726101026000866001600160a01b03166001600160a01b03168152602001908152602001600020611100565b9052905061067f8161114b565b6106898282611176565b6106a461010754610698611284565b9063ffffffff61128816565b6001600160a01b038316600090815261010360209081526040808320939093556101049052908120825190555b610105548110156107615761010581815481106106ea57fe5b60009182526020909120015460405163cd8ae3dd60e01b81526001600160a01b039091169063cd8ae3dd906107239086906004016125ad565b600060405180830381600087803b15801561073d57600080fd5b505af1158015610751573d6000803e3d6000fd5b5050600190920191506106d19050565b507f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f758261078d836110da565b60405161079b9291906125e5565b60405180910390a15050565b6101005460ff1681565b60006107bb61109c565b90506107c5612383565b506001600160a01b038116600090815261010460209081526040918290208251918201909252905481526107f88161114b565b6001600160a01b0382166000908152610103602052604090205461081a611284565b10156108385760405162461bcd60e51b81526004016104a0906128f8565b6001600160a01b0380831660009081526101046020908152604080832083905561010390915281205561010654610871911683836112ad565b7f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d58261078d836110da565b60006108ab61059784846113dc565b90505b92915050565b6099546001600160a01b031690565b60006108d9610597836108d46110a0565b6113dc565b90505b919050565b6108e961109c565b6098546001600160a01b039081169116146109165760405162461bcd60e51b81526004016104a090612b67565b6098546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3609880546001600160a01b0319169055565b61096861109c565b6098546001600160a01b039081169116146109955760405162461bcd60e51b81526004016104a090612b67565b806109b25760405162461bcd60e51b81526004016104a090612aaf565b61010755565b6098546001600160a01b031690565b6101046020526000908152604090205481565b60ff805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561047e5780601f106104535761010080835404028352916020019161047e565b60006108d9610597836110a4565b610106546001600160a01b031681565b600060405162461bcd60e51b81526004016104a090612a78565b610a84610a7f36839003830183612524565b61114b565b610a8c6110de565b6000610a9661109c565b9050610aa0612383565b610aaf36849003840184612524565b6001600160a01b03831660009081526101046020908152604091829020825191820190925290548152909150610ae4906110da565b15610b4e576001600160a01b03821660009081526101046020908152604091829020825191820190925290548152610b2390829063ffffffff61142916565b6001600160a01b03831660009081526101046020908152604080832083905561010390915281205590505b61010654610b75906001600160a01b03168330610b7036889003880188612524565b611455565b610b7f8282611587565b60005b61010554811015610c12576101058181548110610b9b57fe5b60009182526020909120015460405163cd8ae3dd60e01b81526001600160a01b039091169063cd8ae3dd90610bd49086906004016125ad565b600060405180830381600087803b158015610bee57600080fd5b505af1158015610c02573d6000803e3d6000fd5b505060019092019150610b829050565b507f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d82610c3e836110da565b604051610c4c9291906125e5565b60405180910390a1505050565b6099546001600160a01b0316610c815760405162461bcd60e51b81526004016104a090612b18565b610c8961109c565b6099546001600160a01b03908116911614610cb65760405162461bcd60e51b81526004016104a090612750565b6099546098546040516001600160a01b0392831692909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360998054609880546001600160a01b03199081166001600160a01b03841617909155169055565b6101058181548110610d2a57fe5b6000918252602090912001546001600160a01b0316905081565b603354610100900460ff1680610d5d5750610d5d611677565b80610d6b575060335460ff16155b610d875760405162461bcd60e51b81526004016104a090612965565b603354610100900460ff16158015610db2576033805460ff1961ff0019909116610100171660011790555b6001600160a01b038316610dd85760405162461bcd60e51b81526004016104a0906126e1565b610de061167d565b6040805180820190915260108082526f14dd185ad9590814195c9c195d1d585b60821b6020909201918252610e179160fe91612396565b5060408051808201909152600580825264073504552560dc1b6020909201918252610e449160ff91612396565b50610100805460ff1916601217905561010680546001600160a01b0385166001600160a01b03199091161790556101078290558015610e89576033805461ff00191690555b505050565b60006108d982610105805480602002602001604051908101604052809291908181526020018280548015610eeb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ecd575b505050505061170f90919063ffffffff16565b600092915050565b601481565b610f1361109c565b6098546001600160a01b03908116911614610f405760405162461bcd60e51b81526004016104a090612b67565b6000610f546101058363ffffffff61176516565b90506001600160a01b038116610f7c5760405162461bcd60e51b81526004016104a090612bb4565b816001600160a01b0316816001600160a01b031614610fad5760405162461bcd60e51b81526004016104a090612880565b7f2c54da8cf6b6d65b4bd7e9bf095dd4d133a2ce5731ebb20a4f1bcc3db90294308260405161079b91906125ad565b610fe461109c565b6098546001600160a01b039081169116146110115760405162461bcd60e51b81526004016104a090612b67565b610105546014116110345760405162461bcd60e51b81526004016104a090612797565b6110466101058263ffffffff61187116565b6110625760405162461bcd60e51b81526004016104a090612aaf565b7f9400eb2cfb16fdd3f18022e33f5d4b757dea0c4367d95f0495f6af5911e1e9148160405161109191906125ad565b60405180910390a150565b3390565b4390565b6110ac612383565b60405180602001604052806110d26110c38561192a565b6101019063ffffffff61198916565b905292915050565b5190565b610105546110fe5760405162461bcd60e51b81526004016104a090612a2b565b565b805460009080156111425782600001600182038154811061111d57fe5b600091825260209091200154600160401b90046001600160c01b031691506108dc9050565b50600092915050565b6000611156826110da565b116111735760405162461bcd60e51b81526004016104a090612a53565b50565b6001600160a01b03821661119c5760405162461bcd60e51b81526004016104a0906129ea565b6111a4612383565b60405180602001604052806111b8856108c3565b905290506111c4612383565b6111d4828463ffffffff61199516565b90506111de612383565b60405180602001604052806111f1610582565b905290506111fd612383565b61120d828663ffffffff61199516565b905060006112196110a0565b90506112268782866119b8565b61123081836119fb565b60006001600160a01b0388167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef611266896110da565b6040516112739190612c68565b60405180910390a350505050505050565b4290565b6000828201838110156108ab5760405162461bcd60e51b81526004016104a090612673565b6112b683611a27565b6112be612383565b6112c88484611a71565b905060006112d68584611afe565b905060006060866001600160a01b031663a9059cbb60e01b87856040516024016113019291906125e5565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161133f9190612591565b6000604051808303816000865af19150503d806000811461137c576040519150601f19603f3d011682016040523d82523d6000602084013e611381565b606091505b50915091508180156113ab5750805115806113ab5750808060200190518101906113ab91906124ed565b6113c75760405162461bcd60e51b81526004016104a09061263c565b6113d387878587611b7c565b50505050505050565b6113e4612383565b60405180602001604052806114206113fb8561192a565b6001600160a01b0387166000908152610102602052604090209063ffffffff61198916565b90529392505050565b611431612383565b611439612383565b8251845161144c9163ffffffff61128816565b81529392505050565b61145e84611a27565b611466612383565b6114708584611a71565b9050600061147e8684611afe565b905060006060876001600160a01b03166323b872dd60e01b8888866040516024016114ab939291906125c1565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114e99190612591565b6000604051808303816000865af19150503d8060008114611526576040519150601f19603f3d011682016040523d82523d6000602084013e61152b565b606091505b509150915081801561155557508051158061155557508080602001905181019061155591906124ed565b6115715760405162461bcd60e51b81526004016104a09061283f565b61157d88878587611b7c565b5050505050505050565b6001600160a01b0382166115ad5760405162461bcd60e51b81526004016104a090612c31565b6115b5612383565b60405180602001604052806115c9856108c3565b905290506115d5612383565b6115e5828463ffffffff61142916565b90506115ef612383565b6040518060200160405280611602610582565b9052905061160e612383565b61161e828663ffffffff61142916565b9050600061162a6110a0565b90506116378782866119b8565b61164181836119fb565b6001600160a01b03871660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef611266896110da565b303b1590565b603354610100900460ff16806116965750611696611677565b806116a4575060335460ff16155b6116c05760405162461bcd60e51b81526004016104a090612965565b603354610100900460ff161580156116eb576033805460ff1961ff0019909116610100171660011790555b6116f3611bd5565b6116fb611c56565b8015611173576033805461ff001916905550565b6000805b835181101561175b5783818151811061172857fe5b60200260200101516001600160a01b0316836001600160a01b031614156117535760019150506108ae565b600101611713565b5060009392505050565b60006001600160a01b03821661177d575060006108ae565b825460005b818110156118665784818154811061179657fe5b6000918252602090912001546001600160a01b038581169116141561185e57600182038114611827578460018303815481106117ce57fe5b9060005260206000200160009054906101000a90046001600160a01b03168582815481106117f857fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b8480548061183157fe5b600082815260209020810160001990810180546001600160a01b0319169055019055508291506108ae9050565b600101611782565b506000949350505050565b60006001600160a01b03821615806118e757506118e7838054806020026020016040519081016040528092919081815260200182805480156118dc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116118be575b50505050508361170f565b156118f4575060006108ae565b50815460018082018455600093845260209093200180546001600160a01b0319166001600160a01b039290921691909117905590565b60408051808201909152601581527455494e5436345f4e554d4245525f544f4f5f42494760581b602082015260009067ffffffffffffffff8311156119825760405162461bcd60e51b81526004016104a09190612609565b5090919050565b60006108ab8383611d30565b61199d612383565b6119a5612383565b8251845161144c9163ffffffff611ec116565b610e896119c48361192a565b6119d56119d0846110da565b611f03565b6001600160a01b038616600090815261010260205260409020919063ffffffff611f5b16565b611a23611a078361192a565b611a136119d0846110da565b610101919063ffffffff611f5b16565b5050565b6000611a32826120fd565b6001600160a01b0383166000908152602081905260409020549091508114611a23576001600160a01b0391909116600090815260208190526040902055565b611a79612383565b6108ab83846001600160a01b03166370a08231856040518263ffffffff1660e01b8152600401611aa991906125ad565b60206040518083038186803b158015611ac157600080fd5b505afa158015611ad5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af99190612579565b6121ea565b600080611b0a846120fd565b905060128110611b4857611b40611b2882601263ffffffff611ec116565b600a0a611b34856110da565b9063ffffffff61227c16565b9150506108ae565b611b74611b5c60128363ffffffff611ec116565b600a0a611b68856110da565b9063ffffffff6122b616565b949350505050565b611baf611b99611b8c86856121ea565b839063ffffffff61142916565b611ba38686611a71565b9063ffffffff6122f816565b60000b15611bcf5760405162461bcd60e51b81526004016104a090612ad6565b50505050565b603354610100900460ff1680611bee5750611bee611677565b80611bfc575060335460ff16155b611c185760405162461bcd60e51b81526004016104a090612965565b603354610100900460ff161580156116fb576033805460ff1961ff0019909116610100171660011790558015611173576033805461ff001916905550565b603354610100900460ff1680611c6f5750611c6f611677565b80611c7d575060335460ff16155b611c995760405162461bcd60e51b81526004016104a090612965565b603354610100900460ff16158015611cc4576033805460ff1961ff0019909116610100171660011790555b6000611cce61109c565b609880546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015611173576033805461ff001916905550565b815460009080611d445760009150506108ae565b8354600019820190600090869083908110611d5b57fe5b6000918252602090912001805490915067ffffffffffffffff90811690861610611d9a5754600160401b90046001600160c01b031692506108ae915050565b8260011480611dd1575085600001600081548110611db457fe5b60009182526020909120015467ffffffffffffffff908116908616105b15611de257600093505050506108ae565b600060001983015b81811115611e8a578754600283830160010104906000908a9083908110611e0d57fe5b6000918252602090912001805490915067ffffffffffffffff908116908a16811015611e3b57829450611e82565b8067ffffffffffffffff168a67ffffffffffffffff161015611e6257600183039350611e82565b5054600160401b90046001600160c01b031696506108ae95505050505050565b505050611dea565b876000018281548110611e9957fe5b600091825260209091200154600160401b90046001600160c01b031698975050505050505050565b60006108ab83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612320565b60408051808201909152601681527555494e543139325f4e554d4245525f544f4f5f42494760501b60208201526000906001600160c01b038311156119825760405162461bcd60e51b81526004016104a09190612609565b825480611fce576040805180820190915267ffffffffffffffff80851682526001600160c01b0380851660208085019182528854600181018a5560008a8152919091209451940180549151909216600160401b0293831667ffffffffffffffff1990911617909116919091179055611bcf565b6000846000016001830381548110611fe257fe5b6000918252602090912001805490915067ffffffffffffffff908116908516811015612074576040805180820190915267ffffffffffffffff80871682526001600160c01b0380871660208085019182528a54600181018c5560008c8152919091209451940180549151909216600160401b0293831667ffffffffffffffff19909116179091169190911790556120f5565b808567ffffffffffffffff1614156120aa57815467ffffffffffffffff16600160401b6001600160c01b038616021782556120f5565b604080518082018252601a81527f434845434b504f494e545f504153545f434845434b504f494e540000000000006020820152905162461bcd60e51b81526104a09190600401612609565b505050505050565b6001600160a01b038116600090815260208190526040812054806108d95760408051600481526024810182526020810180516001600160e01b031663313ce56760e01b17905290516000916060916001600160a01b0387169161215f91612591565b600060405180830381855afa9150503d806000811461219a576040519150601f19603f3d011682016040523d82523d6000602084013e61219f565b606091505b50915091508180156121b15750805115155b6121cd5760405162461bcd60e51b81526004016104a0906127fe565b808060200190518101906121e19190612579565b95945050505050565b6121f2612383565b60006121fd846120fd565b9050601281106122425760408051602081019091528061223761222784601263ffffffff611ec116565b8690600a0a63ffffffff6122b616565b8152509150506108ae565b60408051602081019091528061227261226260128563ffffffff611ec116565b8690600a0a63ffffffff61227c16565b9052949350505050565b60008261228b575060006108ae565b8282028284828161229857fe5b04146108ab5760405162461bcd60e51b81526004016104a0906128b7565b60006108ab83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061234c565b80518251600091101561230d575060016108ae565b81518351101561114257506000196108ae565b600081848411156123445760405162461bcd60e51b81526004016104a09190612609565b505050900390565b6000818361236d5760405162461bcd60e51b81526004016104a09190612609565b50600083858161237957fe5b0495945050505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106123d757805160ff1916838001178555612404565b82800160010185558215612404579182015b828111156124045782518255916020019190600101906123e9565b50612410929150612414565b5090565b6103ee91905b80821115612410576000815560010161241a565b60006020828403121561243f578081fd5b81356108ab81612cab565b6000806040838503121561245c578081fd5b823561246781612cab565b9150602083013561247781612cab565b809150509250929050565b600080600060608486031215612496578081fd5b83356124a181612cab565b925060208401356124b181612cab565b929592945050506040919091013590565b600080604083850312156124d4578182fd5b82356124df81612cab565b946020939093013593505050565b6000602082840312156124fe578081fd5b815180151581146108ab578182fd5b60006020828403121561251e578081fd5b50919050565b600060208284031215612535578081fd5b6040516020810181811067ffffffffffffffff82111715612554578283fd5b6040529135825250919050565b600060208284031215612572578081fd5b5035919050565b60006020828403121561258a578081fd5b5051919050565b600082516125a3818460208701612c7f565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082528251806020840152612628816040850160208701612c7f565b601f01601f19169190910160400192915050565b6020808252601d908201527f446563696d616c45524332303a207472616e73666572206661696c6564000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f7472616e7366657246726f6d2829206973206e6f7420737570706f7274656400604082015260600190565b6020808252600e908201526d24b73b30b634b21034b7383aba1760911b604082015260600190565b60208082526027908201527f5065727046694f776e61626c65557067726164653a2073616d652061732063616040820152666e64696461746560c81b606082015260800190565b60208082526027908201527f5065727046694f776e61626c65557067726164653a206e6f7420746865206e656040820152663b9037bbb732b960c91b606082015260800190565b6020808252601f908201527f657863656564207374616b654d6f64756c6520616d6f756e74206c696d697400604082015260600190565b60208082526016908201527513995959081d1bc81dda5d1a191c985dc8199a5c9cdd60521b604082015260600190565b60208082526021908201527f446563696d616c45524332303a2067657420646563696d616c73206661696c656040820152601960fa1b606082015260800190565b60208082526021908201527f446563696d616c45524332303a207472616e7366657246726f6d206661696c656040820152601960fa1b606082015260800190565b60208082526018908201527f72656d6f76652077726f6e67207374616b654d6f64756c650000000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526011908201527029ba34b6361034b71031b7b7b63237bbb760791b604082015260600190565b60208082526022908201527f5065727046694f776e61626c65557067726164653a207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b6020808252601a908201527f617070726f76652829206973206e6f7420737570706f72746564000000000000604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252600e908201526d6e6f207374616b654d6f64756c6560901b604082015260600190565b6020808252600b908201526a0416d6f756e7420697320360ac1b604082015260600190565b6020808252601b908201527f7472616e736665722829206973206e6f7420737570706f727465640000000000604082015260600190565b6020808252600d908201526c1a5b9d985b1a59081a5b9c1d5d609a1b604082015260600190565b60208082526022908201527f446563696d616c45524332303a2062616c616e636520696e636f6e73697374656040820152611b9d60f21b606082015260800190565b6020808252602f908201527f5065727046694f776e61626c65557067726164653a2063616e6469646174652060408201526e6973207a65726f206164647265737360881b606082015260800190565b6020808252602d908201527f5065727046694f776e61626c65557067726164653a2063616c6c65722069732060408201526c3737ba103a34329037bbb732b960991b606082015260800190565b6020808252601a908201527f7374616b654d6f64756c6520646f6573206e6f74206578697374000000000000604082015260600190565b60208082526026908201527f5065727046694f776e61626c65557067726164653a2073616d65206173206f726040820152651a59da5b985b60d21b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b90815260200190565b60ff91909116815260200190565b60005b83811015612c9a578181015183820152602001612c82565b83811115611bcf5750506000910152565b6001600160a01b038116811461117357600080fdfea2646970667358221220e4dcdc7c83d398983ef44aef6b5a0f335390c887c7fd524f49c344617cb1601864736f6c63430006090033
Verified Source Code Partial Match
Compiler: v0.6.9+commit.3e3065ac
EVM: istanbul
Optimization: Yes (200 runs)
Decimal.sol 81 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
import { SafeMath } from "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import { DecimalMath } from "./DecimalMath.sol";
library Decimal {
using DecimalMath for uint256;
using SafeMath for uint256;
struct decimal {
uint256 d;
}
function zero() internal pure returns (decimal memory) {
return decimal(0);
}
function one() internal pure returns (decimal memory) {
return decimal(DecimalMath.unit(18));
}
function toUint(decimal memory x) internal pure returns (uint256) {
return x.d;
}
function modD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
return decimal(x.d.mul(DecimalMath.unit(18)) % y.d);
}
function cmp(decimal memory x, decimal memory y) internal pure returns (int8) {
if (x.d > y.d) {
return 1;
} else if (x.d < y.d) {
return -1;
}
return 0;
}
/// @dev add two decimals
function addD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
decimal memory t;
t.d = x.d.add(y.d);
return t;
}
/// @dev subtract two decimals
function subD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
decimal memory t;
t.d = x.d.sub(y.d);
return t;
}
/// @dev multiple two decimals
function mulD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
decimal memory t;
t.d = x.d.muld(y.d);
return t;
}
/// @dev multiple a decimal by a uint256
function mulScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
decimal memory t;
t.d = x.d.mul(y);
return t;
}
/// @dev divide two decimals
function divD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
decimal memory t;
t.d = x.d.divd(y.d);
return t;
}
/// @dev divide a decimal by a uint256
function divScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
decimal memory t;
t.d = x.d.div(y);
return t;
}
}
DecimalMath.sol 53 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
import { SafeMath } from "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
/// @dev Implements simple fixed point math add, sub, mul and div operations.
/// @author Alberto Cuesta Cañada
library DecimalMath {
using SafeMath for uint256;
/// @dev Returns 1 in the fixed point representation, with `decimals` decimals.
function unit(uint8 decimals) internal pure returns (uint256) {
return 10**uint256(decimals);
}
/// @dev Adds x and y, assuming they are both fixed point with 18 decimals.
function addd(uint256 x, uint256 y) internal pure returns (uint256) {
return x.add(y);
}
/// @dev Subtracts y from x, assuming they are both fixed point with 18 decimals.
function subd(uint256 x, uint256 y) internal pure returns (uint256) {
return x.sub(y);
}
/// @dev Multiplies x and y, assuming they are both fixed point with 18 digits.
function muld(uint256 x, uint256 y) internal pure returns (uint256) {
return muld(x, y, 18);
}
/// @dev Multiplies x and y, assuming they are both fixed point with `decimals` digits.
function muld(
uint256 x,
uint256 y,
uint8 decimals
) internal pure returns (uint256) {
return x.mul(y).div(unit(decimals));
}
/// @dev Divides x between y, assuming they are both fixed point with 18 digits.
function divd(uint256 x, uint256 y) internal pure returns (uint256) {
return divd(x, y, 18);
}
/// @dev Divides x between y, assuming they are both fixed point with `decimals` digits.
function divd(
uint256 x,
uint256 y,
uint8 decimals
) internal pure returns (uint256) {
return x.mul(unit(decimals)).div(y);
}
}
AddressArray.sol 37 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
library AddressArray {
function add(address[] storage addrArray, address addr) internal returns (bool) {
if (addr == address(0) || isExisted(addrArray, addr)) {
return false;
}
addrArray.push(addr);
return true;
}
function remove(address[] storage addrArray, address addr) internal returns (address) {
if (addr == address(0)) {
return address(0);
}
uint256 lengthOfArray = addrArray.length;
for (uint256 i; i < lengthOfArray; i++) {
if (addr == addrArray[i]) {
if (i != lengthOfArray - 1) {
addrArray[i] = addrArray[lengthOfArray - 1];
}
addrArray.pop();
return addr;
}
}
return address(0);
}
function isExisted(address[] memory addrArray, address addr) internal pure returns (bool) {
for (uint256 i; i < addrArray.length; i++) {
if (addr == addrArray[i]) return true;
}
return false;
}
}
BlockContext.sol 19 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
// wrap block.xxx functions for testing
// only support timestamp and number so far
abstract contract BlockContext {
//◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//
//◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣ add state variables above ◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣//
uint256[50] private __gap;
function _blockTimestamp() internal view virtual returns (uint256) {
return block.timestamp;
}
function _blockNumber() internal view virtual returns (uint256) {
return block.number;
}
}
DecimalERC20.sol 149 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
import { IERC20 } from "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
import { SafeMath } from "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import { Decimal } from "./Decimal.sol";
abstract contract DecimalERC20 {
using SafeMath for uint256;
using Decimal for Decimal.decimal;
mapping(address => uint256) private decimalMap;
//◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//
//◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣ add state variables above ◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣//
uint256[50] private __gap;
//
// INTERNAL functions
//
// CAUTION: do not input _from == _to s.t. this function will always fail
function _transfer(
IERC20 _token,
address _to,
Decimal.decimal memory _value
) internal {
_updateDecimal(address(_token));
Decimal.decimal memory balanceBefore = _balanceOf(_token, _to);
uint256 roundedDownValue = _toUint(_token, _value);
// solhint-disable avoid-low-level-calls
(bool success, bytes memory data) =
address(_token).call(abi.encodeWithSelector(_token.transfer.selector, _to, roundedDownValue));
require(success && (data.length == 0 || abi.decode(data, (bool))), "DecimalERC20: transfer failed");
_validateBalance(_token, _to, roundedDownValue, balanceBefore);
}
function _transferFrom(
IERC20 _token,
address _from,
address _to,
Decimal.decimal memory _value
) internal {
_updateDecimal(address(_token));
Decimal.decimal memory balanceBefore = _balanceOf(_token, _to);
uint256 roundedDownValue = _toUint(_token, _value);
// solhint-disable avoid-low-level-calls
(bool success, bytes memory data) =
address(_token).call(abi.encodeWithSelector(_token.transferFrom.selector, _from, _to, roundedDownValue));
require(success && (data.length == 0 || abi.decode(data, (bool))), "DecimalERC20: transferFrom failed");
_validateBalance(_token, _to, roundedDownValue, balanceBefore);
}
function _approve(
IERC20 _token,
address _spender,
Decimal.decimal memory _value
) internal {
_updateDecimal(address(_token));
// to be compatible with some erc20 tokens like USDT
__approve(_token, _spender, Decimal.zero());
__approve(_token, _spender, _value);
}
//
// VIEW
//
function _allowance(
IERC20 _token,
address _owner,
address _spender
) internal view returns (Decimal.decimal memory) {
return _toDecimal(_token, _token.allowance(_owner, _spender));
}
function _balanceOf(IERC20 _token, address _owner) internal view returns (Decimal.decimal memory) {
return _toDecimal(_token, _token.balanceOf(_owner));
}
function _totalSupply(IERC20 _token) internal view returns (Decimal.decimal memory) {
return _toDecimal(_token, _token.totalSupply());
}
function _toDecimal(IERC20 _token, uint256 _number) internal view returns (Decimal.decimal memory) {
uint256 tokenDecimals = _getTokenDecimals(address(_token));
if (tokenDecimals >= 18) {
return Decimal.decimal(_number.div(10**(tokenDecimals.sub(18))));
}
return Decimal.decimal(_number.mul(10**(uint256(18).sub(tokenDecimals))));
}
function _toUint(IERC20 _token, Decimal.decimal memory _decimal) internal view returns (uint256) {
uint256 tokenDecimals = _getTokenDecimals(address(_token));
if (tokenDecimals >= 18) {
return _decimal.toUint().mul(10**(tokenDecimals.sub(18)));
}
return _decimal.toUint().div(10**(uint256(18).sub(tokenDecimals)));
}
function _getTokenDecimals(address _token) internal view returns (uint256) {
uint256 tokenDecimals = decimalMap[_token];
if (tokenDecimals == 0) {
(bool success, bytes memory data) = _token.staticcall(abi.encodeWithSignature("decimals()"));
require(success && data.length != 0, "DecimalERC20: get decimals failed");
tokenDecimals = abi.decode(data, (uint256));
}
return tokenDecimals;
}
//
// PRIVATE
//
function _updateDecimal(address _token) private {
uint256 tokenDecimals = _getTokenDecimals(_token);
if (decimalMap[_token] != tokenDecimals) {
decimalMap[_token] = tokenDecimals;
}
}
function __approve(
IERC20 _token,
address _spender,
Decimal.decimal memory _value
) private {
// solhint-disable avoid-low-level-calls
(bool success, bytes memory data) =
address(_token).call(abi.encodeWithSelector(_token.approve.selector, _spender, _toUint(_token, _value)));
require(success && (data.length == 0 || abi.decode(data, (bool))), "DecimalERC20: approve failed");
}
// To prevent from deflationary token, check receiver's balance is as expectation.
function _validateBalance(
IERC20 _token,
address _to,
uint256 _roundedDownValue,
Decimal.decimal memory _balanceBefore
) private view {
require(
_balanceOf(_token, _to).cmp(_balanceBefore.addD(_toDecimal(_token, _roundedDownValue))) == 0,
"DecimalERC20: balance inconsistent"
);
}
}
ERC20ViewOnly.sol 26 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
import { IERC20 } from "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
abstract contract ERC20ViewOnly is IERC20 {
function transfer(address, uint256) public virtual override returns (bool) {
revert("transfer() is not supported");
}
function transferFrom(
address,
address,
uint256
) public virtual override returns (bool) {
revert("transferFrom() is not supported");
}
function approve(address, uint256) public virtual override returns (bool) {
revert("approve() is not supported");
}
function allowance(address, address) public view virtual override returns (uint256) {
return 0;
}
}
IStakeModule.sol 6 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
interface IStakeModule {
function notifyStakeChanged(address staker) external;
}
StakedPerpToken.sol 267 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
import { IERC20 } from "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
import { SafeMath } from "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";
import { IERC20WithCheckpointing } from "./aragonone/IERC20WithCheckpointing.sol";
import { Checkpointing } from "./aragonone/Checkpointing.sol";
import { CheckpointingHelpers } from "./aragonone/CheckpointingHelpers.sol";
import { ERC20ViewOnly } from "../utils/ERC20ViewOnly.sol";
import { Decimal } from "../utils/Decimal.sol";
import { DecimalERC20 } from "../utils/DecimalERC20.sol";
import { BlockContext } from "../utils/BlockContext.sol";
import { PerpFiOwnableUpgrade } from "../utils/PerpFiOwnableUpgrade.sol";
import { AddressArray } from "../utils/AddressArray.sol";
import { IStakeModule } from "../interface/IStakeModule.sol";
contract StakedPerpToken is IERC20WithCheckpointing, ERC20ViewOnly, DecimalERC20, PerpFiOwnableUpgrade, BlockContext {
using Checkpointing for Checkpointing.History;
using CheckpointingHelpers for uint256;
using SafeMath for uint256;
using AddressArray for address[];
uint256 public constant TOKEN_AMOUNT_LIMIT = 20;
//
// EVENTS
//
event Staked(address staker, uint256 amount);
event Unstaked(address staker, uint256 amount);
event Withdrawn(address staker, uint256 amount);
event StakeModuleAdded(address stakedModule);
event StakeModuleRemoved(address stakedModule);
//**********************************************************//
// The below state variables can not change the order //
//**********************************************************//
// ERC20 variables
string public name;
string public symbol;
uint8 public decimals;
// ERC20 variables
// Checkpointing total supply of the deposited token
Checkpointing.History internal totalSupplyHistory;
// Checkpointing balances of the deposited token by staker
mapping(address => Checkpointing.History) internal balancesHistory;
// staker => the time staker can withdraw PERP
mapping(address => uint256) public stakerCooldown;
// staker => PERP staker can withdraw
mapping(address => Decimal.decimal) public stakerWithdrawPendingBalance;
address[] public stakeModules;
IERC20 public perpToken;
uint256 public cooldownPeriod;
//**********************************************************//
// The above state variables can not change the order //
//**********************************************************//
//◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//
//◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣ add state variables above ◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣//
uint256[50] private __gap;
//
// FUNCTIONS
//
function initialize(IERC20 _perpToken, uint256 _cooldownPeriod) external initializer {
require(address(_perpToken) != address(0), "Invalid input.");
__Ownable_init();
name = "Staked Perpetual";
symbol = "sPERP";
decimals = 18;
perpToken = _perpToken;
cooldownPeriod = _cooldownPeriod;
}
function stake(Decimal.decimal calldata _amount) external {
requireNonZeroAmount(_amount);
requireStakeModuleExisted();
address msgSender = _msgSender();
// copy calldata amount to memory
Decimal.decimal memory amount = _amount;
// stake after unstake is allowed, and the states mutated by unstake() will being undo
if (stakerWithdrawPendingBalance[msgSender].toUint() != 0) {
amount = amount.addD(stakerWithdrawPendingBalance[msgSender]);
delete stakerWithdrawPendingBalance[msgSender];
delete stakerCooldown[msgSender];
}
// if staking after unstaking, the amount to be transferred does not need to be updated
_transferFrom(perpToken, msgSender, address(this), _amount);
_mint(msgSender, amount);
// Have to update balance first
for (uint256 i; i < stakeModules.length; i++) {
IStakeModule(stakeModules[i]).notifyStakeChanged(msgSender);
}
emit Staked(msgSender, amount.toUint());
}
// this function mutates stakerWithdrawPendingBalance, stakerCooldown, addTotalSupplyCheckPoint,
// addPersonalBalanceCheckPoint, burn
function unstake() external {
address msgSender = _msgSender();
requireStakeModuleExisted();
require(stakerWithdrawPendingBalance[msgSender].toUint() == 0, "Need to withdraw first");
Decimal.decimal memory balance = Decimal.decimal(balancesHistory[msgSender].latestValue());
requireNonZeroAmount(balance);
_burn(msgSender, balance);
stakerCooldown[msgSender] = _blockTimestamp().add(cooldownPeriod);
stakerWithdrawPendingBalance[msgSender] = balance;
// Have to update balance first
for (uint256 i; i < stakeModules.length; i++) {
IStakeModule(stakeModules[i]).notifyStakeChanged(msgSender);
}
emit Unstaked(msgSender, balance.toUint());
}
function withdraw() external {
address msgSender = _msgSender();
Decimal.decimal memory balance = stakerWithdrawPendingBalance[msgSender];
requireNonZeroAmount(balance);
// there won't be a case that cooldown == 0 && balance == 0
require(_blockTimestamp() >= stakerCooldown[msgSender], "Still in cooldown");
delete stakerWithdrawPendingBalance[msgSender];
delete stakerCooldown[msgSender];
_transfer(perpToken, msgSender, balance);
emit Withdrawn(msgSender, balance.toUint());
}
function addStakeModule(IStakeModule _stakeModule) external onlyOwner {
require(stakeModules.length < TOKEN_AMOUNT_LIMIT, "exceed stakeModule amount limit");
require(stakeModules.add(address(_stakeModule)), "invalid input");
emit StakeModuleAdded(address(_stakeModule));
}
function removeStakeModule(IStakeModule _stakeModule) external onlyOwner {
address removedAddr = stakeModules.remove(address(_stakeModule));
require(removedAddr != address(0), "stakeModule does not exist");
require(removedAddr == address(_stakeModule), "remove wrong stakeModule");
emit StakeModuleRemoved(address(_stakeModule));
}
function setCooldownPeriod(uint256 _cooldownPeriod) external onlyOwner {
require(_cooldownPeriod != 0, "invalid input");
cooldownPeriod = _cooldownPeriod;
}
//
// VIEW FUNCTIONS
//
//
// override: ERC20
//
function balanceOf(address _owner) public view override returns (uint256) {
return _balanceOfAt(_owner, _blockNumber()).toUint();
}
function totalSupply() public view override returns (uint256) {
return _totalSupplyAt(_blockNumber()).toUint();
}
//
// override: IERC20WithCheckpointing
//
function balanceOfAt(address _owner, uint256 __blockNumber) external view override returns (uint256) {
return _balanceOfAt(_owner, __blockNumber).toUint();
}
function totalSupplyAt(uint256 __blockNumber) external view override returns (uint256) {
return _totalSupplyAt(__blockNumber).toUint();
}
//
// EXTERNAL FUNCTIONS
//
function getStakeModuleLength() external view returns (uint256) {
return stakeModules.length;
}
//
// INTERNAL FUNCTIONS
//
function isStakeModuleExisted(IStakeModule _stakeModule) public view returns (bool) {
return stakeModules.isExisted(address(_stakeModule));
}
function _mint(address account, Decimal.decimal memory amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
Decimal.decimal memory balance = Decimal.decimal(balanceOf(account));
Decimal.decimal memory newBalance = balance.addD(amount);
Decimal.decimal memory currentTotalSupply = Decimal.decimal(totalSupply());
Decimal.decimal memory newTotalSupply = currentTotalSupply.addD(amount);
uint256 blockNumber = _blockNumber();
addPersonalBalanceCheckPoint(account, blockNumber, newBalance);
addTotalSupplyCheckPoint(blockNumber, newTotalSupply);
emit Transfer(address(0), account, amount.toUint());
}
function _burn(address account, Decimal.decimal memory amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
Decimal.decimal memory balance = Decimal.decimal(balanceOf(account));
Decimal.decimal memory newBalance = balance.subD(amount);
Decimal.decimal memory currentTotalSupply = Decimal.decimal(totalSupply());
Decimal.decimal memory newTotalSupply = currentTotalSupply.subD(amount);
uint256 blockNumber = _blockNumber();
addPersonalBalanceCheckPoint(account, blockNumber, newBalance);
addTotalSupplyCheckPoint(blockNumber, newTotalSupply);
emit Transfer(account, address(0), amount.toUint());
}
function addTotalSupplyCheckPoint(uint256 __blockNumber, Decimal.decimal memory _amount) internal {
totalSupplyHistory.addCheckpoint(__blockNumber.toUint64Time(), _amount.toUint().toUint192Value());
}
function addPersonalBalanceCheckPoint(
address _staker,
uint256 __blockNumber,
Decimal.decimal memory _amount
) internal {
balancesHistory[_staker].addCheckpoint(__blockNumber.toUint64Time(), _amount.toUint().toUint192Value());
}
function _balanceOfAt(address _owner, uint256 __blockNumber) internal view returns (Decimal.decimal memory) {
return Decimal.decimal(balancesHistory[_owner].getValueAt(__blockNumber.toUint64Time()));
}
function _totalSupplyAt(uint256 __blockNumber) internal view returns (Decimal.decimal memory) {
return Decimal.decimal(totalSupplyHistory.getValueAt(__blockNumber.toUint64Time()));
}
//
// REQUIRE FUNCTIONS
//
function requireNonZeroAmount(Decimal.decimal memory _amount) private pure {
require(_amount.toUint() > 0, "Amount is 0");
}
function requireStakeModuleExisted() internal view {
require(stakeModules.length > 0, "no stakeModule");
}
}
PerpFiOwnableUpgrade.sol 96 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.9;
import { ContextUpgradeSafe } from "@openzeppelin/contracts-ethereum-package/contracts/GSN/Context.sol";
// copy from openzeppelin Ownable, only modify how the owner transfer
/**
* @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.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract PerpFiOwnableUpgrade is ContextUpgradeSafe {
address private _owner;
address private _candidate;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
function candidate() public view returns (address) {
return _candidate;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "PerpFiOwnableUpgrade: caller is not the 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 virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Set ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function setOwner(address newOwner) public onlyOwner {
require(newOwner != address(0), "PerpFiOwnableUpgrade: zero address");
require(newOwner != _owner, "PerpFiOwnableUpgrade: same as original");
require(newOwner != _candidate, "PerpFiOwnableUpgrade: same as candidate");
_candidate = newOwner;
}
/**
* @dev Transfers ownership of the contract to a new account (`_candidate`).
* Can only be called by the new owner.
*/
function updateOwner() public {
require(_candidate != address(0), "PerpFiOwnableUpgrade: candidate is zero address");
require(_candidate == _msgSender(), "PerpFiOwnableUpgrade: not the new owner");
emit OwnershipTransferred(_owner, _candidate);
_owner = _candidate;
_candidate = address(0);
}
uint256[50] private __gap;
}
Checkpointing.sol 120 lines
// source: https://github.com/aragonone/voting-connectors/blob/master/shared/contract-utils/contracts/Checkpointing.sol
/*
* SPDX-License-Identitifer: GPL-3.0-or-later
*/
pragma solidity 0.6.9;
/**
* @title Checkpointing
* @notice Checkpointing library for keeping track of historical values based on an arbitrary time
* unit (e.g. seconds or block numbers).
* @dev Inspired by:
* - MiniMe token (https://github.com/aragon/minime/blob/master/contracts/MiniMeToken.sol)
* - Staking (https://github.com/aragon/staking/blob/master/contracts/Checkpointing.sol)
*/
library Checkpointing {
string private constant ERROR_PAST_CHECKPOINT = "CHECKPOINT_PAST_CHECKPOINT";
struct Checkpoint {
uint64 time;
uint192 value;
}
struct History {
Checkpoint[] history;
}
function addCheckpoint(
History storage _self,
uint64 _time,
uint192 _value
) internal {
uint256 length = _self.history.length;
if (length == 0) {
_self.history.push(Checkpoint(_time, _value));
} else {
Checkpoint storage currentCheckpoint = _self.history[length - 1];
uint256 currentCheckpointTime = uint256(currentCheckpoint.time);
if (_time > currentCheckpointTime) {
_self.history.push(Checkpoint(_time, _value));
} else if (_time == currentCheckpointTime) {
currentCheckpoint.value = _value;
} else {
// ensure list ordering
revert(ERROR_PAST_CHECKPOINT);
}
}
}
function getValueAt(History storage _self, uint64 _time) internal view returns (uint256) {
return _getValueAt(_self, _time);
}
function lastUpdated(History storage _self) internal view returns (uint256) {
uint256 length = _self.history.length;
if (length > 0) {
return uint256(_self.history[length - 1].time);
}
return 0;
}
function latestValue(History storage _self) internal view returns (uint256) {
uint256 length = _self.history.length;
if (length > 0) {
return uint256(_self.history[length - 1].value);
}
return 0;
}
function _getValueAt(History storage _self, uint64 _time) private view returns (uint256) {
uint256 length = _self.history.length;
// Short circuit if there's no checkpoints yet
// Note that this also lets us avoid using SafeMath later on, as we've established that
// there must be at least one checkpoint
if (length == 0) {
return 0;
}
// Check last checkpoint
uint256 lastIndex = length - 1;
Checkpoint storage lastCheckpoint = _self.history[lastIndex];
if (_time >= lastCheckpoint.time) {
return uint256(lastCheckpoint.value);
}
// Check first checkpoint (if not already checked with the above check on last)
if (length == 1 || _time < _self.history[0].time) {
return 0;
}
// Do binary search
// As we've already checked both ends, we don't need to check the last checkpoint again
uint256 low = 0;
uint256 high = lastIndex - 1;
while (high > low) {
uint256 mid = (high + low + 1) / 2; // average, ceil round
Checkpoint storage checkpoint = _self.history[mid];
uint64 midTime = checkpoint.time;
if (_time > midTime) {
low = mid;
} else if (_time < midTime) {
// Note that we don't need SafeMath here because mid must always be greater than 0
// from the while condition
high = mid - 1;
} else {
// _time == midTime
return uint256(checkpoint.value);
}
}
return uint256(_self.history[low].value);
}
}
CheckpointingHelpers.sol 21 lines
// source: https://github.com/aragonone/voting-connectors/blob/master/shared/contract-utils/contracts/CheckpointingHelpers.sol
pragma solidity 0.6.9;
library CheckpointingHelpers {
uint256 private constant MAX_UINT64 = uint64(-1);
uint256 private constant MAX_UINT192 = uint192(-1);
string private constant ERROR_UINT64_TOO_BIG = "UINT64_NUMBER_TOO_BIG";
string private constant ERROR_UINT192_TOO_BIG = "UINT192_NUMBER_TOO_BIG";
function toUint64Time(uint256 _a) internal pure returns (uint64) {
require(_a <= MAX_UINT64, ERROR_UINT64_TOO_BIG);
return uint64(_a);
}
function toUint192Value(uint256 _a) internal pure returns (uint192) {
require(_a <= MAX_UINT192, ERROR_UINT192_TOO_BIG);
return uint192(_a);
}
}
IERC20WithCheckpointing.sol 13 lines
// source: https://github.com/aragonone/voting-connectors/blob/master/shared/contract-utils/contracts/interfaces/IERC20WithCheckpointing.sol
/*
* SPDX-License-Identitifer: GPL-3.0-or-later
*/
pragma solidity 0.6.9;
interface IERC20WithCheckpointing {
function balanceOfAt(address _owner, uint256 _blockNumber) external view returns (uint256);
function totalSupplyAt(uint256 _blockNumber) external view returns (uint256);
}
Context.sol 38 lines
pragma solidity ^0.6.0;
import "../Initializable.sol";
/*
* @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 ContextUpgradeSafe is Initializable {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}
Initializable.sol 62 lines
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;
}
SafeMath.sol 150 lines
pragma solidity ^0.6.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.
*/
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.
*/
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.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
IERC20.sol 75 lines
pragma solidity ^0.6.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
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);
}
Read Contract
TOKEN_AMOUNT_LIMIT 0xde114190 → uint256
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
balanceOfAt 0x4ee2cd7e → uint256
candidate 0x6c8381f8 → address
cooldownPeriod 0x04646a49 → uint256
decimals 0x313ce567 → uint8
getStakeModuleLength 0x032370dc → uint256
isStakeModuleExisted 0xd5f8fcfa → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
perpToken 0x9cadb3a0 → address
stakeModules 0xc1bbe0de → address
stakerCooldown 0x29a2293d → uint256
stakerWithdrawPendingBalance 0x90c95b7d → uint256
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
totalSupplyAt 0x981b24d0 → uint256
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
addStakeModule 0xfae7d15c
address _stakeModule
approve 0x095ea7b3
address
uint256
returns: bool
initialize 0xcd6dc687
address _perpToken
uint256 _cooldownPeriod
removeStakeModule 0xf0a10b1a
address _stakeModule
renounceOwnership 0x715018a6
No parameters
setCooldownPeriod 0x80ea3de1
uint256 _cooldownPeriod
setOwner 0x13af4035
address newOwner
stake 0x0d86c714
tuple _amount
transfer 0xa9059cbb
address
uint256
returns: bool
transferFrom 0x23b872dd
address
address
uint256
returns: bool
unstake 0x2def6620
No parameters
updateOwner 0xbc5920ba
No parameters
withdraw 0x3ccfd60b
No parameters
Recent Transactions
No transactions found for this address