// File: contracts/entryPoint.sol



pragma solidity ^0.8.0;

contract entryPoint {
    struct AddressSlot {
        address value;
    }
    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    constructor (address _implementation)
    {
        _setImplementation(_implementation);
    }

    modifier onlyOwner(){
        (bool success, bytes memory data) = address(this).staticcall(abi.encodeWithSignature("owner()"));
        require(success, "failled getting owner.");
        address owner = abi.decode(data, (address));
        require(owner == msg.sender || owner == address(0), "access denied. owner ONLY.");
        _;
    }

    function setImplementation(address _implementation) external onlyOwner{
        _setImplementation(_implementation);
    }

    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    fallback() external payable {
        _fallback();
    }

    receive() external payable virtual {
        _fallback();
    }

    function _fallback() internal virtual {
        _delegate(_getImplementation());
    }

    function _delegate(address _implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), _implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }
}