pragma solidity ^0.8.13; contract CapabilityBeacon { bytes internal constant INIT_CODE = hex"600060005360016000f3"; bytes32 internal constant INIT_HASH = keccak256(INIT_CODE); event Claimed(address indexed agent, bytes32 indexed capability, address indexed beacon); function deploy(bytes32 capability) external returns (address beacon) { bytes32 salt = keccak256(abi.encodePacked(msg.sender, capability)); beacon = _deploy(salt); emit Claimed(msg.sender, capability, beacon); } function has(address agent, bytes32 capability) external view returns (bool) { address beacon = _computeAddress(agent, capability); return beacon.code.length > 0; } function _deploy(bytes32 salt) private returns (address addr) { bytes memory init = INIT_CODE; assembly { addr := create2(0, add(init, 0x20), mload(init), salt) } } function _computeAddress(address agent, bytes32 capability) internal view returns (address) { bytes32 salt = keccak256(abi.encodePacked(agent, capability)); bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, INIT_HASH)); return address(uint160(uint256(hash))); } }