The document proposes Magna Hook design for Skate. Our goal is to let users stake claimed tokens on Eigen Layer strategy upon claiming on Magna. For staking of these tokens on Eigen Layer strategy, we require a signature signed by the user and passed to the Skate’s Hook on Magna which is then forward to “depositIntoStrategyWithSignature” function on “StrategyManager” contract of Eigen Layer contracts.

The digest for signature can be constructed by making a call to “strategyManager”’s function “calculateStrategyDepositDigestHash”.

https://github.com/Layr-Labs/eigenlayer-contracts/blob/main/src/contracts/core/StrategyManager.sol#L371-L393”

Would it be possible to have the user first sign a signature for deposit to Strategy and only then initiate claim on Magna Vester contract for Skate, having the signature relayed to Skate Hook through “extraData” parameter?

The possible mock implementation for Hook is provided below for reference.

pragma solidity =0.8.24;

import {IPostClaimHandler} from "../../src/interfaces/IPostClaimHandler.sol";
import {IERC20} from "@openzeppelin/interfaces/IERC20.sol";
import {SafeERC20} from "@openzeppelin/token/ERC20/utils/SafeERC20.sol";
import {Context} from "@openzeppelin/utils/Context.sol";

interface IStrategy {
    ...
}

interface IStrategyManager {
    function depositIntoStrategyWithSignature(
        IStrategy strategy,
        IERC20 token,
        uint256 amount,
        address staker,
        uint256 expiry,
        bytes memory signature
    ) external returns (uint256 depositShares);
}

error InvalidCaller();

contract ClaimAndStakeHandler is IPostClaimHandler, Context {
    using SafeERC20 for IERC20;

    address public immutable vesterContract;
    IStrategyManager public immutable strategyManager;
    IStrategy public immutable strategy;

    constructor(address vesterContract_, address strategyManager_, address strategy_) {
        vesterContract = vesterContract_;
        strategyManager = strategyManager_;
        strategy = strategy_;
    }

    function handlePostClaim(
        IERC20 claimToken,
        uint256 amount,
        address originalBeneficiary,
        address withdrawalAddress,
        string memory allocationId,
        bytes memory extraData
    ) external {
        if (_msgSender() != vesterContract) {
            revert InvalidCaller();
        }

        (bytes memory signature, uint256 expiry) = abi.decode(extraData, (bytes, uint256));

        claimToken.approve(address(strategyManager), amount);
        strategyManager.depositIntoStrategyWithSignature(
            strategy, 
            claimToken, 
            amount, 
            withdrawalAddress,
            expiry,
            signature
        );
    }
}