// File: /contracts/WrapperFactory.sol



// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "./interfaces/IProxyFactory.sol";
import "./interfaces/IStakingWrapper.sol";


//Factory to create wrapped staking positions
contract WrapperFactory{
   
    address public constant proxyFactory = address(0x66807B5598A848602734B82E432dD88DBE13fC8f);
    
    address public owner;
    address public pendingOwner;

    address public wrapperImplementation;

    event SetPendingOwner(address indexed _address);
    event OwnerChanged(address indexed _address);
    event ImplementationChanged(address _implementation);
    event WrapperCreated(address _wrapper, uint256 _pid);

    constructor(){
        owner = msg.sender;
        emit OwnerChanged(msg.sender);
    }

    modifier onlyOwner() {
        require(owner == msg.sender, "!owner");
        _;
    }

    //set next owner
    function setPendingOwner(address _po) external onlyOwner{
        pendingOwner = _po;
        emit SetPendingOwner(_po);
    }

    //claim ownership
    function acceptPendingOwner() external {
        require(msg.sender == pendingOwner, "!p_owner");

        owner = pendingOwner;
        pendingOwner = address(0);
        emit OwnerChanged(owner);
    }

    function setImplementation(address _imp) external onlyOwner{
        wrapperImplementation = _imp;
        emit ImplementationChanged(_imp);
    }

    function CreateWrapper(uint256 _pid) external returns (address) {
        //create
        address wrapper = IProxyFactory(proxyFactory).clone(wrapperImplementation);
        emit WrapperCreated(wrapper, _pid);

        //init
        IStakingWrapper(wrapper).initialize(_pid);
        
        return wrapper;
    }
}
// File: /contracts/interfaces/IStakingWrapper.sol



// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

interface IStakingWrapper{
    struct EarnedData {
        address token;
        uint256 amount;
    }

    struct RewardType {
        address reward_token;
        uint128 reward_integral;
        uint128 reward_remaining;
    }

    function initialize(uint256 _poolId) external;
    function setExtraReward(address) external;
    function setRewardHook(address) external;
    function rewardHook() external view returns(address _hook);
    function getReward(address) external;
    function getReward(address,address) external;
    function user_checkpoint(address) external;
    function rewardLength() external view returns(uint256);
    function totalSupply() external view returns(uint256);
    function balanceOf(address) external view returns(uint256);
    function rewards(uint256 _rewardIndex) external view returns(RewardType memory);
    function earned(address _account) external returns(EarnedData[] memory claimable);
    function deposit(uint256 _amount, address _to) external returns (uint256);
    function withdraw(uint256 _amount) external returns (uint256);
    function withdraw(uint256 _amount, address _receiver, address ) external returns(uint256 shares);
    function redeem(uint256 _shares, address _receiver, address _owner) external returns (uint256 assets);
    function mint(uint256 _shares, address _to) external returns (uint256);
}
// File: /contracts/interfaces/IProxyFactory.sol



// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

interface IProxyFactory {
    function clone(address _target) external returns(address);
}