Master Smart Contract

Stake:

function stake() public payable nonReentrant {
       StakeHolder stakeHolder = _stake();
       clETH.mint(address(msg.sender), msg.value);
       ...
}

function stakeForWCLETH() public payable nonReentrant {
       StakeHolder stakeHolder = _stake();
       clETH.mint(address(stakeHolder), msg.value);
       . . .
}

function _stake() internal returns (StakeHolder) {
       require(msg.value >= MIN_DEPOSIT_AMOUNT, "Must sent minimum 32 ETH");
       StakeHolder stakeHolder = StakeHolders[msg.sender];
       . . . 
       StakedBalance[msg.sender] += msg.value;
       totalPoolStake += msg.value;
       return stakeHolder;
}
  1. The user can stake and decide on which chain the user needs the LST. Dexponent offers LST on two types of chains:

    1. Ethereum: LST is clETH.

    2. L2 Chains (eg. Arbitrum): LST is wclETH.

  2. Once the user wants to stake, the respective stake/ stakeForWCLETH function is called:

    1. The minimum amount to stake is checked.

    2. If the ISC already exists - the ISC balance is incremented. Else, a new ISC is created.

    3. ETH is sent to this ISC immediately.

    4. If the user chooses to get clETH, clETH is minted and deposited in the user’s wallet.

    5. If the user chooses to get wclETH, clETH is minted and locked on ISC, and wclETH is minted and sent to the user's wallet on the chosen L2 chain.

Unstake

function unstake(uint256 amount) public nonReentrant ZeroAmount(amount)  {
   bool enoughStaked = hasEnoughStakedETH(amount,msg.sender);
   require(
       enoughStaked && clETH.balanceOf(msg.sender) >= amount,
       "Not enough clETH"
   );
   clETH.transferFrom(
       msg.sender,
       address(StakeHolders[msg.sender]),
       amount
   );
   WithdrawalBalance[msg.sender] += amount;
   . . . 
}
  1. Once the user chooses to unstake and wants to exit a particular validator:

    1. The smart contract checks if the user has enough staked balance.

    2. clETH is transferred from the user's wallet to the ISC.

    3. The node operator is directed to exit the particular validator.

function burnCleth(
       address account,
       uint256 amount
   ) external nonReentrant onlyOwner ZeroAddress(account) ZeroAmount(amount)  {
       require(
           amount <= WithdrawalBalance[account],
           "withdrawal amount is not enough"
       );
       StakeHolder stakedHolderContract = StakeHolders[account];
       WithdrawalBalance[account] -= amount;
       StakedBalance[account] -= amount;
       totalPoolStake -= amount;
       clETH.burnFrom(address(stakedHolderContract), amount);
       stakedHolderContract.withdrawETH(amount, account);
	. . . 
}
  1. Once the validator is exited, the user can claim the ETH from ISC. Admin does the following:

    1. clETH from the ISC is burned.

    2. ETH is transferred to the user’s wallet from ISC.

Rewards

function claimRewardForCleth(
       address account,
       uint256 amount
   ) external nonReentrant onlyOwner {
       claimReward(account, account, amount);
       ...
}
function claimRewardForWcleth(
       address account,
       uint256 amount
   ) external nonReentrant onlyOwner {
       StakeHolder stakeHolder = StakeHolders[account];
       claimReward(address(stakeHolder), account, amount);
	. . .
}
function claimReward(
       address clETHMintTo,
       address account,
       uint256 amount
   )
       internal
       ZeroAddress(account)
       ZeroAddress(clETHMintTo)
       ZeroAmount(amount)
   {
       StakeHolder stakeHolder = StakeHolders[account];
       require(address(stakeHolder) != address(0), "Invalid Account");
       require(
           address(stakeHolder).balance >= amount,
           "Insufficient Rewards to claim"
       );
       clETH.mint(clETHMintTo, amount);
       stakeHolder.withdrawETH(amount, stakeHolder.masterContract());
}
  1. The rewards are collected on ISC. Once the user claims them, Admin does the following:

    1. LST equivalent to the claimed rewards amount is minted and sent to the user’s wallet.

    2. Equivalent ETH is transferred from ISC to MSC. Only the unclaimed amount of rewards is present in the ISC.

Ownership Transfer

function changeOwner(address newOwner) external  nonReentrant onlyOwner ZeroAddress(newOwner) {
   . 
   owner = newOwner;
}
  1. All the Admin privileges are transferred to the new address.

Last updated