Address Contract Partially Verified
Address
0x5cE71E603B138F7e65029Cc1918C0566ed0dBD4B
Balance
0 ETH
Nonce
1
Code Size
8857 bytes
Creator
0x27e80dB1...603D at tx 0x5db60200...8f32e5
Indexed Transactions
0
Contract Bytecode
8857 bytes
0x60806040526004361061007f5760003560e01c8063dacfffa81161004e578063dacfffa81461010e578063e44ba18f1461012e578063f012062c1461014e578063fa8779c81461016357600080fd5b806354fd4d501461008b5780635e38c572146100bc578063c095415d146100dc578063d2ef0795146100de57600080fd5b3661008657005b600080fd5b34801561009757600080fd5b506000546100a59060ff1681565b60405160ff90911681526020015b60405180910390f35b3480156100c857600080fd5b506100dc6100d7366004611d6b565b610191565b005b3480156100ea57600080fd5b506100fe6100f9366004611e44565b6101af565b60405190151581526020016100b3565b34801561011a57600080fd5b506100dc610129366004611e74565b610268565b34801561013a57600080fd5b506100dc610149366004611f55565b610295565b34801561015a57600080fd5b506100dc61070f565b34801561016f57600080fd5b5061018361017e366004611f87565b6108ff565b6040519081526020016100b3565b6101a48989898989898989896000610268565b505050505050505050565b6000806101be61010085612002565b905060006101ce61010086612016565b6040517f726577617264732e696e74657276616c2e636c61696d6564000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b166038820152604c810184905290915060009061025290606c0160405160208183030381529060405280519060200120610984565b600190921b918216909114925050505b92915050565b61027989898c8a8a8a8a8a8a610a1d565b6102898a8a8a8a8a8a8a88610e0d565b50505050505050505050565b6040518060400160405280601e81526020017f726f636b65744d65726b6c654469737472696275746f724d61696e6e65740000815250306102fb826040516020016102e0919061202a565b60405160208183030381529060405280519060200120611863565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610394576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e74726163740000000060448201526064015b60405180910390fd5b6040518060400160405280601181526020017f726f636b657452657761726473506f6f6c000000000000000000000000000000815250336103df826040516020016102e0919061202a565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610473576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f496e76616c6964206f72206f7574646174656420636f6e747261637400000000604482015260640161038b565b6040517f726577617264732e6d65726b6c652e726f6f74000000000000000000000000006020820152603381018990526000906053016040516020818303038152906040528051906020012090506000801b6104ce826118fb565b146104d857600080fd5b6104e28189611957565b600061050d7f41c30d91bfaf5fa8d610263b0554366f2159a2b6807bf2fdbeb8f2b21a62f17b611863565b90508615610577578073ffffffffffffffffffffffffffffffffffffffff166398ea5fca886040518263ffffffff1660e01b81526004016000604051808303818588803b15801561055d57600080fd5b505af1158015610571573d6000803e3d6000fd5b50505050505b87156102895760006105a87f1b80652f417157fe4774177f7d33c8b600483b9193e3f00d2ab1ace8fa6bdc9c611863565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018c90529192509082169063095ea7b3906044016020604051808303816000875af1158015610621573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106459190612082565b506040517ff444295800000000000000000000000000000000000000000000000000000000815260606004820152601e60648201527f726f636b65744d65726b6c654469737472696275746f724d61696e6e65740000608482015273ffffffffffffffffffffffffffffffffffffffff8281166024830152604482018b905283169063f44429589060a401600060405180830381600087803b1580156106ea57600080fd5b505af11580156106fe573d6000803e3d6000fd5b505050505050505050505050505050565b600061073a7f41c30d91bfaf5fa8d610263b0554366f2159a2b6807bf2fdbeb8f2b21a62f17b611863565b6040517f726577617264732e6574682e62616c616e63650000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16603382015290915060009060470160405160208183030381529060405280519060200120905060006107ba82610984565b90506107c78260006119eb565b6040517f3bed33ce0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff841690633bed33ce90602401600060405180830381600087803b15801561082f57600080fd5b505af1158015610843573d6000803e3d6000fd5b50506040516000925033915083908381818185875af1925050503d8060008114610889576040519150601f19603f3d011682016040523d82523d6000602084013e61088e565b606091505b50509050806108f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5472616e73666572206661696c65640000000000000000000000000000000000604482015260640161038b565b50505050565b6040517f726577617264732e6574682e62616c616e63650000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b166033820152600090819060470160405160208183030381529060405280519060200120905061097d81610984565b9392505050565b600080546040517fbd02d0f50000000000000000000000000000000000000000000000000000000081526004810184905261010090910473ffffffffffffffffffffffffffffffffffffffff169063bd02d0f5906024015b602060405180830381865afa1580156109f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061026291906120a4565b60006101008a8a6000818110610a3557610a356120bd565b90506020020135610a469190612002565b6040517f726577617264732e696e74657276616c2e636c61696d6564000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608b901b166038820152604c8101829052909150600090606c016040516020818303038152906040528051906020012090506000610ace82610984565b905060005b8b811015610df45760008a8a83818110610aef57610aef6120bd565b905060200201351180610b1a57506000888883818110610b1157610b116120bd565b90506020020135115b610b80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f496e76616c696420616d6f756e74000000000000000000000000000000000000604482015260640161038b565b6101008d8d83818110610b9557610b956120bd565b90506020020135610ba69190612002565b8414610c6257610bb683836119eb565b6101008d8d83818110610bcb57610bcb6120bd565b90506020020135610bdc9190612002565b6040517f726577617264732e696e74657276616c2e636c61696d6564000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608e901b166038820152604c8101829052909450606c01604051602081830303815290604052805190602001209250610c5f83610984565b91505b60006101008e8e84818110610c7957610c796120bd565b90506020020135610c8a9190612016565b90506001811b838116819003610cfc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f416c726561647920636c61696d65640000000000000000000000000000000000604482015260640161038b565b610d748f8f85818110610d1157610d116120bd565b905060200201358e8e8e87818110610d2b57610d2b6120bd565b905060200201358d8d88818110610d4457610d446120bd565b905060200201358c8c89818110610d5d57610d5d6120bd565b9050602002810190610d6f91906120ec565b611a4d565b610dda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f496e76616c69642070726f6f6600000000000000000000000000000000000000604482015260640161038b565b506001901b9190911790610ded81612154565b9050610ad3565b50610dff82826119eb565b505050505050505050505050565b6000610e387f41c30d91bfaf5fa8d610263b0554366f2159a2b6807bf2fdbeb8f2b21a62f17b611863565b90506000806000610e7d6040518060400160405280601181526020017f726f636b65744e6f64654d616e61676572000000000000000000000000000000815250611b63565b6040517fb71f0c7c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e811660048301529192509082169063b71f0c7c90602401602060405180830381865afa158015610eed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f11919061218c565b6000546040517f5b49ff6200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8f8116600483015292955061010090910490911690635b49ff6290602401602060405180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae919061218c565b6040517fe667d82800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e811660048301529193509082169063e667d82890602401602060405180830381865afa15801561101e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110429190612082565b156111dc5784156110f7573373ffffffffffffffffffffffffffffffffffffffff8416146110f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f43616e206f6e6c7920636c61696d20616e64207374616b652066726f6d20525060448201527f4c207769746864726177616c2061646472657373000000000000000000000000606482015260840161038b565b61127b565b3373ffffffffffffffffffffffffffffffffffffffff8416148061113057503373ffffffffffffffffffffffffffffffffffffffff8d16145b8061115057503373ffffffffffffffffffffffffffffffffffffffff8316145b6110f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f43616e206f6e6c7920636c61696d2066726f6d207769746864726177616c206160448201527f6464726573736573206f72206e6f646520616464726573730000000000000000606482015260840161038b565b3373ffffffffffffffffffffffffffffffffffffffff8d16148061121557503373ffffffffffffffffffffffffffffffffffffffff8316145b61127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f43616e206f6e6c7920636c61696d2066726f6d206e6f64652061646472657373604482015260640161038b565b5060006112a77f1b80652f417157fe4774177f7d33c8b600483b9193e3f00d2ab1ace8fa6bdc9c611863565b905060008060005b8c811015611313578b8b828181106112c9576112c96120bd565b90506020020135836112db91906121a9565b92508989828181106112ef576112ef6120bd565b905060200201358261130191906121a9565b915061130c81612154565b90506112af565b508187111561137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e76616c6964207374616b6520616d6f756e74000000000000000000000000604482015260640161038b565b600061138a88846121bc565b90508015611423576040517f01e3366700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301528581166024830152604482018390528816906301e3366790606401600060405180830381600087803b15801561140a57600080fd5b505af115801561141e573d6000803e3d6000fd5b505050505b5080156115f9576040517f3bed33ce0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff871690633bed33ce90602401600060405180830381600087803b15801561149257600080fd5b505af11580156114a6573d6000803e3d6000fd5b5050505060008473ffffffffffffffffffffffffffffffffffffffff168261271090604051600060405180830381858888f193505050503d8060008114611509576040519150601f19603f3d011682016040523d82523d6000602084013e61150e565b606091505b50509050806115f7576040517f726577617264732e6574682e62616c616e63650000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660338201526000906047016040516020818303038152906040528051906020012090506115948184611bf9565b8773ffffffffffffffffffffffffffffffffffffffff166398ea5fca846040518263ffffffff1660e01b81526004016000604051808303818588803b1580156115dc57600080fd5b505af11580156115f0573d6000803e3d6000fd5b5050505050505b505b505084156117fd57600081905060006116466040518060400160405280601181526020017f726f636b65744e6f64655374616b696e67000000000000000000000000000000815250611b63565b6040517f01e3366700000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8581166024830152604482018a9052919250908716906301e3366790606401600060405180830381600087803b1580156116c057600080fd5b505af11580156116d4573d6000803e3d6000fd5b50506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018b90528516925063095ea7b391506044016020604051808303816000875af115801561174d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117719190612082565b506040517fcb1c832100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8f811660048301526024820189905282169063cb1c832190604401600060405180830381600087803b1580156117e257600080fd5b505af11580156117f6573d6000803e3d6000fd5b5050505050505b8b73ffffffffffffffffffffffffffffffffffffffff167fa95ccb6ea843871c0e81afc0fa4387c0bb5b36ad97007a97b3ea802f443c5a178c8c8c8c8c8c60405161184d9695949392919061221a565b60405180910390a2505050505050505050505050565b600080546040517f21f8a7210000000000000000000000000000000000000000000000000000000081526004810184905261010090910473ffffffffffffffffffffffffffffffffffffffff16906321f8a72190602401602060405180830381865afa1580156118d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610262919061218c565b600080546040517fa6ed563e0000000000000000000000000000000000000000000000000000000081526004810184905261010090910473ffffffffffffffffffffffffffffffffffffffff169063a6ed563e906024016109dc565b6000546040517f4e91db08000000000000000000000000000000000000000000000000000000008152600481018490526024810183905261010090910473ffffffffffffffffffffffffffffffffffffffff1690634e91db08906044015b600060405180830381600087803b1580156119cf57600080fd5b505af11580156119e3573d6000803e3d6000fd5b505050505050565b6000546040517fe2a4853a000000000000000000000000000000000000000000000000000000008152600481018490526024810183905261010090910473ffffffffffffffffffffffffffffffffffffffff169063e2a4853a906044016119b5565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660208201526000603482018190526054820186905260748201859052908190609401604051602081830303815290604052805190602001209050600088604051602001611af091907f726577617264732e6d65726b6c652e726f6f74000000000000000000000000008152601381019190915260330190565b6040516020818303038152906040528051906020012090506000611b13826118fb565b9050611b55868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250859250879150611c5b9050565b9a9950505050505050505050565b600080611b7a836040516020016102e0919061202a565b905073ffffffffffffffffffffffffffffffffffffffff8116610262576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e640000000000000000000000000000604482015260640161038b565b6000546040517fadb353dc000000000000000000000000000000000000000000000000000000008152600481018490526024810183905261010090910473ffffffffffffffffffffffffffffffffffffffff169063adb353dc906044016119b5565b600082611c688584611c71565b14949350505050565b600081815b8451811015611cb657611ca282868381518110611c9557611c956120bd565b6020026020010151611cbe565b915080611cae81612154565b915050611c76565b509392505050565b6000818310611cda57600082815260208490526040902061097d565b5060009182526020526040902090565b73ffffffffffffffffffffffffffffffffffffffff81168114611d0c57600080fd5b50565b8035611d1a81611cea565b919050565b60008083601f840112611d3157600080fd5b50813567ffffffffffffffff811115611d4957600080fd5b6020830191508360208260051b8501011115611d6457600080fd5b9250929050565b600080600080600080600080600060a08a8c031215611d8957600080fd5b8935611d9481611cea565b985060208a013567ffffffffffffffff80821115611db157600080fd5b611dbd8d838e01611d1f565b909a50985060408c0135915080821115611dd657600080fd5b611de28d838e01611d1f565b909850965060608c0135915080821115611dfb57600080fd5b611e078d838e01611d1f565b909650945060808c0135915080821115611e2057600080fd5b50611e2d8c828d01611d1f565b915080935050809150509295985092959850929598565b60008060408385031215611e5757600080fd5b823591506020830135611e6981611cea565b809150509250929050565b60008060008060008060008060008060c08b8d031215611e9357600080fd5b611e9c8b611d0f565b995060208b013567ffffffffffffffff80821115611eb957600080fd5b611ec58e838f01611d1f565b909b50995060408d0135915080821115611ede57600080fd5b611eea8e838f01611d1f565b909950975060608d0135915080821115611f0357600080fd5b611f0f8e838f01611d1f565b909750955060808d0135915080821115611f2857600080fd5b50611f358d828e01611d1f565b9150809450508092505060a08b013590509295989b9194979a5092959850565b60008060008060808587031215611f6b57600080fd5b5050823594602084013594506040840135936060013592509050565b600060208284031215611f9957600080fd5b813561097d81611cea565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008261201157612011611fa4565b500490565b60008261202557612025611fa4565b500690565b7f636f6e74726163742e616464726573730000000000000000000000000000000081526000825160005b818110156120715760208186018101516010868401015201612054565b506000920160100191825250919050565b60006020828403121561209457600080fd5b8151801515811461097d57600080fd5b6000602082840312156120b657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261212157600080fd5b83018035915067ffffffffffffffff82111561213c57600080fd5b6020019150600581901b3603821315611d6457600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361218557612185611fd3565b5060010190565b60006020828403121561219e57600080fd5b815161097d81611cea565b8082018082111561026257610262611fd3565b8181038181111561026257610262611fd3565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561220157600080fd5b8260051b80836020870137939093016020019392505050565b60608152600061222e60608301888a6121cf565b82810360208401526122418187896121cf565b905082810360408401526122568185876121cf565b999850505050505050505056fea2646970667358221220f75764e6da0af61a491821a4735054ae09dab1877bf776e7e5c0c30978e1f3b264736f6c63430008120033
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); }
}
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);
}
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;
}
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;
}
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;
}
RocketTokenRPLInterface.sol 45 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/IERC20.sol";
interface RocketTokenRPLInterface is IERC20 {
function getInflationCalcTime() external view returns(uint256);
function getInflationIntervalTime() external view returns(uint256);
function getInflationIntervalRate() external view returns(uint256);
function getInflationIntervalsPassed() external view returns(uint256);
function getInflationIntervalStartTime() external view returns(uint256);
function getInflationRewardsContractAddress() external view returns(address);
function inflationCalculate() external view returns (uint256);
function inflationMintTokens() external returns (uint256);
function swapTokens(uint256 _amount) external;
}
RocketVaultWithdrawerInterface.sol 35 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 RocketVaultWithdrawerInterface {
function receiveVaultWithdrawalETH() external payable;
}
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 56 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 withdrawRPL(uint256 _amount) external;
function withdrawRPL(address _nodeAddress, uint256 _amount) external;
function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) external;
}
MerkleProof.sol 227 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*
* _Available since v4.7._
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*
* _Available since v4.4._
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*
* _Available since v4.7._
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* _Available since v4.7._
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
require(proofPos == proofLen, "MerkleProof: invalid multiproof");
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
require(proofPos == proofLen, "MerkleProof: invalid multiproof");
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
RocketRewardsRelayInterface.sol 38 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;
interface RocketRewardsRelayInterface {
function relayRewards(uint256 _intervalIndex, bytes32 _merkleRoot, uint256 _rewardsRPL, uint256 _rewardsETH) external;
function claim(address _nodeAddress, uint256[] calldata _intervalIndex, uint256[] calldata _amountRPL, uint256[] calldata _amountETH, bytes32[][] calldata _merkleProof) external;
function claimAndStake(address _nodeAddress, uint256[] calldata _intervalIndex, uint256[] calldata _amountRPL, uint256[] calldata _amountETH, bytes32[][] calldata _merkleProof, uint256 _stakeAmount) external;
function isClaimed(uint256 _intervalIndex, address _claimer) external view returns (bool);
}
RocketSmoothingPoolInterface.sol 35 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;
interface RocketSmoothingPoolInterface {
function withdrawEther(address _to, uint256 _amount) external;
}
RocketMerkleDistributorMainnet.sol 245 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 "../RocketBase.sol";
import "../../interface/token/RocketTokenRPLInterface.sol";
import "../../interface/RocketVaultInterface.sol";
import "../../interface/node/RocketNodeStakingInterface.sol";
import "../../interface/rewards/RocketRewardsRelayInterface.sol";
import "../../interface/rewards/RocketSmoothingPoolInterface.sol";
import "../../interface/RocketVaultWithdrawerInterface.sol";
import "../../interface/node/RocketNodeManagerInterface.sol";
import "../../interface/rewards/RocketMerkleDistributorMainnetInterface.sol";
import "@openzeppelin4/contracts/utils/cryptography/MerkleProof.sol";
/// @dev On mainnet, the relay and the distributor are the same contract as there is no need for an intermediate contract to
/// handle cross-chain messaging.
contract RocketMerkleDistributorMainnet is RocketBase, RocketMerkleDistributorMainnetInterface, RocketVaultWithdrawerInterface {
// Events
event RewardsClaimed(address indexed claimer, uint256[] rewardIndex, uint256[] amountRPL, uint256[] amountETH);
// Constants
uint256 constant network = 0;
// Immutables
bytes32 immutable rocketVaultKey;
bytes32 immutable rocketTokenRPLKey;
// Allow receiving ETH
receive() payable external {}
// Construct
constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
// Version
version = 2;
// Precompute keys
rocketVaultKey = keccak256(abi.encodePacked("contract.address", "rocketVault"));
rocketTokenRPLKey = keccak256(abi.encodePacked("contract.address", "rocketTokenRPL"));
}
// Called by RocketRewardsPool to include a snapshot into this distributor
function relayRewards(uint256 _rewardIndex, bytes32 _root, uint256 _rewardsRPL, uint256 _rewardsETH) external override onlyLatestContract("rocketMerkleDistributorMainnet", address(this)) onlyLatestContract("rocketRewardsPool", msg.sender) {
bytes32 key = keccak256(abi.encodePacked('rewards.merkle.root', _rewardIndex));
require(getBytes32(key) == bytes32(0));
setBytes32(key, _root);
// Send the ETH and RPL to the vault
RocketVaultInterface rocketVault = RocketVaultInterface(getAddress(rocketVaultKey));
if (_rewardsETH > 0) {
rocketVault.depositEther{value: _rewardsETH}();
}
if (_rewardsRPL > 0) {
IERC20 rocketTokenRPL = IERC20(getAddress(rocketTokenRPLKey));
rocketTokenRPL.approve(address(rocketVault), _rewardsRPL);
rocketVault.depositToken("rocketMerkleDistributorMainnet", rocketTokenRPL, _rewardsRPL);
}
}
// Reward recipients can call this method with a merkle proof to claim rewards for one or more reward intervals
function claim(address _nodeAddress, uint256[] calldata _rewardIndex, uint256[] calldata _amountRPL, uint256[] calldata _amountETH, bytes32[][] calldata _merkleProof) external override {
claimAndStake(_nodeAddress, _rewardIndex, _amountRPL, _amountETH, _merkleProof, 0);
}
function claimAndStake(address _nodeAddress, uint256[] calldata _rewardIndex, uint256[] calldata _amountRPL, uint256[] calldata _amountETH, bytes32[][] calldata _merkleProof, uint256 _stakeAmount) public override {
_verifyClaim(_rewardIndex, _nodeAddress, _amountRPL, _amountETH, _merkleProof);
_claimAndStake(_nodeAddress, _rewardIndex, _amountRPL, _amountETH, _stakeAmount);
}
// Node operators can call this method to claim rewards for one or more reward intervals and specify an amount of RPL to stake at the same time
function _claimAndStake(address _nodeAddress, uint256[] calldata _rewardIndex, uint256[] calldata _amountRPL, uint256[] calldata _amountETH, uint256 _stakeAmount) internal {
// Get contracts
RocketVaultInterface rocketVault = RocketVaultInterface(getAddress(rocketVaultKey));
address rplWithdrawalAddress;
address withdrawalAddress;
// Confirm caller is permitted
{
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
if (_stakeAmount > 0) {
// If staking and RPL withdrawal address is set, must be called from RPL withdrawal address
require(msg.sender == rplWithdrawalAddress, "Can only claim and stake from RPL withdrawal address");
} else {
// Otherwise, must be called from RPL withdrawal address, node address or withdrawal address
require(msg.sender == rplWithdrawalAddress || msg.sender == _nodeAddress || msg.sender == withdrawalAddress, "Can only claim from withdrawal addresses or node address");
}
} else {
// If RPL withdrawal address isn't set, must be called from node address or withdrawal address
require(msg.sender == _nodeAddress || msg.sender == withdrawalAddress, "Can only claim from node address");
}
}
address rocketTokenRPLAddress = getAddress(rocketTokenRPLKey);
// Calculate totals
{
uint256 totalAmountRPL = 0;
uint256 totalAmountETH = 0;
for (uint256 i = 0; i < _rewardIndex.length; ++i) {
totalAmountRPL = totalAmountRPL + _amountRPL[i];
totalAmountETH = totalAmountETH + _amountETH[i];
}
// Validate input
require(_stakeAmount <= totalAmountRPL, "Invalid stake amount");
{
// Distribute any remaining tokens to the node's withdrawal address
uint256 remaining = totalAmountRPL - _stakeAmount;
if (remaining > 0) {
rocketVault.withdrawToken(rplWithdrawalAddress, IERC20(rocketTokenRPLAddress), remaining);
}
}
// Distribute ETH
if (totalAmountETH > 0) {
rocketVault.withdrawEther(totalAmountETH);
// Allow up to 10000 gas to send ETH to the withdrawal address
(bool result,) = withdrawalAddress.call{value: totalAmountETH, gas: 10000}("");
if (!result) {
// If the withdrawal address cannot accept the ETH with 10000 gas, add it to their balance to be claimed later at their own expense
bytes32 balanceKey = keccak256(abi.encodePacked('rewards.eth.balance', withdrawalAddress));
addUint(balanceKey, totalAmountETH);
// Return the ETH to the vault
rocketVault.depositEther{value: totalAmountETH}();
}
}
}
// Restake requested amount
if (_stakeAmount > 0) {
RocketTokenRPLInterface rocketTokenRPL = RocketTokenRPLInterface(rocketTokenRPLAddress);
RocketNodeStakingInterface rocketNodeStaking = RocketNodeStakingInterface(getContractAddress("rocketNodeStaking"));
rocketVault.withdrawToken(address(this), IERC20(rocketTokenRPLAddress), _stakeAmount);
rocketTokenRPL.approve(address(rocketNodeStaking), _stakeAmount);
rocketNodeStaking.stakeRPLFor(_nodeAddress, _stakeAmount);
}
// Emit event
emit RewardsClaimed(_nodeAddress, _rewardIndex, _amountRPL, _amountETH);
}
// If ETH was claimed but was unable to be sent to the withdrawal address, it can be claimed via this function
function claimOutstandingEth() external override {
// Get contracts
RocketVaultInterface rocketVault = RocketVaultInterface(getAddress(rocketVaultKey));
// Get the amount and zero it out
bytes32 balanceKey = keccak256(abi.encodePacked('rewards.eth.balance', msg.sender));
uint256 amount = getUint(balanceKey);
setUint(balanceKey, 0);
// Withdraw the ETH from the vault
rocketVault.withdrawEther(amount);
// Attempt to send it to the caller
(bool result,) = payable(msg.sender).call{value: amount}("");
require(result, 'Transfer failed');
}
// Returns the amount of ETH that can be claimed by a withdrawal address
function getOutstandingEth(address _address) external override view returns (uint256) {
bytes32 balanceKey = keccak256(abi.encodePacked('rewards.eth.balance', _address));
return getUint(balanceKey);
}
// Verifies the given data exists as a leaf nodes for the specified reward interval and marks them as claimed if they are valid
// Note: this function is optimised for gas when _rewardIndex is ordered numerically
function _verifyClaim(uint256[] calldata _rewardIndex, address _nodeAddress, uint256[] calldata _amountRPL, uint256[] calldata _amountETH, bytes32[][] calldata _merkleProof) internal {
// Set initial parameters to the first reward index in the array
uint256 indexWordIndex = _rewardIndex[0] / 256;
bytes32 claimedWordKey = keccak256(abi.encodePacked('rewards.interval.claimed', _nodeAddress, indexWordIndex));
uint256 claimedWord = getUint(claimedWordKey);
// Loop over every entry
for (uint256 i = 0; i < _rewardIndex.length; ++i) {
// Prevent accidental claim of 0
require(_amountRPL[i] > 0 || _amountETH[i] > 0, "Invalid amount");
// Check if this entry has a different word index than the previous
if (indexWordIndex != _rewardIndex[i] / 256) {
// Store the previous word
setUint(claimedWordKey, claimedWord);
// Load the word for this entry
indexWordIndex = _rewardIndex[i] / 256;
claimedWordKey = keccak256(abi.encodePacked('rewards.interval.claimed', _nodeAddress, indexWordIndex));
claimedWord = getUint(claimedWordKey);
}
// Calculate the bit index for this entry
uint256 indexBitIndex = _rewardIndex[i] % 256;
// Ensure the bit is not yet set on this word
uint256 mask = (1 << indexBitIndex);
require(claimedWord & mask != mask, "Already claimed");
// Verify the merkle proof
require(_verifyProof(_rewardIndex[i], _nodeAddress, _amountRPL[i], _amountETH[i], _merkleProof[i]), "Invalid proof");
// Set the bit for the current reward index
claimedWord = claimedWord | (1 << indexBitIndex);
}
// Store the word
setUint(claimedWordKey, claimedWord);
}
// Verifies that the given proof is valid
function _verifyProof(uint256 _rewardIndex, address _nodeAddress, uint256 _amountRPL, uint256 _amountETH, bytes32[] calldata _merkleProof) internal view returns (bool) {
bytes32 node = keccak256(abi.encodePacked(_nodeAddress, network, _amountRPL, _amountETH));
bytes32 key = keccak256(abi.encodePacked('rewards.merkle.root', _rewardIndex));
bytes32 merkleRoot = getBytes32(key);
return MerkleProof.verify(_merkleProof, merkleRoot, node);
}
// Returns true if the given claimer has claimed for the given reward interval
function isClaimed(uint256 _rewardIndex, address _claimer) public override view returns (bool) {
uint256 indexWordIndex = _rewardIndex / 256;
uint256 indexBitIndex = _rewardIndex % 256;
uint256 claimedWord = getUint(keccak256(abi.encodePacked('rewards.interval.claimed', _claimer, indexWordIndex)));
uint256 mask = (1 << indexBitIndex);
return claimedWord & mask == mask;
}
// Allow receiving ETH from RocketVault, no action required
function receiveVaultWithdrawalETH() external override payable {}
}
RocketMerkleDistributorMainnetInterface.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.
*
*/
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;
import "./RocketRewardsRelayInterface.sol";
interface RocketMerkleDistributorMainnetInterface is RocketRewardsRelayInterface {
function claimOutstandingEth() external;
function getOutstandingEth(address _address) external view returns (uint256);
}
Read Contract
getOutstandingEth 0xfa8779c8 → uint256
isClaimed 0xd2ef0795 → bool
version 0x54fd4d50 → uint8
Write Contract 5 functions
These functions modify contract state and require a wallet transaction to execute.
claim 0x5e38c572
address _nodeAddress
uint256[] _rewardIndex
uint256[] _amountRPL
uint256[] _amountETH
bytes32[][] _merkleProof
claimAndStake 0xdacfffa8
address _nodeAddress
uint256[] _rewardIndex
uint256[] _amountRPL
uint256[] _amountETH
bytes32[][] _merkleProof
uint256 _stakeAmount
claimOutstandingEth 0xf012062c
No parameters
receiveVaultWithdrawalETH 0xc095415d
No parameters
relayRewards 0xe44ba18f
uint256 _rewardIndex
bytes32 _root
uint256 _rewardsRPL
uint256 _rewardsETH
Recent Transactions
No transactions found for this address