Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xF18Dc176C10Ff6D8b5A17974126D43301F8EEB95
Balance 0 ETH
Nonce 1
Code Size 18041 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

18041 bytes
0x608060405234801561001057600080fd5b50600436106101a35760003560e01c8063641a24d2116100ee578063a493e6a211610097578063cb1c832111610071578063cb1c83211461035d578063e5e82b7c14610370578063f0d19b8914610383578063f3512f841461039657600080fd5b8063a493e6a214610324578063c0d05dd814610337578063c601bf781461034a57600080fd5b80639961cee4116100c85780639961cee4146102f65780639a206c8e14610309578063a39e96c31461031157600080fd5b8063641a24d2146102ad5780636b088d5c146102d057806397be2143146102e357600080fd5b80632c177a531161015057806348aeedf51161012a57806348aeedf5146102685780634e58ff6e1461027b57806354fd4d501461028e57600080fd5b80632c177a531461022f5780633d65c1fa146102425780633e200d4b1461025557600080fd5b8063194c63d811610181578063194c63d8146101f657806321f3da4414610209578063245395a61461021c57600080fd5b806303fa87b4146101a8578063088903a4146101ce57806310b63749146101e3575b600080fd5b6101bb6101b63660046142be565b6103a9565b6040519081526020015b60405180910390f35b6101e16101dc3660046142e9565b610521565b005b6101e16101f1366004614322565b610530565b6101e16102043660046142e9565b610828565b6101e1610217366004614363565b610bb9565b6101e161022a366004614363565b61139a565b6101e161023d366004614363565b6117d1565b6101e161025036600461438f565b611a4a565b6101e16102633660046143da565b611dd2565b6101bb6102763660046142be565b611ddf565b6101bb6102893660046142be565b611f84565b60005461029b9060ff1681565b60405160ff90911681526020016101c5565b6102c06102bb3660046142be565b61207a565b60405190151581526020016101c5565b6101e16102de3660046143da565b6120d1565b6101bb6102f13660046142be565b6120db565b6101bb6103043660046142be565b61229f565b6101bb6123e9565b6101e161031f366004614363565b612419565b6101bb6103323660046142be565b612850565b6101bb6103453660046142be565b612a9a565b6101e1610358366004614363565b612b02565b6101e161036b366004614363565b612e27565b6101bb61037e3660046142be565b6132ba565b6101bb6103913660046142be565b61344e565b6101bb6103a43660046142be565b61369d565b6000806103ea6040518060400160405280601381526020017f726f636b65744e6574776f726b507269636573000000000000000000000000008152506136ee565b9050600061042c6040518060400160405280601d81526020017f726f636b657444414f50726f746f636f6c53657474696e67734e6f64650000008152506136ee565b90506000816001600160a01b0316636fdbe57b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561046e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049291906143f3565b9050600061049f86612850565b9050836001600160a01b031663724d4a096040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050391906143f3565b61050d838361443b565b6105179190614452565b9695505050505050565b61052c338383611a4a565b5050565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e67000000000000000000000000000000815250306105968260405160200161057b919061448d565b6040516020818303038152906040528051906020012061375d565b6001600160a01b0316816001600160a01b0316146105fb5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064015b60405180910390fd5b6040517f636f6e74726163742e657869737473000000000000000000000000000000000060208201526bffffffffffffffffffffffff193360601b16602f82015261065f906043015b604051602081830303815290604052805190602001206137e8565b6106d05760405162461bcd60e51b8152602060048201526024808201527f496e76616c6964206f72206f75746461746564206e6574776f726b20636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6040517f6e6f64652e65786973747300000000000000000000000000000000000000000060208201526bffffffffffffffffffffffff19606087901b16602b820152859061072090603f01610644565b61076c5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964206e6f6465000000000000000000000000000000000000000060448201526064016105f2565b836107768761229f565b10156107c45760405162461bcd60e51b815260206004820152601b60248201527f53656e6465722068617320696e73756666696369656e742052504c000000000060448201526064016105f2565b6107ce8685613873565b6107d88585613a4c565b604080518581524260208201526001600160a01b0380881692908916917f3bf4a4ef95ccf3119f6977afa759933d4edd361281f5c3b91203f43104fa3432910160405180910390a3505050505050565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e67000000000000000000000000000000815250306108738260405160200161057b919061448d565b6001600160a01b0316816001600160a01b0316146108d35760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b8360006109146040518060400160405280601181526020017f726f636b65744e6f64654d616e616765720000000000000000000000000000008152506136ee565b6040517fe667d8280000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529192509082169063e667d82890602401602060405180830381865afa158015610977573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099b91906144e5565b15610aad576040517fb71f0c7c0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526000919083169063b71f0c7c90602401602060405180830381865afa158015610a03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a279190614502565b9050336001600160a01b03821614610aa75760405162461bcd60e51b815260206004820152602a60248201527f4d7573742062652063616c6c65642066726f6d2052504c20776974686472617760448201527f616c20616464726573730000000000000000000000000000000000000000000060648201526084016105f2565b50610b05565b336001600160a01b03831614610b055760405162461bcd60e51b815260206004820181905260248201527f4d7573742062652063616c6c65642066726f6d206e6f6465206164647265737360448201526064016105f2565b6040517f72706c2e6c6f636b696e672e616c6c6f7765640000000000000000000000000060208201526bffffffffffffffffffffffff19606088901b166033820152610b6b906047015b6040516020818303038152906040528051906020012086613b91565b6040805186151581524260208201526001600160a01b038816917f6b33e987d80ef301261d0265922ffe70da2b332f0e097034ce01dbb998cbd01391015b60405180910390a2505050505050565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e6700000000000000000000000000000081525030610c048260405160200161057b919061448d565b6001600160a01b0316816001600160a01b031614610c645760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b6040517f6e6f64652e65786973747300000000000000000000000000000000000000000060208201526bffffffffffffffffffffffff19606086901b16602b820152610cb290603f01610644565b610cfe5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964206e6f6465000000000000000000000000000000000000000060448201526064016105f2565b6000610d3e6040518060400160405280601181526020017f726f636b65744e6f64654d616e616765720000000000000000000000000000008152506136ee565b6040517fb71f0c7c0000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015291925060009183169063b71f0c7c90602401602060405180830381865afa158015610da3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc79190614502565b6040517fe667d8280000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301529192509083169063e667d82890602401602060405180830381865afa158015610e2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4e91906144e5565b15610eb057336001600160a01b03821614610eab5760405162461bcd60e51b815260206004820152600e60248201527f496e76616c69642063616c6c657200000000000000000000000000000000000060448201526064016105f2565b610fad565b600080546040517f5b49ff620000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015261010090920490911690635b49ff6290602401602060405180830381865afa158015610f1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3e9190614502565b9050336001600160a01b0388161480610f5f5750336001600160a01b038216145b610fab5760405162461bcd60e51b815260206004820152600e60248201527f496e76616c69642063616c6c657200000000000000000000000000000000000060448201526064016105f2565b505b6000610fed6040518060400160405280602081526020017f726f636b657444414f50726f746f636f6c53657474696e6773526577617264738152506136ee565b9050600061102f6040518060400160405280600b81526020017f726f636b65745661756c740000000000000000000000000000000000000000008152506136ee565b9050816001600160a01b03166394e5d5126040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109391906143f3565b61109c89612a9a565b6110a6904261451f565b101561111a5760405162461bcd60e51b815260206004820152602d60248201527f546865207769746864726177616c20636f6f6c646f776e20706572696f64206860448201527f6173206e6f74207061737365640000000000000000000000000000000000000060648201526084016105f2565b60006111258961229f565b905060006111328a61369d565b90508861113f828461451f565b10156111b35760405162461bcd60e51b815260206004820152603360248201527f5769746864726177616c20616d6f756e742065786365656473206e6f6465277360448201527f207374616b65642052504c2062616c616e63650000000000000000000000000060648201526084016105f2565b806111bd8b611f84565b6111c79190614532565b6111d18a8461451f565b101561126b5760405162461bcd60e51b815260206004820152604860248201527f4e6f64652773207374616b65642052504c2062616c616e63652061667465722060448201527f7769746864726177616c206973206c657373207468616e20726571756972656460648201527f2062616c616e6365000000000000000000000000000000000000000000000000608482015260a4016105f2565b61127489613c19565b61127e8a8a613873565b826001600160a01b03166301e33667866112cc6040518060400160405280600e81526020017f726f636b6574546f6b656e52504c0000000000000000000000000000000000008152506136ee565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018c9052606401600060405180830381600087803b15801561133357600080fd5b505af1158015611347573d6000803e3d6000fd5b5050604080518c81524260208201526001600160a01b038e1693507f9947063f70b076145616018b82ed1dd5585e15b7ae0a0b17a8b06bec4c4c31e292500160405180910390a250505050505050505050565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e67000000000000000000000000000000815250306113e58260405160200161057b919061448d565b6001600160a01b0316816001600160a01b0316146114455760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b336114988160405160200161064491907f6d696e69706f6f6c2e6578697374730000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff1916600f82015260230190565b6114e45760405162461bcd60e51b815260206004820152601060248201527f496e76616c6964206d696e69706f6f6c0000000000000000000000000000000060448201526064016105f2565b60006115246040518060400160405280601381526020017f726f636b65744e6574776f726b507269636573000000000000000000000000008152506136ee565b905060006115666040518060400160405280600b81526020017f726f636b65745661756c740000000000000000000000000000000000000000008152506136ee565b90506000826001600160a01b031663724d4a096040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115cc91906143f3565b6115de88670de0b6b3a764000061443b565b6115e89190614452565b905060006115f58961229f565b905080821115611603578091505b811561170357826001600160a01b031663ee91035e6116566040518060400160405280600e81526020017f726f636b6574546f6b656e52504c0000000000000000000000000000000000008152506136ee565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260606004820152601460648201527f726f636b657441756374696f6e4d616e6167657200000000000000000000000060848201526001600160a01b0390911660248201526044810185905260a401600060405180830381600087803b1580156116ea57600080fd5b505af11580156116fe573d6000803e3d6000fd5b505050505b61170c82613c19565b6117168983613873565b6040517f6d696e69706f6f6c2e72706c2e736c617368656400000000000000000000000060208201526bffffffffffffffffffffffff193360601b16603482015261177b90604801604051602081830303815290604052805190602001206001613b91565b60408051838152602081018a9052428183015290516001600160a01b038b16917f38a2777b6a84fdb3fc375fe8ade69fdad1afdcdd93c79e7ae2319b806a626c4d919081900360600190a2505050505050505050565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e670000000000000000000000000000008152503061181c8260405160200161057b919061448d565b6001600160a01b0316816001600160a01b03161461187c5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b6040517f636f6e74726163742e657869737473000000000000000000000000000000000060208201526bffffffffffffffffffffffff193360601b16602f8201526118c990604301610644565b61193a5760405162461bcd60e51b8152602060048201526024808201527f496e76616c6964206f72206f75746461746564206e6574776f726b20636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6040517f72706c2e6c6f636b65642e6e6f64652e616d6f756e740000000000000000000060208201526bffffffffffffffffffffffff19606086901b166036820152600090604a0160405160208183030381529060405280519060200120905060006119a582613c43565b9050808511156119f75760405162461bcd60e51b815260206004820152601560248201527f4e6f7420656e6f756768206c6f636b65642052504c000000000000000000000060448201526064016105f2565b611a0a82611a05878461451f565b613cce565b604080518681524260208201526001600160a01b038816917f95f42213e171837caaa6cc7f589ef03a30179b7b85e386dfb146a30c5b10cfa99101610ba9565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e6700000000000000000000000000000081525030611a958260405160200161057b919061448d565b6001600160a01b0316816001600160a01b031614611af55760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b846000611b366040518060400160405280601181526020017f726f636b65744e6f64654d616e616765720000000000000000000000000000008152506136ee565b6040517fe667d8280000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529192509082169063e667d82890602401602060405180830381865afa158015611b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbd91906144e5565b15611ccf576040517fb71f0c7c0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526000919083169063b71f0c7c90602401602060405180830381865afa158015611c25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c499190614502565b9050336001600160a01b03821614611cc95760405162461bcd60e51b815260206004820152602a60248201527f4d7573742062652063616c6c65642066726f6d2052504c20776974686472617760448201527f616c20616464726573730000000000000000000000000000000000000000000060648201526084016105f2565b50611d27565b336001600160a01b03831614611d275760405162461bcd60e51b815260206004820181905260248201527f4d7573742062652063616c6c65642066726f6d206e6f6465206164647265737360448201526064016105f2565b6040517f6e6f64652e7374616b652e666f722e616c6c6f7765640000000000000000000060208201526bffffffffffffffffffffffff19606089811b8216603684015288901b16604a820152611d7f90605e01610b4f565b6040805186151581524260208201526001600160a01b0380891692908a16917fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec5910160405180910390a350505050505050565b611ddc3382612e27565b50565b600080611e206040518060400160405280601d81526020017f726f636b657444414f50726f746f636f6c53657474696e67734e6f64650000008152506136ee565b90506000816001600160a01b0316636fdbe57b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8691906143f3565b905080600003611eb957507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9392505050565b6000611ef96040518060400160405280601381526020017f726f636b65744e6574776f726b507269636573000000000000000000000000008152506136ee565b905081816001600160a01b031663724d4a096040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e91906143f3565b611f678761229f565b611f71919061443b565b611f7b9190614452565b95945050505050565b600080611fc56040518060400160405280601381526020017f726f636b65744e6574776f726b507269636573000000000000000000000000008152506136ee565b905060006120076040518060400160405280601d81526020017f726f636b657444414f50726f746f636f6c53657474696e67734e6f64650000008152506136ee565b90506000816001600160a01b0316631e72ba866040518163ffffffff1660e01b8152600401602060405180830381865afa158015612049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206d91906143f3565b9050600061049f866132ba565b6040517f72706c2e6c6f636b696e672e616c6c6f7765640000000000000000000000000060208201526bffffffffffffffffffffffff19606083901b1660338201526000906120cb90604701610644565b92915050565b611ddc3382610bb9565b6000806120e783612850565b90508060000361210b57612104670de0b6b3a7640000600261443b565b9392505050565b600061212e604051806060016040528060218152602001614623602191396136ee565b90506000816001600160a01b03166308e50d386040518163ffffffff1660e01b8152600401602060405180830381865afa158015612170573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219491906143f3565b905060006121d66040518060400160405280601581526020017f726f636b65744d696e69706f6f6c4d616e6167657200000000000000000000008152506136ee565b6040517f1844ec010000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152919250600091849190841690631844ec0190602401602060405180830381865afa15801561223e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226291906143f3565b61226c919061443b565b9050612278858261451f565b61228a670de0b6b3a76400008361443b565b6122949190614452565b979650505050505050565b6040517f72706c2e7374616b65642e6e6f64652e616d6f756e740000000000000000000060208201526bffffffffffffffffffffffff19606083901b1660368201526000908190604a0160405160208183030381529060405280519060200120905060006123416040518060400160405280601681526020017f726f636b65744e6574776f726b536e617073686f7473000000000000000000008152506136ee565b9050600080826001600160a01b03166379feb107856040518263ffffffff1660e01b815260040161237491815260200190565b606060405180830381865afa158015612391573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b59190614545565b919350909150507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116826105175761229485613c43565b60006124147fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a306613c43565b905090565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e67000000000000000000000000000000815250306124648260405160200161057b919061448d565b6001600160a01b0316816001600160a01b0316146124c45760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b6040517f636f6e74726163742e657869737473000000000000000000000000000000000060208201526bffffffffffffffffffffffff193360601b16602f82015261251190604301610644565b6125825760405162461bcd60e51b8152602060048201526024808201527f496e76616c6964206f72206f75746461746564206e6574776f726b20636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6040517f6e6f64652e65786973747300000000000000000000000000000000000000000060208201526bffffffffffffffffffffffff19606086901b16602b82015284906125d290603f01610644565b61261e5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964206e6f6465000000000000000000000000000000000000000060448201526064016105f2565b836126288661229f565b10156126765760405162461bcd60e51b815260206004820152601960248201527f4e6f64652068617320696e73756666696369656e742052504c0000000000000060448201526064016105f2565b61267f84613c19565b6126898585613873565b60006126c96040518060400160405280600e81526020017f726f636b6574546f6b656e52504c0000000000000000000000000000000000008152506136ee565b9050600061270b6040518060400160405280600b81526020017f726f636b65745661756c740000000000000000000000000000000000000000008152506136ee565b6040517f01e336670000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03848116602483015260448201899052919250908216906301e3366790606401600060405180830381600087803b15801561277857600080fd5b505af115801561278c573d6000803e3d6000fd5b50506040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018990526001600160a01b03851692506342966c689150602401600060405180830381600087803b1580156127eb57600080fd5b505af11580156127ff573d6000803e3d6000fd5b5050604080518981524260208201526001600160a01b038b1693507f7a3b7812b93ab45ed01ea9fc22b37301461966d61ca09bc0859a84ca07298b129250015b60405180910390a250505050505050565b6000806128916040518060400160405280601681526020017f726f636b65744e6574776f726b536e617073686f7473000000000000000000008152506136ee565b6040517f6574682e6d6174636865642e6e6f64652e616d6f756e7400000000000000000060208201526bffffffffffffffffffffffff19606086901b166037820152909150600090604b01604051602081830303815290604052805190602001209050600080836001600160a01b03166379feb107846040518263ffffffff1660e01b815260040161292591815260200190565b606060405180830381865afa158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614545565b92505091508115612998577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1695945050505050565b60006129a384613c43565b905080156129b5579695505050505050565b60006129f56040518060400160405280601581526020017f726f636b65744d696e69706f6f6c4d616e6167657200000000000000000000008152506136ee565b6040517f1844ec010000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015291925090821690631844ec0190602401602060405180830381865afa158015612a58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7c91906143f3565b612a8e9067de0b6b3a7640000061443b565b98975050505050505050565b6040517f72706c2e7374616b65642e6e6f64652e74696d6500000000000000000000000060208201526bffffffffffffffffffffffff19606083901b1660348201526000906120cb906048015b60405160208183030381529060405280519060200120613c43565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e6700000000000000000000000000000081525030612b4d8260405160200161057b919061448d565b6001600160a01b0316816001600160a01b031614612bad5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b6040517f636f6e74726163742e657869737473000000000000000000000000000000000060208201526bffffffffffffffffffffffff193360601b16602f820152612bfa90604301610644565b612c6b5760405162461bcd60e51b8152602060048201526024808201527f496e76616c6964206f72206f75746461746564206e6574776f726b20636f6e7460448201527f726163740000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6040517f72706c2e6c6f636b696e672e616c6c6f7765640000000000000000000000000060208201526bffffffffffffffffffffffff19606086901b166033820152612cb990604701610644565b612d055760405162461bcd60e51b815260206004820152601f60248201527f4e6f6465206973206e6f7420616c6c6f77656420746f206c6f636b2052504c0060448201526064016105f2565b6000612d108561229f565b6040517f72706c2e6c6f636b65642e6e6f64652e616d6f756e740000000000000000000060208201526bffffffffffffffffffffffff19606088901b166036820152909150600090604a016040516020818303038152906040528051906020012090506000612d7e82613c43565b905085612d8b828561451f565b1015612dd95760405162461bcd60e51b815260206004820152601560248201527f4e6f7420656e6f756768207374616b65642052504c000000000000000000000060448201526064016105f2565b612de782611a058884614532565b604080518781524260208201526001600160a01b038916917fce4a5a05852c75132c79a7a41af76ced563f8391e69eea41a0b38214c4e847cf910161283f565b6040518060400160405280601181526020017f726f636b65744e6f64655374616b696e6700000000000000000000000000000081525030612e728260405160200161057b919061448d565b6001600160a01b0316816001600160a01b031614612ed25760405162461bcd60e51b815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064016105f2565b6040517f6e6f64652e65786973747300000000000000000000000000000000000000000060208201526bffffffffffffffffffffffff19606086901b16602b8201528490612f2290603f01610644565b612f6e5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964206e6f6465000000000000000000000000000000000000000060448201526064016105f2565b6040517f636f6e74726163742e616464726573730000000000000000000000000000000060208201527f726f636b65744d65726b6c654469737472696275746f724d61696e6e657400006030820152612fc990604e0161057b565b6001600160a01b0316336001600160a01b0316146132a95760006130216040518060400160405280601181526020017f726f636b65744e6f64654d616e616765720000000000000000000000000000008152506136ee565b6040517fe667d8280000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015291925060009183169063e667d82890602401602060405180830381865afa158015613086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130aa91906144e5565b1561314a576040517fb71f0c7c0000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301526000919084169063b71f0c7c90602401602060405180830381865afa158015613112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131369190614502565b6001600160a01b0316331491506131fd9050565b600080546040517f5b49ff620000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015261010090920490911690635b49ff6290602401602060405180830381865afa1580156131b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d89190614502565b9050336001600160a01b03891614806131f95750336001600160a01b038216145b9150505b806132a6576040517f6e6f64652e7374616b652e666f722e616c6c6f7765640000000000000000000060208201526bffffffffffffffffffffffff19606089811b8216603684015233901b16604a82015261325a90605e01610644565b6132a65760405162461bcd60e51b815260206004820152601860248201527f4e6f7420616c6c6f77656420746f207374616b6520666f72000000000000000060448201526064016105f2565b50505b6132b38585613d23565b5050505050565b6000806132fb6040518060400160405280601581526020017f726f636b65744d696e69706f6f6c4d616e6167657200000000000000000000008152506136ee565b6040517f1844ec010000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152919250600091831690631844ec0190602401602060405180830381865afa158015613360573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338491906143f3565b9050600061339185612850565b9050801561343c5760006133bc604051806060016040528060218152602001614623602191396136ee565b90506000816001600160a01b03166308e50d386040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342291906143f3565b90506000613430828661443b565b9050612a8e848261451f565b611f7b8267de0b6b3a7640000061443b565b60008061348f6040518060400160405280601381526020017f726f636b65744e6574776f726b507269636573000000000000000000000000008152506136ee565b905060006134d16040518060400160405280601d81526020017f726f636b657444414f50726f746f636f6c53657474696e67734e6f64650000008152506136ee565b905060006134de8561229f565b905060006134eb86612850565b905060006134f8876132ba565b90506000856001600160a01b031663724d4a096040518163ffffffff1660e01b8152600401602060405180830381865afa15801561353a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061355e91906143f3565b90506000856001600160a01b0316631e72ba866040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c491906143f3565b90506000826135d3838661443b565b6135dd9190614452565b9050808611156135f4579998505050505050505050565b6000876001600160a01b0316636fdbe57b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613634573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365891906143f3565b9050600084613667838961443b565b6136719190614452565b90508088101561368d575060009b9a5050505050505050505050565b50959a9950505050505050505050565b6040517f72706c2e6c6f636b65642e6e6f64652e616d6f756e740000000000000000000060208201526bffffffffffffffffffffffff19606083901b1660368201526000906120cb90604a01612ae7565b6000806137058360405160200161057b919061448d565b90506001600160a01b0381166120cb5760405162461bcd60e51b815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e64000000000000000000000000000060448201526064016105f2565b600080546040517f21f8a721000000000000000000000000000000000000000000000000000000008152600481018490526101009091046001600160a01b0316906321f8a72190602401602060405180830381865afa1580156137c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb9190614502565b600080546040517f7ae1cfca000000000000000000000000000000000000000000000000000000008152600481018490526101009091046001600160a01b031690637ae1cfca90602401602060405180830381865afa15801561384f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb91906144e5565b60006138b36040518060400160405280601681526020017f726f636b65744e6574776f726b536e617073686f7473000000000000000000008152506136ee565b6040517f72706c2e7374616b65642e6e6f64652e616d6f756e740000000000000000000060208201526bffffffffffffffffffffffff19606086901b166036820152909150600090604a01604051602081830303815290604052805190602001209050600080836001600160a01b03166379feb107846040518263ffffffff1660e01b815260040161394791815260200190565b606060405180830381865afa158015613964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139889190614545565b92505091508161399e5761399b83613c43565b90505b6001600160a01b038416635ba59649846139b888856145b1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166024820152604401600060405180830381600087803b158015613a2c57600080fd5b505af1158015613a40573d6000803e3d6000fd5b50505050505050505050565b6000613a8c6040518060400160405280601681526020017f726f636b65744e6574776f726b536e617073686f7473000000000000000000008152506136ee565b6040517f72706c2e7374616b65642e6e6f64652e616d6f756e740000000000000000000060208201526bffffffffffffffffffffffff19606086901b166036820152909150600090604a01604051602081830303815290604052805190602001209050600080836001600160a01b03166379feb107846040518263ffffffff1660e01b8152600401613b2091815260200190565b606060405180830381865afa158015613b3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b619190614545565b925050915081613b7757613b7483613c43565b90505b6001600160a01b038416635ba59649846139b888856145ed565b6000546040517fabfdcced0000000000000000000000000000000000000000000000000000000081526004810184905282151560248201526101009091046001600160a01b03169063abfdcced906044015b600060405180830381600087803b158015613bfd57600080fd5b505af1158015613c11573d6000803e3d6000fd5b505050505050565b611ddc7fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a30682614170565b600080546040517fbd02d0f5000000000000000000000000000000000000000000000000000000008152600481018490526101009091046001600160a01b03169063bd02d0f590602401602060405180830381865afa158015613caa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb91906143f3565b6000546040517fe2a4853a00000000000000000000000000000000000000000000000000000000815260048101849052602481018390526101009091046001600160a01b03169063e2a4853a90604401613be3565b6000613d636040518060400160405280601381526020017f726f636b65744e6574776f726b566f74696e67000000000000000000000000008152506136ee565b6040517fbdbc6d420000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529192509082169063bdbc6d4290602401600060405180830381600087803b158015613dc357600080fd5b505af1158015613dd7573d6000803e3d6000fd5b505050506000613e1b6040518060400160405280600e81526020017f726f636b6574546f6b656e52504c0000000000000000000000000000000000008152506136ee565b90506000613e5d6040518060400160405280600b81526020017f726f636b65745661756c740000000000000000000000000000000000000000008152506136ee565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101869052909150829082906001600160a01b038316906323b872dd906064016020604051808303816000875af1158015613ed0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ef491906144e5565b613f665760405162461bcd60e51b815260206004820152602a60248201527f436f756c64206e6f74207472616e736665722052504c20746f207374616b696e60448201527f6720636f6e74726163740000000000000000000000000000000000000000000060648201526084016105f2565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301526024820188905283169063095ea7b3906044016020604051808303816000875af1158015613fce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ff291906144e5565b6140645760405162461bcd60e51b815260206004820152602360248201527f436f756c64206e6f7420617070726f7665207661756c742052504c206465706f60448201527f736974000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6040517ff444295800000000000000000000000000000000000000000000000000000000815260606004820152601160648201527f726f636b65744e6f64655374616b696e6700000000000000000000000000000060848201526001600160a01b0383811660248301526044820188905282169063f44429589060a401600060405180830381600087803b1580156140fb57600080fd5b505af115801561410f573d6000803e3d6000fd5b5050505061411c866141c5565b6141268787613a4c565b61413087426141ef565b604080518781524260208201526001600160a01b038916917f4e3bcb61bb8e63cb9ed2c46d47eeb6ae847c629e909fbb32b9d17874affb4a89910161283f565b6000546040517febb9d8c900000000000000000000000000000000000000000000000000000000815260048101849052602481018390526101009091046001600160a01b03169063ebb9d8c990604401613be3565b611ddc7fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a30682614254565b6040517f72706c2e7374616b65642e6e6f64652e74696d6500000000000000000000000060208201526bffffffffffffffffffffffff19606084901b16603482015261052c906048016040516020818303038152906040528051906020012082613cce565b6000546040517fadb353dc00000000000000000000000000000000000000000000000000000000815260048101849052602481018390526101009091046001600160a01b03169063adb353dc90604401613be3565b6001600160a01b0381168114611ddc57600080fd5b6000602082840312156142d057600080fd5b8135612104816142a9565b8015158114611ddc57600080fd5b600080604083850312156142fc57600080fd5b8235614307816142a9565b91506020830135614317816142db565b809150509250929050565b60008060006060848603121561433757600080fd5b8335614342816142a9565b92506020840135614352816142a9565b929592945050506040919091013590565b6000806040838503121561437657600080fd5b8235614381816142a9565b946020939093013593505050565b6000806000606084860312156143a457600080fd5b83356143af816142a9565b925060208401356143bf816142a9565b915060408401356143cf816142db565b809150509250925092565b6000602082840312156143ec57600080fd5b5035919050565b60006020828403121561440557600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176120cb576120cb61440c565b600082614488577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f636f6e74726163742e616464726573730000000000000000000000000000000081526000825160005b818110156144d457602081860181015160108684010152016144b7565b506000920160100191825250919050565b6000602082840312156144f757600080fd5b8151612104816142db565b60006020828403121561451457600080fd5b8151612104816142a9565b818103818111156120cb576120cb61440c565b808201808211156120cb576120cb61440c565b60008060006060848603121561455a57600080fd5b8351614565816142db565b602085015190935063ffffffff8116811461457f57600080fd5b60408501519092507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146143cf57600080fd5b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8281168282160390808211156145e6576145e661440c565b5092915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181168382160190808211156145e6576145e661440c56fe726f636b657444414f50726f746f636f6c53657474696e67734d696e69706f6f6ca26469706673582212201d3ffa5fe5954fb80cb77aa8a195a8c6957efcc8474d1c37fcbcb600b8cb831364736f6c63430008120033

Verified Source Code Partial Match

Compiler: v0.8.18+commit.87f61d96 EVM: paris Optimization: Yes (15000 runs)
NodeDetails.sol 61 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

// A struct containing all the information on-chain about a specific node

struct NodeDetails {
    bool exists;
    uint256 registrationTime;
    string timezoneLocation;
    bool feeDistributorInitialised;
    address feeDistributorAddress;
    uint256 rewardNetwork;
    uint256 rplStake;
    uint256 effectiveRPLStake;
    uint256 minimumRPLStake;
    uint256 maximumRPLStake;
    uint256 ethMatched;
    uint256 ethMatchedLimit;
    uint256 minipoolCount;
    uint256 balanceETH;
    uint256 balanceRETH;
    uint256 balanceRPL;
    uint256 balanceOldRPL;
    uint256 depositCreditBalance;
    uint256 distributorBalanceUserETH;
    uint256 distributorBalanceNodeETH;
    address withdrawalAddress;
    address pendingWithdrawalAddress;
    bool smoothingPoolRegistrationState;
    uint256 smoothingPoolRegistrationChanged;
    address nodeAddress;
}
RocketBase.sol 190 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

import "../interface/RocketStorageInterface.sol";

/// @title Base settings / modifiers for each contract in Rocket Pool
/// @author David Rugendyke

abstract contract RocketBase {

    // Calculate using this as the base
    uint256 constant calcBase = 1 ether;

    // Version of the contract
    uint8 public version;

    // The main storage contract where primary persistant storage is maintained
    RocketStorageInterface rocketStorage = RocketStorageInterface(address(0));


    /*** Modifiers **********************************************************/

    /**
    * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract
    */
    modifier onlyLatestNetworkContract() {
        require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract");
        _;
    }

    /**
    * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract
    */
    modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
        require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract");
        _;
    }

    /**
    * @dev Throws if called by any sender that isn't a registered node
    */
    modifier onlyRegisteredNode(address _nodeAddress) {
        require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
        _;
    }

    /**
    * @dev Throws if called by any sender that isn't a trusted node DAO member
    */
    modifier onlyTrustedNode(address _nodeAddress) {
        require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node");
        _;
    }

    /**
    * @dev Throws if called by any sender that isn't a registered minipool
    */
    modifier onlyRegisteredMinipool(address _minipoolAddress) {
        require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool");
        _;
    }
    

    /**
    * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled)
    */
    modifier onlyGuardian() {
        require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian");
        _;
    }




    /*** Methods **********************************************************/

    /// @dev Set the main Rocket Storage address
    constructor(RocketStorageInterface _rocketStorageAddress) {
        // Update the contract address
        rocketStorage = RocketStorageInterface(_rocketStorageAddress);
    }


    /// @dev Get the address of a network contract by name
    function getContractAddress(string memory _contractName) internal view returns (address) {
        // Get the current contract address
        address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
        // Check it
        require(contractAddress != address(0x0), "Contract not found");
        // Return
        return contractAddress;
    }


    /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist)
    function getContractAddressUnsafe(string memory _contractName) internal view returns (address) {
        // Get the current contract address
        address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
        // Return
        return contractAddress;
    }


    /// @dev Get the name of a network contract by address
    function getContractName(address _contractAddress) internal view returns (string memory) {
        // Get the contract name
        string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress)));
        // Check it
        require(bytes(contractName).length > 0, "Contract not found");
        // Return
        return contractName;
    }

    /// @dev Get revert error message from a .call method
    function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
        // If the _res length is less than 68, then the transaction failed silently (without a revert message)
        if (_returnData.length < 68) return "Transaction reverted silently";
        assembly {
            // Slice the sighash.
            _returnData := add(_returnData, 0x04)
        }
        return abi.decode(_returnData, (string)); // All that remains is the revert string
    }



    /*** Rocket Storage Methods ****************************************/

    // Note: Unused helpers have been removed to keep contract sizes down

    /// @dev Storage get methods
    function getAddress(bytes32 _key) internal view returns (address) { return rocketStorage.getAddress(_key); }
    function getUint(bytes32 _key) internal view returns (uint) { return rocketStorage.getUint(_key); }
    function getString(bytes32 _key) internal view returns (string memory) { return rocketStorage.getString(_key); }
    function getBytes(bytes32 _key) internal view returns (bytes memory) { return rocketStorage.getBytes(_key); }
    function getBool(bytes32 _key) internal view returns (bool) { return rocketStorage.getBool(_key); }
    function getInt(bytes32 _key) internal view returns (int) { return rocketStorage.getInt(_key); }
    function getBytes32(bytes32 _key) internal view returns (bytes32) { return rocketStorage.getBytes32(_key); }

    /// @dev Storage set methods
    function setAddress(bytes32 _key, address _value) internal { rocketStorage.setAddress(_key, _value); }
    function setUint(bytes32 _key, uint _value) internal { rocketStorage.setUint(_key, _value); }
    function setString(bytes32 _key, string memory _value) internal { rocketStorage.setString(_key, _value); }
    function setBytes(bytes32 _key, bytes memory _value) internal { rocketStorage.setBytes(_key, _value); }
    function setBool(bytes32 _key, bool _value) internal { rocketStorage.setBool(_key, _value); }
    function setInt(bytes32 _key, int _value) internal { rocketStorage.setInt(_key, _value); }
    function setBytes32(bytes32 _key, bytes32 _value) internal { rocketStorage.setBytes32(_key, _value); }

    /// @dev Storage delete methods
    function deleteAddress(bytes32 _key) internal { rocketStorage.deleteAddress(_key); }
    function deleteUint(bytes32 _key) internal { rocketStorage.deleteUint(_key); }
    function deleteString(bytes32 _key) internal { rocketStorage.deleteString(_key); }
    function deleteBytes(bytes32 _key) internal { rocketStorage.deleteBytes(_key); }
    function deleteBool(bytes32 _key) internal { rocketStorage.deleteBool(_key); }
    function deleteInt(bytes32 _key) internal { rocketStorage.deleteInt(_key); }
    function deleteBytes32(bytes32 _key) internal { rocketStorage.deleteBytes32(_key); }

    /// @dev Storage arithmetic methods
    function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); }
    function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); }
}
MinipoolStatus.sol 41 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

// Represents a minipool's status within the network

enum MinipoolStatus {
    Initialised,    // The minipool has been initialised and is awaiting a deposit of user ETH
    Prelaunch,      // The minipool has enough ETH to begin staking and is awaiting launch by the node operator
    Staking,        // The minipool is currently staking
    Withdrawable,   // NO LONGER USED
    Dissolved       // The minipool has been dissolved and its user deposited ETH has been returned to the deposit pool
}
IERC20.sol 106 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity >0.5.0 <0.9.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}
MinipoolDeposit.sol 41 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

// Represents the type of deposits required by a minipool

enum MinipoolDeposit {
    None,       // Marks an invalid deposit type
    Full,       // The minipool requires 32 ETH from the node operator, 16 ETH of which will be refinanced from user deposits
    Half,       // The minipool required 16 ETH from the node operator to be matched with 16 ETH from user deposits
    Empty,      // The minipool requires 0 ETH from the node operator to be matched with 32 ETH from user deposits (trusted nodes only)
    Variable    // Indicates this minipool is of the new generation that supports a variable deposit amount
}
MinipoolDetails.sol 60 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

import "./MinipoolDeposit.sol";
import "./MinipoolStatus.sol";

// A struct containing all the information on-chain about a specific minipool

struct MinipoolDetails {
    bool exists;
    address minipoolAddress;
    bytes pubkey;
    MinipoolStatus status;
    uint256 statusBlock;
    uint256 statusTime;
    bool finalised;
    MinipoolDeposit depositType;
    uint256 nodeFee;
    uint256 nodeDepositBalance;
    bool nodeDepositAssigned;
    uint256 userDepositBalance;
    bool userDepositAssigned;
    uint256 userDepositAssignedTime;
    bool useLatestDelegate;
    address delegate;
    address previousDelegate;
    address effectiveDelegate;
    uint256 penaltyCount;
    uint256 penaltyRate;
    address nodeAddress;
}
IERC20Burnable.sol 39 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

import "./IERC20.sol";

pragma solidity >0.5.0 <0.9.0;

interface IERC20Burnable is IERC20 {
    function burn(uint256 amount) external;
    function burnFrom(address account, uint256 amount) external;
}
Math.sol 339 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}
RocketVaultInterface.sol 43 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only
import "./util/IERC20Burnable.sol";

interface RocketVaultInterface {
    function balanceOf(string memory _networkContractName) external view returns (uint256);
    function depositEther() external payable;
    function withdrawEther(uint256 _amount) external;
    function depositToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) external;
    function withdrawToken(address _withdrawalAddress, IERC20 _tokenAddress, uint256 _amount) external;
    function balanceOfToken(string memory _networkContractName, IERC20 _tokenAddress) external view returns (uint256);
    function transferToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) external;
    function burnToken(IERC20Burnable _tokenAddress, uint256 _amount) external;
}
RocketNodeStaking.sol 510 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.18;

import "../../interface/util/IERC20.sol";

import "../RocketBase.sol";
import "../../interface/minipool/RocketMinipoolManagerInterface.sol";
import "../../interface/network/RocketNetworkPricesInterface.sol";
import "../../interface/node/RocketNodeStakingInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsRewardsInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
import "../../interface/RocketVaultInterface.sol";
import "../../interface/util/AddressSetStorageInterface.sol";
import "../../interface/network/RocketNetworkSnapshotsInterface.sol";
import "../network/RocketNetworkSnapshots.sol";
import "../../interface/node/RocketNodeManagerInterface.sol";
import "../../interface/network/RocketNetworkVotingInterface.sol";

/// @notice Handles node deposits and minipool creation
contract RocketNodeStaking is RocketBase, RocketNodeStakingInterface {

    // Constants
    bytes32 immutable internal totalKey;

    // Events
    event RPLStaked(address indexed from, uint256 amount, uint256 time);
    event RPLWithdrawn(address indexed to, uint256 amount, uint256 time);
    event RPLSlashed(address indexed node, uint256 amount, uint256 ethValue, uint256 time);
    event StakeRPLForAllowed(address indexed node, address indexed caller, bool allowed, uint256 time);
    event RPLLockingAllowed(address indexed node, bool allowed, uint256 time);
    event RPLLocked(address indexed from, uint256 amount, uint256 time);
    event RPLUnlocked(address indexed from, uint256 amount, uint256 time);
    event RPLTransferred(address indexed from, address indexed to, uint256 amount, uint256 time);
    event RPLBurned(address indexed from, uint256 amount, uint256 time);

    modifier onlyRPLWithdrawalAddressOrNode(address _nodeAddress) {
        // Check that the call is coming from RPL withdrawal address (or node if unset)
        RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
        if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
            address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
            require(msg.sender == rplWithdrawalAddress, "Must be called from RPL withdrawal address");
        } else {
            require(msg.sender == _nodeAddress, "Must be called from node address");
        }
        _;
    }

    constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
        version = 6;

        // Precompute keys
        totalKey = keccak256(abi.encodePacked("rpl.staked.total.amount"));
    }

    /// @notice Returns the total quantity of RPL staked on the network
    function getTotalRPLStake() override external view returns (uint256) {
        return getUint(totalKey);
    }

    /// @dev Increases the total network RPL stake
    /// @param _amount How much to increase by
    function increaseTotalRPLStake(uint256 _amount) private {
        addUint(totalKey, _amount);
    }

    /// @dev Decrease the total network RPL stake
    /// @param _amount How much to decrease by
    function decreaseTotalRPLStake(uint256 _amount) private {
        subUint(totalKey, _amount);
    }

    /// @notice Returns the amount a given node operator has staked
    /// @param _nodeAddress The address of the node operator to query
    function getNodeRPLStake(address _nodeAddress) override public view returns (uint256) {
        bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
        RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
        (bool exists,, uint224 value) = rocketNetworkSnapshots.latest(key);
        uint256 stake = uint256(value);
        if (!exists){
            // Fallback to old value
            stake = getUint(key);
        }
        return stake;
    }

    /// @dev Increases a node operator's RPL stake
    /// @param _amount How much to increase by
    function increaseNodeRPLStake(address _nodeAddress, uint256 _amount) private {
        RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
        bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
        (bool exists,, uint224 value) = rocketNetworkSnapshots.latest(key);
        if (!exists){
            value = uint224(getUint(key));
        }
        rocketNetworkSnapshots.push(key, value + uint224(_amount));
    }

    /// @dev Decrease a node operator's RPL stake
    /// @param _amount How much to decrease by
    function decreaseNodeRPLStake(address _nodeAddress, uint256 _amount) private {
        RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
        bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
        (bool exists,, uint224 value) = rocketNetworkSnapshots.latest(key);
        if (!exists){
            value = uint224(getUint(key));
        }
        rocketNetworkSnapshots.push(key, value - uint224(_amount));
    }

    /// @notice Returns a node's matched ETH amount (amount taken from protocol to stake)
    /// @param _nodeAddress The address of the node operator to query
    function getNodeETHMatched(address _nodeAddress) override public view returns (uint256) {
        RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
        bytes32 key = keccak256(abi.encodePacked("eth.matched.node.amount", _nodeAddress));
        (bool exists, , uint224 value) = rocketNetworkSnapshots.latest(key);
        if (exists) {
            // Value was previously set in a snapshot so return that
            return value;
        } else {
            // Fallback to old method
            uint256 ethMatched = getUint(key);
            if (ethMatched > 0) {
                // Value was previously calculated and stored so return that
                return ethMatched;
            } else {
                // Fallback for backwards compatibility before ETH matched was recorded (all legacy minipools matched 16 ETH from protocol)
                RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
                return rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress) * 16 ether;
            }
        }
    }

    /// @notice Returns a node's provided ETH amount (amount supplied to create minipools)
    /// @param _nodeAddress The address of the node operator to query
    function getNodeETHProvided(address _nodeAddress) override public view returns (uint256) {
        // Get contracts
        RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
        uint256 activeMinipoolCount = rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress);
        // Retrieve stored ETH matched value
        uint256 ethMatched = getNodeETHMatched(_nodeAddress);
        if (ethMatched > 0) {
            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
            uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
            // ETH provided is number of staking minipools * 32 - eth matched
            uint256 totalEthStaked = activeMinipoolCount * launchAmount;
            return totalEthStaked - ethMatched;
        } else {
            // Fallback for legacy minipools is number of staking minipools * 16
            return activeMinipoolCount * 16 ether;
        }
    }

    /// @notice Returns the ratio between capital taken from users and provided by a node operator.
    ///         The value is a 1e18 precision fixed point integer value of (node capital + user capital) / node capital.
    /// @param _nodeAddress The address of the node operator to query
    function getNodeETHCollateralisationRatio(address _nodeAddress) override public view returns (uint256) {
        uint256 ethMatched = getNodeETHMatched(_nodeAddress);
        if (ethMatched == 0) {
            // Node operator only has legacy minipools and all legacy minipools had a 1:1 ratio
            return calcBase * 2;
        } else {
            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
            uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
            RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
            uint256 totalEthStaked = rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress) * launchAmount;
            return (totalEthStaked * calcBase) / (totalEthStaked - ethMatched);
        }
    }

    /// @notice Returns the timestamp at which a node last staked RPL
    function getNodeRPLStakedTime(address _nodeAddress) override public view returns (uint256) {
        return getUint(keccak256(abi.encodePacked("rpl.staked.node.time", _nodeAddress)));
    }

    /// @dev Sets the timestamp at which a node last staked RPL
    /// @param _nodeAddress The address of the node operator to set the value for
    /// @param _time The timestamp to set
    function setNodeRPLStakedTime(address _nodeAddress, uint256 _time) private {
        setUint(keccak256(abi.encodePacked("rpl.staked.node.time", _nodeAddress)), _time);
    }

    /// @notice Calculate and return a node's effective RPL stake amount
    /// @param _nodeAddress The address of the node operator to calculate for
    function getNodeEffectiveRPLStake(address _nodeAddress) override public view returns (uint256) {
        // Load contracts
        RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
        RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
        // Get node's current RPL stake
        uint256 rplStake = getNodeRPLStake(_nodeAddress);
        // Retrieve variables for calculations
        uint256 matchedETH = getNodeETHMatched(_nodeAddress);
        uint256 providedETH = getNodeETHProvided(_nodeAddress);
        uint256 rplPrice = rocketNetworkPrices.getRPLPrice();
        // RPL stake cannot exceed maximum
        uint256 maximumStakePercent = rocketDAOProtocolSettingsNode.getMaximumPerMinipoolStake();
        uint256 maximumStake = providedETH * maximumStakePercent / rplPrice;
        if (rplStake > maximumStake) {
            return maximumStake;
        }
        // If RPL stake is lower than minimum, node has no effective stake
        uint256 minimumStakePercent = rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake();
        uint256 minimumStake = matchedETH * minimumStakePercent / rplPrice;
        if (rplStake < minimumStake) {
            return 0;
        }
        // Otherwise, return the actual stake
        return rplStake;
    }

    /// @notice Calculate and return a node's minimum RPL stake to collateralize their minipools
    /// @param _nodeAddress The address of the node operator to calculate for
    function getNodeMinimumRPLStake(address _nodeAddress) override external view returns (uint256) {
        // Load contracts
        RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
        RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
        // Retrieve variables
        uint256 minimumStakePercent = rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake();
        uint256 matchedETH = getNodeETHMatched(_nodeAddress);
        return matchedETH * minimumStakePercent / rocketNetworkPrices.getRPLPrice();
    }

    /// @notice Calculate and return a node's maximum RPL stake to fully collateralise their minipools
    /// @param _nodeAddress The address of the node operator to calculate for
    function getNodeMaximumRPLStake(address _nodeAddress) override public view returns (uint256) {
        // Load contracts
        RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
        RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
        // Retrieve variables
        uint256 maximumStakePercent = rocketDAOProtocolSettingsNode.getMaximumPerMinipoolStake();
        uint256 providedETH = getNodeETHProvided(_nodeAddress);
        return providedETH * maximumStakePercent / rocketNetworkPrices.getRPLPrice();
    }

    /// @notice Calculate and return a node's limit of how much user ETH they can use based on RPL stake
    /// @param _nodeAddress The address of the node operator to calculate for
    function getNodeETHMatchedLimit(address _nodeAddress) override external view returns (uint256) {
        // Load contracts
        RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
        // Retrieve minimum stake parameter
        uint256 minimumStakePercent = rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake();
        // When minimum stake is zero, allow unlimited amount of matched ETH
        if (minimumStakePercent == 0) {
            return type(uint256).max;
        }
        // Calculate and return limit
        RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
        return getNodeRPLStake(_nodeAddress) *rocketNetworkPrices.getRPLPrice() / minimumStakePercent;
    }

    /// @notice Returns whether this node allows RPL locking or not
    /// @param _nodeAddress The address of the node operator to query for
    function getRPLLockingAllowed(address _nodeAddress) external view returns (bool) {
        return getBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress)));
    }

    /// @notice Accept an RPL stake from the node operator's own address
    ///         Requires the node's RPL withdrawal address to be unset
    /// @param _amount The amount of RPL to stake
    function stakeRPL(uint256 _amount) override external {
        stakeRPLFor(msg.sender, _amount);
    }

    /// @notice Accept an RPL stake from any address for a specified node
    ///         Requires caller to have approved this contract to spend RPL
    ///         Requires caller to be on the node operator's allow list (see `setStakeForAllowed`)
    /// @param _nodeAddress The address of the node operator to stake on behalf of
    /// @param _amount The amount of RPL to stake
    function stakeRPLFor(address _nodeAddress, uint256 _amount) override public onlyLatestContract("rocketNodeStaking", address(this)) onlyRegisteredNode(_nodeAddress) {
        // Must be node's RPL withdrawal address if set or the node's address or an allow listed address or rocketMerkleDistributorMainnet
        if (msg.sender != getAddress(keccak256(abi.encodePacked("contract.address", "rocketMerkleDistributorMainnet")))) {
            RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
            bool fromNode = false;
            if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
                address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
                fromNode = msg.sender == rplWithdrawalAddress;
            } else {
                address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
                fromNode = (msg.sender == _nodeAddress) || (msg.sender == withdrawalAddress);
            }
            if (!fromNode) {
                require(getBool(keccak256(abi.encodePacked("node.stake.for.allowed", _nodeAddress, msg.sender))), "Not allowed to stake for");
            }
        }
        _stakeRPL(_nodeAddress, _amount);
    }

    /// @notice Sets the allow state for this node to perform functions that require locking RPL
    /// @param _nodeAddress The address of the node operator to change the state for
    /// @param _allowed Whether locking is allowed or not
    function setRPLLockingAllowed(address _nodeAddress, bool _allowed) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyRPLWithdrawalAddressOrNode(_nodeAddress) {
        // Set the value
        setBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress)), _allowed);
        // Log it
        emit RPLLockingAllowed(_nodeAddress, _allowed, block.timestamp);
    }

    /// @notice Explicitly allow or remove allowance of an address to be able to stake on behalf of a node
    /// @dev The node operator is determined by the address calling this method, it is here for backwards compatibility
    /// @param _caller The address you wish to allow
    /// @param _allowed Whether the address is allowed or denied
    function setStakeRPLForAllowed(address _caller, bool _allowed) override external {
        setStakeRPLForAllowed(msg.sender, _caller, _allowed);
    }

    /// @notice Explicitly allow or remove allowance of an address to be able to stake on behalf of a node
    /// @param _nodeAddress The address of the node operator allowing the caller
    /// @param _caller The address you wish to allow
    /// @param _allowed Whether the address is allowed or denied
    function setStakeRPLForAllowed(address _nodeAddress, address _caller, bool _allowed) override public onlyLatestContract("rocketNodeStaking", address(this)) onlyRPLWithdrawalAddressOrNode(_nodeAddress) {
        // Set the value
        setBool(keccak256(abi.encodePacked("node.stake.for.allowed", _nodeAddress, _caller)), _allowed);
        // Log it
        emit StakeRPLForAllowed(_nodeAddress, _caller, _allowed, block.timestamp);
    }

    /// @dev Internal logic for staking RPL
    /// @param _nodeAddress The address to increase the RPL stake of
    /// @param _amount The amount of RPL to stake
    function _stakeRPL(address _nodeAddress, uint256 _amount) internal {
        // Ensure voting has been initialised for this node
        RocketNetworkVotingInterface rocketNetworkVoting = RocketNetworkVotingInterface(getContractAddress("rocketNetworkVoting"));
        rocketNetworkVoting.initialiseVotingFor(_nodeAddress);
        // Load contracts
        address rplTokenAddress = getContractAddress("rocketTokenRPL");
        address rocketVaultAddress = getContractAddress("rocketVault");
        IERC20 rplToken = IERC20(rplTokenAddress);
        RocketVaultInterface rocketVault = RocketVaultInterface(rocketVaultAddress);
        // Transfer RPL tokens
        require(rplToken.transferFrom(msg.sender, address(this), _amount), "Could not transfer RPL to staking contract");
        // Deposit RPL tokens to vault
        require(rplToken.approve(rocketVaultAddress, _amount), "Could not approve vault RPL deposit");
        rocketVault.depositToken("rocketNodeStaking", rplToken, _amount);
        // Update RPL stake amounts & node RPL staked block
        increaseTotalRPLStake(_amount);
        increaseNodeRPLStake(_nodeAddress, _amount);
        setNodeRPLStakedTime(_nodeAddress, block.timestamp);
        // Emit RPL staked event
        emit RPLStaked(_nodeAddress, _amount, block.timestamp);
    }

    /// @notice Returns the amount of RPL that is locked for a given node
    /// @param _nodeAddress The address of the node operator to query for
    function getNodeRPLLocked(address _nodeAddress) override public view returns (uint256) {
        return getUint(keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress)));
    }

    /// @notice Locks an amount of RPL from being withdrawn even if the node operator is over capitalised
    /// @param _nodeAddress The address of the node operator
    /// @param _amount The amount of RPL to lock
    function lockRPL(address _nodeAddress, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() {
        // Check status
        require(getBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress))), "Node is not allowed to lock RPL");
        // The node must have unlocked stake equaling or greater than the amount
        uint256 rplStake = getNodeRPLStake(_nodeAddress);
        bytes32 lockedStakeKey = keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress));
        uint256 lockedStake = getUint(lockedStakeKey);
        require(rplStake - lockedStake >= _amount, "Not enough staked RPL");
        // Increase locked RPL
        setUint(lockedStakeKey, lockedStake + _amount);
        // Emit event
        emit RPLLocked(_nodeAddress, _amount, block.timestamp);
    }

    /// @notice Unlocks an amount of RPL making it possible to withdraw if the nod is over capitalised
    /// @param _nodeAddress The address of the node operator
    /// @param _amount The amount of RPL to unlock
    function unlockRPL(address _nodeAddress, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() {
        // The node must have locked stake equaling or greater than the amount
        bytes32 lockedStakeKey = keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress));
        uint256 lockedStake = getUint(lockedStakeKey);
        require(_amount <= lockedStake, "Not enough locked RPL");
        // Decrease locked RPL
        setUint(lockedStakeKey, lockedStake - _amount);
        // Emit event
        emit RPLUnlocked(_nodeAddress, _amount, block.timestamp);
    }

    /// @notice Transfers RPL from one node to another
    /// @param _from The node to transfer from
    /// @param _to The node to transfer to
    /// @param _amount The amount of RPL to transfer
    function transferRPL(address _from, address _to, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() onlyRegisteredNode(_from) {
        // Check sender has enough RPL
        require(getNodeRPLStake(_from) >= _amount, "Sender has insufficient RPL");
        // Transfer the stake
        decreaseNodeRPLStake(_from, _amount);
        increaseNodeRPLStake(_to, _amount);
        // Emit event
        emit RPLTransferred(_from, _to, _amount, block.timestamp);
    }

    /// @notice Burns an amount of RPL staked by a given node operator
    /// @param _from The node to burn from
    /// @param _amount The amount of RPL to burn
    function burnRPL(address _from, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() onlyRegisteredNode(_from) {
        // Check sender has enough RPL
        require(getNodeRPLStake(_from) >= _amount, "Node has insufficient RPL");
        // Decrease the stake amount
        decreaseTotalRPLStake(_amount);
        decreaseNodeRPLStake(_from, _amount);
        // Withdraw the RPL to this contract
        IERC20Burnable rplToken = IERC20Burnable(getContractAddress("rocketTokenRPL"));
        RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
        rocketVault.withdrawToken(address(this), rplToken, _amount);
        // Execute the token burn
        rplToken.burn(_amount);
        // Emit event
        emit RPLBurned(_from, _amount, block.timestamp);
    }

    /// @notice Withdraw staked RPL back to the node account or withdraw RPL address
    ///         Can only be called by a node if they have not set their RPL withdrawal address
    /// @param _amount The amount of RPL to withdraw
    function withdrawRPL(uint256 _amount) override external {
        withdrawRPL(msg.sender, _amount);
    }

    /// @notice Withdraw staked RPL back to the node account or withdraw RPL address
    ///         If RPL withdrawal address has been set, must be called from it. Otherwise, must be called from
    ///         node's primary withdrawal address or their node address.
    /// @param _nodeAddress The address of the node withdrawing
    /// @param _amount The amount of RPL to withdraw
    function withdrawRPL(address _nodeAddress, uint256 _amount) override public onlyLatestContract("rocketNodeStaking", address(this)) {
        // Check valid node
        require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
        // Check address is permitted to withdraw
        RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
        address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
        if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
            // If RPL withdrawal address is set, must be called from it
            require(msg.sender == rplWithdrawalAddress, "Invalid caller");
        } else {
            // Otherwise, must be called from node address or withdrawal address
            address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
            require(msg.sender == _nodeAddress || msg.sender == withdrawalAddress, "Invalid caller");
        }
        // Load contracts
        RocketDAOProtocolSettingsRewardsInterface rocketDAOProtocolSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards"));
        RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
        // Check cooldown period (one claim period) has passed since RPL last staked
        require(block.timestamp - getNodeRPLStakedTime(_nodeAddress) >= rocketDAOProtocolSettingsRewards.getRewardsClaimIntervalTime(), "The withdrawal cooldown period has not passed");
        // Get & check node's current RPL stake
        uint256 rplStake = getNodeRPLStake(_nodeAddress);
        uint256 lockedStake = getNodeRPLLocked(_nodeAddress);
        require(rplStake - lockedStake >= _amount, "Withdrawal amount exceeds node's staked RPL balance");
        // Check withdrawal would not under collateralise node
        require(rplStake - _amount >= getNodeMaximumRPLStake(_nodeAddress) + lockedStake, "Node's staked RPL balance after withdrawal is less than required balance");
        // Update RPL stake amounts
        decreaseTotalRPLStake(_amount);
        decreaseNodeRPLStake(_nodeAddress, _amount);
        // Transfer RPL tokens to node's RPL withdrawal address (if unset, defaults to primary withdrawal address)
        rocketVault.withdrawToken(rplWithdrawalAddress, IERC20(getContractAddress("rocketTokenRPL")), _amount);
        // Emit RPL withdrawn event
        emit RPLWithdrawn(_nodeAddress, _amount, block.timestamp);
    }

    /// @notice Slash a node's RPL by an ETH amount
    ///         Only accepts calls from registered minipools
    /// @param _nodeAddress The address to slash RPL from
    /// @param _ethSlashAmount The amount of RPL to slash denominated in ETH value
    function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyRegisteredMinipool(msg.sender) {
        // Load contracts
        RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
        RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
        // Calculate RPL amount to slash
        uint256 rplSlashAmount = calcBase * _ethSlashAmount / rocketNetworkPrices.getRPLPrice();
        // Cap slashed amount to node's RPL stake
        uint256 rplStake = getNodeRPLStake(_nodeAddress);
        if (rplSlashAmount > rplStake) { rplSlashAmount = rplStake; }
        // Transfer slashed amount to auction contract
        if(rplSlashAmount > 0) rocketVault.transferToken("rocketAuctionManager", IERC20(getContractAddress("rocketTokenRPL")), rplSlashAmount);
        // Update RPL stake amounts
        decreaseTotalRPLStake(rplSlashAmount);
        decreaseNodeRPLStake(_nodeAddress, rplSlashAmount);
        // Mark minipool as slashed
        setBool(keccak256(abi.encodePacked("minipool.rpl.slashed", msg.sender)), true);
        // Emit RPL slashed event
        emit RPLSlashed(_nodeAddress, rplSlashAmount, _ethSlashAmount, block.timestamp);
    }

}
RocketStorageInterface.sol 79 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

interface RocketStorageInterface {

    // Deploy status
    function getDeployedStatus() external view returns (bool);

    // Guardian
    function getGuardian() external view returns(address);
    function setGuardian(address _newAddress) external;
    function confirmGuardian() external;

    // Getters
    function getAddress(bytes32 _key) external view returns (address);
    function getUint(bytes32 _key) external view returns (uint);
    function getString(bytes32 _key) external view returns (string memory);
    function getBytes(bytes32 _key) external view returns (bytes memory);
    function getBool(bytes32 _key) external view returns (bool);
    function getInt(bytes32 _key) external view returns (int);
    function getBytes32(bytes32 _key) external view returns (bytes32);

    // Setters
    function setAddress(bytes32 _key, address _value) external;
    function setUint(bytes32 _key, uint _value) external;
    function setString(bytes32 _key, string calldata _value) external;
    function setBytes(bytes32 _key, bytes calldata _value) external;
    function setBool(bytes32 _key, bool _value) external;
    function setInt(bytes32 _key, int _value) external;
    function setBytes32(bytes32 _key, bytes32 _value) external;

    // Deleters
    function deleteAddress(bytes32 _key) external;
    function deleteUint(bytes32 _key) external;
    function deleteString(bytes32 _key) external;
    function deleteBytes(bytes32 _key) external;
    function deleteBool(bytes32 _key) external;
    function deleteInt(bytes32 _key) external;
    function deleteBytes32(bytes32 _key) external;

    // Arithmetic
    function addUint(bytes32 _key, uint256 _amount) external;
    function subUint(bytes32 _key, uint256 _amount) external;

    // Protected storage
    function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
    function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
    function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external;
    function confirmWithdrawalAddress(address _nodeAddress) external;
}
RocketNetworkSnapshots.sol 184 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: MIT
// Copyright (c) 2016-2023 zOS Global Limited and contributors
// Adapted from OpenZeppelin `Checkpoints` contract
pragma solidity 0.8.18;

import "@openzeppelin4/contracts/utils/math/Math.sol";

import "../RocketBase.sol";
import "../../interface/network/RocketNetworkSnapshotsInterface.sol";

/// @notice Accounting for snapshotting of values based on block numbers
contract RocketNetworkSnapshots is RocketBase, RocketNetworkSnapshotsInterface {

    constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
        // Set contract version
        version = 1;

        // Setup for if this contract is being deployed as part of a new instance deployment
        if (!rocketStorage.getDeployedStatus()) {
            _insert(keccak256("network.prices.rpl"), 0.01 ether);
            _insert(keccak256("node.voting.power.stake.maximum"), 1.5 ether);
        }
    }

    function push(bytes32 _key, uint224 _value) onlyLatestContract("rocketNetworkSnapshots", address(this)) onlyLatestNetworkContract external {
        _insert(_key, _value);
    }

    function length(bytes32 _key) public view returns (uint256) {
        return rocketStorage.getUint(keccak256(abi.encodePacked("snapshot.length", _key)));
    }

    function latest(bytes32 _key) external view returns (bool, uint32, uint224) {
        uint256 len = length(_key);
        if (len == 0) {
            return (false, 0, 0);
        }
        Checkpoint224 memory checkpoint = _load(_key, len - 1);
        return (true, checkpoint._block, checkpoint._value);
    }

    function latestBlock(bytes32 _key) external view returns (uint32) {
        uint256 len = length(_key);
        return len == 0 ? 0 : _blockAt(_key, len - 1);
    }

    function latestValue(bytes32 _key) external view returns (uint224) {
        uint256 len = length(_key);
        return len == 0 ? 0 : _valueAt(_key, len - 1);
    }

    function lookup(bytes32 _key, uint32 _block) external view returns (uint224) {
        uint256 len = length(_key);
        uint256 pos = _binaryLookup(_key, _block, 0, len);
        return pos == 0 ? 0 : _valueAt(_key, pos - 1);
    }

    function lookupRecent(bytes32 _key, uint32 _block, uint256 _recency) external view returns (uint224) {
        uint256 len = length(_key);

        uint256 low = 0;
        uint256 high = len;

        if (len > 5 && len > _recency) {
            uint256 mid = len - _recency;
            if (_block < _blockAt(_key, mid)) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        uint256 pos = _binaryLookup(_key, _block, low, high);

        return pos == 0 ? 0 : _valueAt(_key, pos - 1);
    }

    function _insert(bytes32 _key, uint224 _value) private {
        uint32 blockNumber = uint32(block.number);
        uint256 pos = length(_key);

        if (pos > 0) {
            Checkpoint224 memory last = _load(_key, pos - 1);

            // Checkpoint keys must be non-decreasing.
            require (last._block <= blockNumber, "Unordered snapshot insertion");

            // Update or push new checkpoint
            if (last._block == blockNumber) {
                last._value = _value;
                _set(_key, pos - 1, last);
            } else {
                _push(_key, Checkpoint224({_block: blockNumber, _value: _value}));
            }
        } else {
            _push(_key, Checkpoint224({_block: blockNumber, _value: _value}));
        }
    }

    function _binaryLookup(
        bytes32 _key,
        uint32 _block,
        uint256 _low,
        uint256 _high
    ) private view returns (uint256) {
        while (_low < _high) {
            uint256 mid = Math.average(_low, _high);
            if (_blockAt(_key, mid) > _block) {
                _high = mid;
            } else {
                _low = mid + 1;
            }
        }
        return _high;
    }

    function _load(bytes32 _key, uint256 _pos) private view returns (Checkpoint224 memory) {
        bytes32 key = bytes32(uint256(_key) + _pos);
        bytes32 raw = rocketStorage.getBytes32(key);
        Checkpoint224 memory result;
        result._block = uint32(uint256(raw) >> 224);
        result._value = uint224(uint256(raw));
        return result;
    }

    function _blockAt(bytes32 _key, uint256 _pos) private view returns (uint32) {
        bytes32 key = bytes32(uint256(_key) + _pos);
        bytes32 raw = rocketStorage.getBytes32(key);
        return uint32(uint256(raw) >> 224);
    }

    function _valueAt(bytes32 _key, uint256 _pos) private view returns (uint224) {
        bytes32 key = bytes32(uint256(_key) + _pos);
        bytes32 raw = rocketStorage.getBytes32(key);
        return uint224(uint256(raw));
    }

    function _push(bytes32 _key, Checkpoint224 memory _item) private {
        bytes32 lengthKey = keccak256(abi.encodePacked("snapshot.length", _key));
        uint256 snapshotLength = rocketStorage.getUint(lengthKey);
        bytes32 key = bytes32(uint256(_key) + snapshotLength);
        rocketStorage.setUint(lengthKey, snapshotLength + 1);
        rocketStorage.setBytes32(key, _encode(_item));
    }

    function _set(bytes32 _key, uint256 _pos, Checkpoint224 memory _item) private {
        bytes32 key = bytes32(uint256(_key) + _pos);
        rocketStorage.setBytes32(key, _encode(_item));
    }

    function _encode(Checkpoint224 memory _item) private pure returns (bytes32) {
        return bytes32(
            uint256(_item._block) << 224 | uint256(_item._value)
        );
    }
}
RocketNodeManagerInterface.sol 70 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;

import "../../types/NodeDetails.sol";

interface RocketNodeManagerInterface {

    // Structs
    struct TimezoneCount {
        string timezone;
        uint256 count;
    }

    function getNodeCount() external view returns (uint256);
    function getNodeCountPerTimezone(uint256 offset, uint256 limit) external view returns (TimezoneCount[] memory);
    function getNodeAt(uint256 _index) external view returns (address);
    function getNodeExists(address _nodeAddress) external view returns (bool);
    function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
    function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
    function getNodeRPLWithdrawalAddress(address _nodeAddress) external view returns (address);
    function getNodeRPLWithdrawalAddressIsSet(address _nodeAddress) external view returns (bool);
    function unsetRPLWithdrawalAddress(address _nodeAddress) external;
    function setRPLWithdrawalAddress(address _nodeAddress, address _newRPLWithdrawalAddress, bool _confirm) external;
    function confirmRPLWithdrawalAddress(address _nodeAddress) external;
    function getNodePendingRPLWithdrawalAddress(address _nodeAddress) external view returns (address);
    function getNodeTimezoneLocation(address _nodeAddress) external view returns (string memory);
    function registerNode(string calldata _timezoneLocation) external;
    function getNodeRegistrationTime(address _nodeAddress) external view returns (uint256);
    function setTimezoneLocation(string calldata _timezoneLocation) external;
    function setRewardNetwork(address _nodeAddress, uint256 network) external;
    function getRewardNetwork(address _nodeAddress) external view returns (uint256);
    function getFeeDistributorInitialised(address _nodeAddress) external view returns (bool);
    function initialiseFeeDistributor() external;
    function getAverageNodeFee(address _nodeAddress) external view returns (uint256);
    function setSmoothingPoolRegistrationState(bool _state) external;
    function getSmoothingPoolRegistrationState(address _nodeAddress) external returns (bool);
    function getSmoothingPoolRegistrationChanged(address _nodeAddress) external returns (uint256);
    function getSmoothingPoolRegisteredNodeCount(uint256 _offset, uint256 _limit) external view returns (uint256);
    function getNodeDetails(address _nodeAddress) external view returns (NodeDetails memory);
    function getNodeAddresses(uint256 _offset, uint256 _limit) external view returns (address[] memory);
}
RocketNodeStakingInterface.sol 57 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;

interface RocketNodeStakingInterface {
    function getTotalRPLStake() external view returns (uint256);
    function getNodeRPLStake(address _nodeAddress) external view returns (uint256);
    function getNodeETHMatched(address _nodeAddress) external view returns (uint256);
    function getNodeETHProvided(address _nodeAddress) external view returns (uint256);
    function getNodeETHCollateralisationRatio(address _nodeAddress) external view returns (uint256);
    function getNodeRPLStakedTime(address _nodeAddress) external view returns (uint256);
    function getNodeEffectiveRPLStake(address _nodeAddress) external view returns (uint256);
    function getNodeMinimumRPLStake(address _nodeAddress) external view returns (uint256);
    function getNodeMaximumRPLStake(address _nodeAddress) external view returns (uint256);
    function getNodeETHMatchedLimit(address _nodeAddress) external view returns (uint256);
    function getRPLLockingAllowed(address _nodeAddress) external view returns (bool);
    function stakeRPL(uint256 _amount) external;
    function stakeRPLFor(address _nodeAddress, uint256 _amount) external;
    function setRPLLockingAllowed(address _nodeAddress, bool _allowed) external;
    function setStakeRPLForAllowed(address _caller, bool _allowed) external;
    function setStakeRPLForAllowed(address _nodeAddress, address _caller, bool _allowed) external;
    function getNodeRPLLocked(address _nodeAddress) external view returns (uint256);
    function lockRPL(address _nodeAddress, uint256 _amount) external;
    function unlockRPL(address _nodeAddress, uint256 _amount) external;
    function transferRPL(address _from, address _to, uint256 _amount) external;
    function burnRPL(address _from, uint256 _amount) external;
    function withdrawRPL(uint256 _amount) external;
    function withdrawRPL(address _nodeAddress, uint256 _amount) external;
    function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) external;
}
AddressSetStorageInterface.sol 39 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

interface AddressSetStorageInterface {
    function getCount(bytes32 _key) external view returns (uint);
    function getItem(bytes32 _key, uint _index) external view returns (address);
    function getIndexOf(bytes32 _key, address _value) external view returns (int);
    function addItem(bytes32 _key, address _value) external;
    function removeItem(bytes32 _key, address _value) external;
}
RocketMinipoolInterface.sol 80 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolStatus.sol";
import "../RocketStorageInterface.sol";

interface RocketMinipoolInterface {
    function version() external view returns (uint8);
    function initialise(address _nodeAddress) external;
    function getStatus() external view returns (MinipoolStatus);
    function getFinalised() external view returns (bool);
    function getStatusBlock() external view returns (uint256);
    function getStatusTime() external view returns (uint256);
    function getScrubVoted(address _member) external view returns (bool);
    function getDepositType() external view returns (MinipoolDeposit);
    function getNodeAddress() external view returns (address);
    function getNodeFee() external view returns (uint256);
    function getNodeDepositBalance() external view returns (uint256);
    function getNodeRefundBalance() external view returns (uint256);
    function getNodeDepositAssigned() external view returns (bool);
    function getPreLaunchValue() external view returns (uint256);
    function getNodeTopUpValue() external view returns (uint256);
    function getVacant() external view returns (bool);
    function getPreMigrationBalance() external view returns (uint256);
    function getUserDistributed() external view returns (bool);
    function getUserDepositBalance() external view returns (uint256);
    function getUserDepositAssigned() external view returns (bool);
    function getUserDepositAssignedTime() external view returns (uint256);
    function getTotalScrubVotes() external view returns (uint256);
    function calculateNodeShare(uint256 _balance) external view returns (uint256);
    function calculateUserShare(uint256 _balance) external view returns (uint256);
    function preDeposit(uint256 _bondingValue, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) external payable;
    function deposit() external payable;
    function userDeposit() external payable;
    function distributeBalance(bool _rewardsOnly) external;
    function beginUserDistribute() external;
    function userDistributeAllowed() external view returns (bool);
    function refund() external;
    function slash() external;
    function finalise() external;
    function canStake() external view returns (bool);
    function canPromote() external view returns (bool);
    function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) external;
    function prepareVacancy(uint256 _bondAmount, uint256 _currentBalance) external;
    function promote() external;
    function dissolve() external;
    function close() external;
    function voteScrub() external;
    function reduceBondAmount() external;
}
RocketNetworkPricesInterface.sol 37 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only
interface RocketNetworkPricesInterface {
    function getPricesBlock() external view returns (uint256);
    function getRPLPrice() external view returns (uint256);
    function submitPrices(uint256 _block, uint256 _slotTimestamp, uint256 _rplPrice) external;
    function executeUpdatePrices(uint256 _block, uint256 _slotTimestamp, uint256 _rplPrice) external;
}
RocketNetworkVotingInterface.sol 42 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;

interface RocketNetworkVotingInterface {
    function initialiseVotingFor(address _nodeAddress) external;
    function initialiseVoting() external;
    function initialiseVotingWithDelegate(address _delegate) external;
    function getVotingInitialised(address _nodeAddress) external view returns (bool);
    function getNodeCount(uint32 _block) external view returns (uint256);
    function getVotingPower(address _nodeAddress, uint32 _block) external view returns (uint256);
    function setDelegate(address _newDelegate) external;
    function getDelegate(address _nodeAddress, uint32 _block) external view returns (address);
    function getCurrentDelegate(address _nodeAddress) external view returns (address);
}
RocketMinipoolManagerInterface.sol 73 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolDetails.sol";
import "./RocketMinipoolInterface.sol";

interface RocketMinipoolManagerInterface {
    function getMinipoolCount() external view returns (uint256);
    function getStakingMinipoolCount() external view returns (uint256);
    function getFinalisedMinipoolCount() external view returns (uint256);
    function getActiveMinipoolCount() external view returns (uint256);
    function getMinipoolRPLSlashed(address _minipoolAddress) external view returns (bool);
    function getMinipoolCountPerStatus(uint256 offset, uint256 limit) external view returns (uint256, uint256, uint256, uint256, uint256);
    function getPrelaunchMinipools(uint256 offset, uint256 limit) external view returns (address[] memory);
    function getMinipoolAt(uint256 _index) external view returns (address);
    function getNodeMinipoolCount(address _nodeAddress) external view returns (uint256);
    function getNodeActiveMinipoolCount(address _nodeAddress) external view returns (uint256);
    function getNodeFinalisedMinipoolCount(address _nodeAddress) external view returns (uint256);
    function getNodeStakingMinipoolCount(address _nodeAddress) external view returns (uint256);
    function getNodeStakingMinipoolCountBySize(address _nodeAddress, uint256 _depositSize) external view returns (uint256);
    function getNodeMinipoolAt(address _nodeAddress, uint256 _index) external view returns (address);
    function getNodeValidatingMinipoolCount(address _nodeAddress) external view returns (uint256);
    function getNodeValidatingMinipoolAt(address _nodeAddress, uint256 _index) external view returns (address);
    function getMinipoolByPubkey(bytes calldata _pubkey) external view returns (address);
    function getMinipoolExists(address _minipoolAddress) external view returns (bool);
    function getMinipoolDestroyed(address _minipoolAddress) external view returns (bool);
    function getMinipoolPubkey(address _minipoolAddress) external view returns (bytes memory);
    function updateNodeStakingMinipoolCount(uint256 _previousBond, uint256 _newBond, uint256 _previousFee, uint256 _newFee) external;
    function getMinipoolWithdrawalCredentials(address _minipoolAddress) external pure returns (bytes memory);
    function createMinipool(address _nodeAddress, uint256 _salt) external returns (RocketMinipoolInterface);
    function createVacantMinipool(address _nodeAddress, uint256 _salt, bytes calldata _validatorPubkey, uint256 _bondAmount, uint256 _currentBalance) external returns (RocketMinipoolInterface);
    function removeVacantMinipool() external;
    function getVacantMinipoolCount() external view returns (uint256);
    function getVacantMinipoolAt(uint256 _index) external view returns (address);
    function destroyMinipool() external;
    function incrementNodeStakingMinipoolCount(address _nodeAddress) external;
    function decrementNodeStakingMinipoolCount(address _nodeAddress) external;
    function tryDistribute(address _nodeAddress) external;
    function incrementNodeFinalisedMinipoolCount(address _nodeAddress) external;
    function setMinipoolPubkey(bytes calldata _pubkey) external;
    function getMinipoolDepositType(address _minipoolAddress) external view returns (MinipoolDeposit);
}
RocketNetworkSnapshotsInterface.sol 46 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;

struct Checkpoint224 {
    uint32 _block;
    uint224 _value;
}

/// @notice Accounting for snapshotting of values based on block numbers
interface RocketNetworkSnapshotsInterface {
    function push(bytes32 _key, uint224 _value) external;
    function length(bytes32 _key) external view returns (uint256);
    function latest(bytes32 _key) external view returns (bool, uint32, uint224);
    function latestBlock(bytes32 _key) external view returns (uint32);
    function latestValue(bytes32 _key) external view returns (uint224);
    function lookup(bytes32 _key, uint32 _block) external view returns (uint224);
    function lookupRecent(bytes32 _key, uint32 _block, uint256 _recency) external view returns (uint224);
}
RocketDAOProtocolSettingsNodeInterface.sol 41 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

interface RocketDAOProtocolSettingsNodeInterface {
    function getRegistrationEnabled() external view returns (bool);
    function getSmoothingPoolRegistrationEnabled() external view returns (bool);
    function getDepositEnabled() external view returns (bool);
    function getVacantMinipoolsEnabled() external view returns (bool);
    function getMinimumPerMinipoolStake() external view returns (uint256);
    function getMaximumPerMinipoolStake() external view returns (uint256);
    function getMaximumStakeForVotingPower() external view returns (uint256);
}
RocketDAOProtocolSettingsRewardsInterface.sol 42 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;

interface RocketDAOProtocolSettingsRewardsInterface {
    function setSettingRewardsClaimers(uint256 _trustedNodePercent, uint256 _protocolPercent, uint256 _nodePercent) external;
    function getRewardsClaimerPerc(string memory _contractName) external view returns (uint256);
    function getRewardsClaimersPerc() external view returns (uint256 _trustedNodePercent, uint256 _protocolPercent, uint256 _nodePercent);
    function getRewardsClaimersTrustedNodePerc() external view returns (uint256);
    function getRewardsClaimersProtocolPerc() external view returns (uint256);
    function getRewardsClaimersNodePerc() external view returns (uint256);
    function getRewardsClaimersTimeUpdated() external view returns (uint256);
    function getRewardsClaimIntervalPeriods() external view returns (uint256);
    function getRewardsClaimIntervalTime() external view returns (uint256);
}
RocketDAOProtocolSettingsMinipoolInterface.sol 50 lines
/**
   *       .
   *      / \
   *     |.'.|
   *     |'.'|
   *   ,'|   |'.
   *  |,-'-|-'-.|
   *   __|_| |         _        _      _____           _
   *  | ___ \|        | |      | |    | ___ \         | |
   *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
   *  |    // _ \ / __| |/ / _ \ __|  |  __/ _ \ / _ \| |
   *  | |\ \ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
   *  \_| \_\___/ \___|_|\_\___|\__|  \_|  \___/ \___/|_|
   * +---------------------------------------------------+
   * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
   * +---------------------------------------------------+
   *
   *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
   *  be community-owned, decentralised, permissionless, & trustless.
   *
   *  For more information about Rocket Pool, visit https://rocketpool.net
   *
   *  Authored by the Rocket Pool Core Team
   *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
   *  A special thanks to the Rocket Pool community for all their contributions.
   *
   */

pragma solidity >0.5.0 <0.9.0;

// SPDX-License-Identifier: GPL-3.0-only

import "../../../../types/MinipoolDeposit.sol";

interface RocketDAOProtocolSettingsMinipoolInterface {
    function getLaunchBalance() external view returns (uint256);
    function getPreLaunchValue() external pure returns (uint256);
    function getDepositUserAmount(MinipoolDeposit _depositType) external view returns (uint256);
    function getFullDepositUserAmount() external view returns (uint256);
    function getHalfDepositUserAmount() external view returns (uint256);
    function getVariableDepositAmount() external view returns (uint256);
    function getSubmitWithdrawableEnabled() external view returns (bool);
    function getBondReductionEnabled() external view returns (bool);
    function getLaunchTimeout() external view returns (uint256);
    function getMaximumCount() external view returns (uint256);
    function isWithinUserDistributeWindow(uint256 _time) external view returns (bool);
    function hasUserDistributeWindowPassed(uint256 _time) external view returns (bool);
    function getUserDistributeWindowStart() external view returns (uint256);
    function getUserDistributeWindowLength() external view returns (uint256);
}

Read Contract

getNodeETHCollateralisationRatio 0x97be2143 → uint256
getNodeETHMatched 0xa493e6a2 → uint256
getNodeETHMatchedLimit 0x48aeedf5 → uint256
getNodeETHProvided 0xe5e82b7c → uint256
getNodeEffectiveRPLStake 0xf0d19b89 → uint256
getNodeMaximumRPLStake 0x4e58ff6e → uint256
getNodeMinimumRPLStake 0x03fa87b4 → uint256
getNodeRPLLocked 0xf3512f84 → uint256
getNodeRPLStake 0x9961cee4 → uint256
getNodeRPLStakedTime 0xc0d05dd8 → uint256
getRPLLockingAllowed 0x641a24d2 → bool
getTotalRPLStake 0x9a206c8e → uint256
version 0x54fd4d50 → uint8

Write Contract 12 functions

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

burnRPL 0xa39e96c3
address _from
uint256 _amount
lockRPL 0xc601bf78
address _nodeAddress
uint256 _amount
setRPLLockingAllowed 0x194c63d8
address _nodeAddress
bool _allowed
setStakeRPLForAllowed 0x088903a4
address _caller
bool _allowed
setStakeRPLForAllowed 0x3d65c1fa
address _nodeAddress
address _caller
bool _allowed
slashRPL 0x245395a6
address _nodeAddress
uint256 _ethSlashAmount
stakeRPL 0x3e200d4b
uint256 _amount
stakeRPLFor 0xcb1c8321
address _nodeAddress
uint256 _amount
transferRPL 0x10b63749
address _from
address _to
uint256 _amount
unlockRPL 0x2c177a53
address _nodeAddress
uint256 _amount
withdrawRPL 0x21f3da44
address _nodeAddress
uint256 _amount
withdrawRPL 0x6b088d5c
uint256 _amount

Recent Transactions

No transactions found for this address