47 lines
1.8 KiB
Solidity
47 lines
1.8 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "@openzeppelin/contracts/access/AccessControl.sol";
|
|
import "./WLPReceiptToken.sol";
|
|
import "./interfaces/IWLPProgramEvents.sol";
|
|
|
|
/**
|
|
* @title PublicChainMintController
|
|
* @notice Destination-chain controller: mints `wLP` once per `lockRef` (replay protection).
|
|
* @dev Relayer must verify Chain 138 `LPLocked` event / attestation off-chain or via future ZK proof.
|
|
*/
|
|
contract PublicChainMintController is AccessControl, IWLPProgramEvents {
|
|
bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE");
|
|
|
|
WLPReceiptToken public immutable wlp;
|
|
/// @notice Optional Chain 138 locker address for documentation / future cross-verify hooks.
|
|
address public immutable chain138Locker;
|
|
|
|
mapping(bytes32 => bool) public mintedForLock;
|
|
bool public mintPaused;
|
|
|
|
constructor(address wlp_, address chain138Locker_, address admin) {
|
|
require(wlp_ != address(0) && admin != address(0), "MintCtl: zero");
|
|
wlp = WLPReceiptToken(wlp_);
|
|
chain138Locker = chain138Locker_;
|
|
_grantRole(DEFAULT_ADMIN_ROLE, admin);
|
|
}
|
|
|
|
/**
|
|
* @notice Idempotent mint keyed by `lockRef` (must match Chain 138 locker emission).
|
|
*/
|
|
function mintForLock(bytes32 lockRef, address recipient, uint256 amount) external onlyRole(RELAYER_ROLE) {
|
|
require(!mintPaused, "MintCtl: paused");
|
|
require(lockRef != bytes32(0), "MintCtl: zero lockRef");
|
|
require(recipient != address(0) && amount > 0, "MintCtl: bad args");
|
|
require(!mintedForLock[lockRef], "MintCtl: replay");
|
|
mintedForLock[lockRef] = true;
|
|
wlp.mint(recipient, amount);
|
|
emit WLPMinted(lockRef, recipient, amount);
|
|
}
|
|
|
|
function setMintPaused(bool paused) external onlyRole(DEFAULT_ADMIN_ROLE) {
|
|
mintPaused = paused;
|
|
}
|
|
}
|