RegenStakerFactory
Title: RegenStaker Factory
Author: Golem Foundation
Deploys RegenStaker contracts with explicit variant selection
SECURITY: Validates deployment bytecode against pre-configured canonical hashes
SECURITY ASSUMPTION: Factory deployer is trusted to provide correct canonical bytecode hashes. If deployer is compromised, all future deployments could use unauthorized code. This is an acceptable risk given the controlled deployment environment.
TRUST BOUNDARY WARNING: This factory guarantees CODE IDENTITY only, NOT parameter safety. The factory validates that deployed bytecode matches canonical, audited code. However, it does NOT validate constructor parameters, including:
- earningPowerCalculator: Controls reward distribution logic
- admin: Has full control over staker configuration
- Access Control: Allowsets and blocksets control access to various operations A malicious actor can deploy a staker with canonical bytecode but inject:
- A malicious earning power calculator (to manipulate rewards)
- Themselves as admin (to change calculator post-deployment)
- Malicious address sets
OPERATIONAL SECURITY: Before funding or integrating with ANY RegenStaker instance:
- Verify the earningPowerCalculator address and its code
- Verify the admin is a trusted party/governance contract
- Verify all address sets are legitimate
- For official deployments, use published addresses from governance The StakerDeploy event includes calculator address and codehash to facilitate verification. For production use, consider requiring deployments from a governance-approved strict factory that maintains an allowset of acceptable calculators.
Note: security-contact: [email protected]
State Variables
canonicalBytecodeHash
mapping(RegenStakerVariant => bytes32) public canonicalBytecodeHash
stakers
Tracks deployed stakers per deployer
mapping(address => StakerInfo[]) public stakers
Functions
constructor
Initializes the factory with canonical bytecode hashes for both variants
constructor(bytes32 regenStakerBytecodeHash, bytes32 noDelegationBytecodeHash) ;
Parameters
| Name | Type | Description |
|---|---|---|
regenStakerBytecodeHash | bytes32 | Canonical hash for WITH_DELEGATION variant |
noDelegationBytecodeHash | bytes32 | Canonical hash for WITHOUT_DELEGATION variant |
validatedBytecode
Modifier to validate bytecode against canonical hash
modifier validatedBytecode(bytes calldata code, RegenStakerVariant variant) ;
createStakerWithoutDelegation
Deploy RegenStaker without delegation support
WARNING: This factory validates bytecode but NOT constructor parameters. Verify params.earningPowerCalculator, params.admin, and address sets before funding!
function createStakerWithoutDelegation(CreateStakerParams calldata params, bytes32 salt, bytes calldata code)
external
validatedBytecode(code, RegenStakerVariant.WITHOUT_DELEGATION)
returns (address stakerAddress);
Parameters
| Name | Type | Description |
|---|---|---|
params | CreateStakerParams | Staker configuration parameters |
salt | bytes32 | Deployment salt for deterministic addressing |
code | bytes | Bytecode for WITHOUT_DELEGATION variant |
Returns
| Name | Type | Description |
|---|---|---|
stakerAddress | address | Address of deployed contract |
createStakerWithDelegation
Deploy RegenStaker with delegation support
WARNING: This factory validates bytecode but NOT constructor parameters. Verify params.earningPowerCalculator, params.admin, and address sets before funding!
function createStakerWithDelegation(CreateStakerParams calldata params, bytes32 salt, bytes calldata code)
external
validatedBytecode(code, RegenStakerVariant.WITH_DELEGATION)
returns (address stakerAddress);
Parameters
| Name | Type | Description |
|---|---|---|
params | CreateStakerParams | Staker configuration parameters |
salt | bytes32 | Deployment salt for deterministic addressing |
code | bytes | Bytecode for WITH_DELEGATION variant |
Returns
| Name | Type | Description |
|---|---|---|
stakerAddress | address | Address of deployed contract |
predictStakerAddress
Predict deterministic deployment address
function predictStakerAddress(bytes32 salt, address deployer, bytes memory bytecode)
external
view
returns (address);
Parameters
| Name | Type | Description |
|---|---|---|
salt | bytes32 | Deployment salt |
deployer | address | Address that will deploy |
bytecode | bytes | Deployment bytecode (including constructor args) |
Returns
| Name | Type | Description |
|---|---|---|
<none> | address | Predicted contract address |
getStakersByDeployer
Returns all RegenStakers deployed by a specific address
function getStakersByDeployer(address deployer) external view returns (StakerInfo[] memory);
Parameters
| Name | Type | Description |
|---|---|---|
deployer | address | Deployer address |
_validateBytecode
Validate bytecode against canonical hash
function _validateBytecode(bytes calldata code, RegenStakerVariant variant) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
code | bytes | Bytecode to validate |
variant | RegenStakerVariant | RegenStaker variant this bytecode represents |
_deployStaker
function _deployStaker(
CreateStakerParams calldata params,
bytes32 salt,
bytes memory code,
RegenStakerVariant variant
) internal returns (address stakerAddress);
_encodeConstructorParams
function _encodeConstructorParams(CreateStakerParams calldata params) internal pure returns (bytes memory);
_recordStaker
function _recordStaker(
CreateStakerParams calldata params,
address stakerAddress,
bytes32 salt,
RegenStakerVariant variant
) internal;
Events
StakerDeploy
Emitted when a new RegenStaker is deployed
calculatorAddress is sufficient for verification; off-chain tools can query code directly
event StakerDeploy(
address indexed deployer,
address indexed admin,
address indexed stakerAddress,
bytes32 salt,
RegenStakerVariant variant,
address calculatorAddress
);
Parameters
| Name | Type | Description |
|---|---|---|
deployer | address | Address that called the factory |
admin | address | Admin of the newly deployed staker |
stakerAddress | address | Address of the deployed staker |
salt | bytes32 | Deployment salt used |
variant | RegenStakerVariant | Variant of staker deployed |
calculatorAddress | address | Earning power calculator address (CRITICAL FOR VERIFICATION) |
Errors
InvalidBytecode
error InvalidBytecode();
UnauthorizedBytecode
error UnauthorizedBytecode(RegenStakerVariant variant, bytes32 providedHash, bytes32 expectedHash);
Structs
CreateStakerParams
struct CreateStakerParams {
IERC20 rewardsToken;
IERC20 stakeToken;
address admin;
IAddressSet stakerAllowset;
IAddressSet stakerBlockset;
AccessMode stakerAccessMode;
IAddressSet allocationMechanismAllowset;
IEarningPowerCalculator earningPowerCalculator;
uint256 maxBumpTip;
uint256 minimumStakeAmount;
uint256 rewardDuration;
}
StakerInfo
Information about a deployed RegenStaker
struct StakerInfo {
address deployerAddress;
uint256 timestamp;
address admin;
address stakerAddress;
RegenStakerVariant variant;
address calculatorAddress;
bytes32 salt;
}
Enums
RegenStakerVariant
enum RegenStakerVariant {
WITHOUT_DELEGATION,
WITH_DELEGATION
}