// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./interfaces/IGatekeeper.sol"; contract Gatekeeper is IGatekeeper { uint256 public override ghostedSupply; address public immutable staking; uint256 private _aggregatedPublicKey; mapping(uint256 => mapping(uint256 => bool)) private _executedTransaction; constructor( address _staking, uint256 _ghostedSupply ) { ghostedSupply = _ghostedSupply; staking = _staking; } function ghost(bytes32 receiver, uint256 amount) external override { if (msg.sender != staking) revert NotStaking(); ghostedSupply += amount; emit Ghosted(receiver, amount); } function materialize( address receiver, uint256 amount, uint256 rx, uint256 s ) external override { if (msg.sender != staking) revert NotStaking(); _checkTransactionExistence(rx, s); bytes32 message = keccak256(abi.encodePacked("materialize", receiver, amount)); if (_incorrectSignature(rx, s, message)) revert WrongSignature(); ghostedSupply -= amount; emit Materialized(receiver, amount); } function rotate( uint256 aggregatedPublicKey, uint256 rx, uint256 s ) external override { _checkTransactionExistence(rx, s); bytes32 message = keccak256(abi.encodePacked("rotate", aggregatedPublicKey)); if (_incorrectSignature(rx, s, message)) revert WrongSignature(); _aggregatedPublicKey = aggregatedPublicKey; emit Rotated(aggregatedPublicKey); } function _checkTransactionExistence(uint256 rx, uint256 s) private { if (_executedTransaction[rx][s]) revert AlreadyExecuted(); _executedTransaction[rx][s] = true; } function _incorrectSignature(uint256 rx, uint256 s, bytes32 m) private pure returns (bool) { // no logic below, just to suppress warnings from solc uint256 void = rx; void = s; void = uint256(m); // always bad signature for now return true; } }