Files
smom-dbis-138/contracts/tokens/CompliantFiatToken.sol
defiQUG 2a4753eb2d feat: restore operator WIP — PMM JSON sync entrypoint, dotenv RPC trim + secrets, pool env alignment
- Resolve stash: merge load_deployment_env path with secure-secrets and CR/LF RPC strip
- create-pmm-full-mesh-chain138.sh delegates to sync-chain138-pmm-pools-from-json.sh
- env.additions.example: canonical PMM pool defaults (cUSDT/USDT per crosscheck)
- Include Chain138 scripts, official mirror deploy scaffolding, and prior staged changes

Made-with: Cursor
2026-03-27 19:02:30 -07:00

103 lines
3.4 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "../compliance/LegallyCompliantBase.sol";
/**
* @title CompliantFiatToken
* @notice Generic ISO-4217 compliant fiat/commodity token (ERC-20, DEX-ready)
* @dev Use for cEURC, cGBPC, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT, etc.
* Full ERC-20 for DEX liquidity pools; inherits LegallyCompliantBase.
*
* XAU (gold) invariant — enforced by policy and integrators, not by ERC-20 math:
* When `currencyCode()` is `"XAU"` (e.g. cXAUC, cXAUT), **one full token** means
* **exactly one troy ounce** of fine gold: balances and `mint`/`transfer` amounts use
* `10 ** decimals()` base units per troy ounce (with 6 decimals, `1_000_000` base = 1 oz).
* Fiat codes (USD, EUR, …) use one full token as one unit of that currency at `decimals`.
*/
contract CompliantFiatToken is ERC20, Pausable, Ownable, LegallyCompliantBase {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint8 private immutable _decimalsStorage;
string private _currencyCode;
/**
* @notice Constructor
* @param name_ Token name (e.g. "Euro Coin (Compliant)")
* @param symbol_ Token symbol (e.g. "cEURC")
* @param decimals_ Token decimals (e.g. 6)
* @param currencyCode_ ISO-4217 code (e.g. "EUR")
* @param initialOwner Owner address
* @param admin Compliance admin (DEFAULT_ADMIN_ROLE)
* @param initialSupply Initial supply to mint to deployer
*/
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
string memory currencyCode_,
address initialOwner,
address admin,
uint256 initialSupply
)
ERC20(name_, symbol_)
Ownable(initialOwner)
LegallyCompliantBase(admin)
{
_decimalsStorage = decimals_;
_currencyCode = currencyCode_;
_grantRole(MINTER_ROLE, initialOwner);
if (initialSupply > 0) {
_mint(msg.sender, initialSupply);
}
}
function decimals() public view override returns (uint8) {
return _decimalsStorage;
}
function currencyCode() external view returns (string memory) {
return _currencyCode;
}
/**
* @notice Internal transfer with compliance tracking
*/
function _update(
address from,
address to,
uint256 amount
) internal override whenNotPaused {
super._update(from, to, amount);
if (from != address(0) && to != address(0)) {
bytes32 legalRefHash = _generateLegalReferenceHash(
from,
to,
amount,
abi.encodePacked(symbol(), " Transfer")
);
emit ValueTransferDeclared(from, to, amount, legalRefHash);
}
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
/// @notice Mint (DBIS Rail: grant MINTER_ROLE only to DBIS_GRU_MintController; revoke from others)
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
function burn(uint256 amount) public {
_burn(msg.sender, amount);
}
}