feat: expand non-evm relay and route planning support
This commit is contained in:
73
contracts/wrapped-lp-public/Chain138LPLocker.sol
Normal file
73
contracts/wrapped-lp-public/Chain138LPLocker.sol
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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 pool’s 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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user