- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault. - Token-aggregation service routes, planner, chain config, relay env templates. - Config snapshots and multi-chain deployment markdown updates. - gitignore services/btc-intake/dist/ (tsc output); do not track dist. Run forge build && forge test before deploy (large solc graph). Made-with: Cursor
133 lines
4.2 KiB
Solidity
133 lines
4.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
|
|
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
|
|
import "../../vendor/openzeppelin/UUPSUpgradeable.sol";
|
|
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
import "../../emoney/interfaces/IeMoneyToken.sol";
|
|
|
|
/**
|
|
* @title DebtToken
|
|
* @notice Token representing outstanding debt obligation (dToken equivalent)
|
|
* @dev Minted when borrow occurs, burned on repayment
|
|
* Interest-accruing, non-freely transferable
|
|
* Extends eMoneyToken pattern
|
|
*/
|
|
contract DebtToken is Initializable, ERC20Upgradeable, AccessControlUpgradeable, UUPSUpgradeable {
|
|
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
|
|
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
|
|
|
|
address public vault;
|
|
address public currency; // eMoney currency address
|
|
uint8 private _decimalsStorage;
|
|
bool private _transferable;
|
|
|
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
constructor() {
|
|
_disableInitializers();
|
|
}
|
|
|
|
/**
|
|
* @notice Initialize the debt token (5-arg for backward compatibility; decimals=18, not transferable)
|
|
*/
|
|
function initialize(
|
|
string memory name,
|
|
string memory symbol,
|
|
address vault_,
|
|
address currency_,
|
|
address admin
|
|
) external initializer {
|
|
_initializeFull(name, symbol, vault_, currency_, admin, 18, false);
|
|
}
|
|
|
|
/**
|
|
* @notice Initialize with decimals and transferability (ERC-20; optionally DEX-transferable)
|
|
* @param decimals_ Token decimals (e.g. 6 for stablecoins; 0 = use 18)
|
|
* @param transferable_ If true, full ERC-20 transfers allowed (DEX-ready)
|
|
*/
|
|
function initializeFull(
|
|
string memory name,
|
|
string memory symbol,
|
|
address vault_,
|
|
address currency_,
|
|
address admin,
|
|
uint8 decimals_,
|
|
bool transferable_
|
|
) external initializer {
|
|
_initializeFull(name, symbol, vault_, currency_, admin, decimals_ > 0 ? decimals_ : 18, transferable_);
|
|
}
|
|
|
|
function _initializeFull(
|
|
string memory name,
|
|
string memory symbol,
|
|
address vault_,
|
|
address currency_,
|
|
address admin,
|
|
uint8 decimals_,
|
|
bool transferable_
|
|
) internal {
|
|
__ERC20_init(name, symbol);
|
|
__AccessControl_init();
|
|
__UUPSUpgradeable_init();
|
|
vault = vault_;
|
|
currency = currency_;
|
|
_decimalsStorage = decimals_;
|
|
_transferable = transferable_;
|
|
_grantRole(DEFAULT_ADMIN_ROLE, admin);
|
|
}
|
|
|
|
/**
|
|
* @notice Returns token decimals (matches underlying for DEX compatibility)
|
|
*/
|
|
function decimals() public view override returns (uint8) {
|
|
return _decimalsStorage;
|
|
}
|
|
|
|
function isTransferable() external view returns (bool) {
|
|
return _transferable;
|
|
}
|
|
|
|
/**
|
|
* @notice Mint debt tokens (only by vault)
|
|
* @param to Recipient address
|
|
* @param amount Amount to mint
|
|
*/
|
|
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
|
|
_mint(to, amount);
|
|
}
|
|
|
|
/**
|
|
* @notice Burn debt tokens (only by vault)
|
|
* @param from Source address
|
|
* @param amount Amount to burn
|
|
*/
|
|
function burn(address from, uint256 amount) external onlyRole(BURNER_ROLE) {
|
|
_burn(from, amount);
|
|
}
|
|
|
|
/**
|
|
* @notice Override transfer: when transferable, full ERC-20; else mint/burn/vault only
|
|
*/
|
|
function _update(address from, address to, uint256 amount) internal virtual override {
|
|
if (from == address(0) || to == address(0)) {
|
|
super._update(from, to, amount);
|
|
return;
|
|
}
|
|
if (_transferable) {
|
|
super._update(from, to, amount);
|
|
return;
|
|
}
|
|
if (from == vault || to == vault) {
|
|
super._update(from, to, amount);
|
|
return;
|
|
}
|
|
revert("DebtToken: transfers not allowed");
|
|
}
|
|
|
|
/**
|
|
* @notice Authorize upgrade (UUPS)
|
|
*/
|
|
function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {}
|
|
}
|