Files
smom-dbis-138/contracts/wrapped-lp-public/Chain138LPLocker.sol

74 lines
2.8 KiB
Solidity
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./interfaces/IWLPProgramEvents.sol";
/**
* @title Chain138LPLocker
* @notice Escrows DODO PMM LP ERC20 on Chain 138; releases only to BRIDGE_RELEASE_ROLE (Option A).
* @dev Per-lock `lockRef` is used as the cross-chain idempotency key for destination mint.
* One deployment typically corresponds to one `lpToken` (one pools LP token).
*/
contract Chain138LPLocker is AccessControl, IWLPProgramEvents {
using SafeERC20 for IERC20;
bytes32 public constant BRIDGE_RELEASE_ROLE = keccak256("BRIDGE_RELEASE_ROLE");
IERC20 public immutable lpToken;
struct Deposit {
address depositor;
uint256 amount;
bool released;
}
uint256 public lockCounter;
uint256 public totalEscrowed;
mapping(bytes32 => Deposit) public deposits;
constructor(address lpToken_, address admin) {
require(lpToken_ != address(0) && admin != address(0), "Locker: zero");
lpToken = IERC20(lpToken_);
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
/**
* @notice Lock LP into escrow; `lockRef` must be relayed to the public chain for mint.
*/
function deposit(uint256 amount) external returns (bytes32 lockRef) {
require(amount > 0, "Locker: zero amount");
lpToken.safeTransferFrom(msg.sender, address(this), amount);
lockRef = keccak256(abi.encode(block.chainid, address(this), lockCounter++, msg.sender, amount));
deposits[lockRef] = Deposit({depositor: msg.sender, amount: amount, released: false});
totalEscrowed += amount;
emit LPLocked(lockRef, msg.sender, amount, address(lpToken));
}
/**
* @notice Release one full lock to `to` after redemption message (or operational unwind).
*/
function releaseLock(bytes32 lockRef, address to) external onlyRole(BRIDGE_RELEASE_ROLE) {
Deposit storage d = deposits[lockRef];
require(d.amount > 0 && !d.released, "Locker: bad lock");
d.released = true;
uint256 amt = d.amount;
totalEscrowed -= amt;
lpToken.safeTransfer(to, amt);
emit LPReleased(lockRef, to, amt, address(lpToken));
}
/**
* @notice Aggregate release for pro-rata / FIFO policies (requires off-chain ordering).
*/
function releaseAmount(address to, uint256 amount) external onlyRole(BRIDGE_RELEASE_ROLE) {
require(amount > 0 && amount <= totalEscrowed, "Locker: amount");
totalEscrowed -= amount;
lpToken.safeTransfer(to, amount);
emit LPReleased(bytes32(0), to, amount, address(lpToken));
}
}