Files
smom-dbis-138/contracts/emoney/TokenFactory138.sol
defiQUG cad927816e
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m20s
CI/CD Pipeline / Security Scanning (push) Successful in 2m48s
CI/CD Pipeline / Lint and Format (push) Failing after 47s
CI/CD Pipeline / Terraform Validation (push) Failing after 28s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 30s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 44s
Validation / validate-genesis (push) Successful in 37s
Validation / validate-terraform (push) Failing after 42s
Validation / validate-kubernetes (push) Failing after 12s
Validation / validate-smart-contracts (push) Failing after 16m44s
Validation / validate-security (push) Failing after 20s
Validation / validate-documentation (push) Failing after 19s
Verify Deployment / Verify Deployment (push) Failing after 1m21s
fix(token-list): align cUSDC_V2/cUSDT_V2 logoURI with registry policy
Use dedicated cusdc_v2/cusdt_v2 SVG paths so GRU token alignment validation passes.
2026-06-30 15:31:55 -07:00

120 lines
4.5 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "./interfaces/ITokenFactory138.sol";
import "./interfaces/IeMoneyToken.sol";
import "./interfaces/IPolicyManager.sol";
import "./eMoneyToken.sol";
import "./errors/FactoryErrors.sol";
import "./errors/RegistryErrors.sol";
/**
* @title TokenFactory138
* @notice Factory for deploying new eMoneyToken instances as UUPS upgradeable proxies
* @dev Deploys ERC1967Proxy instances pointing to a shared implementation contract.
* Each token is configured with its issuer, lien mode, bridge settings, and registered by code hash.
*/
contract TokenFactory138 is ITokenFactory138, AccessControl {
bytes32 public constant TOKEN_DEPLOYER_ROLE = keccak256("TOKEN_DEPLOYER_ROLE");
address public immutable implementation;
address public immutable policyManager;
address public immutable debtRegistry;
address public immutable complianceRegistry;
mapping(bytes32 => address) private _tokensByCodeHash;
/**
* @notice Initializes the factory with registry and implementation addresses
* @param admin Address that will receive DEFAULT_ADMIN_ROLE
* @param implementation_ Address of the eMoneyToken implementation contract (used for all proxies)
* @param policyManager_ Address of PolicyManager contract
* @param debtRegistry_ Address of DebtRegistry contract
* @param complianceRegistry_ Address of ComplianceRegistry contract
*/
constructor(
address admin,
address implementation_,
address policyManager_,
address debtRegistry_,
address complianceRegistry_
) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
implementation = implementation_;
policyManager = policyManager_;
debtRegistry = debtRegistry_;
complianceRegistry = complianceRegistry_;
}
/**
* @notice Deploys a new eMoneyToken instance as a UUPS proxy
* @dev Requires TOKEN_DEPLOYER_ROLE. Creates ERC1967Proxy, initializes token, and configures PolicyManager.
* @param name Token name (e.g., "USD eMoney")
* @param symbol Token symbol (e.g., "USDe")
* @param config Token configuration (decimals, issuer, lien mode, bridge settings)
* @return token Address of the deployed proxy token contract
*/
function deployToken(
string calldata name,
string calldata symbol,
TokenConfig calldata config
) external override onlyRole(TOKEN_DEPLOYER_ROLE) returns (address token) {
if (config.issuer == address(0)) revert ZeroIssuer();
if (config.defaultLienMode != 1 && config.defaultLienMode != 2) {
revert PolicyInvalidLienMode(config.defaultLienMode);
}
// Deploy UUPS proxy
bytes memory initData = abi.encodeWithSelector(
IeMoneyToken.initialize.selector,
name,
symbol,
config.decimals,
config.issuer,
policyManager,
debtRegistry,
complianceRegistry
);
ERC1967Proxy proxy = new ERC1967Proxy(implementation, initData);
token = address(proxy);
// Configure token in PolicyManager
IPolicyManager(policyManager).setLienMode(token, config.defaultLienMode);
IPolicyManager(policyManager).setBridgeOnly(token, config.bridgeOnly);
if (config.bridge != address(0)) {
IPolicyManager(policyManager).setBridge(token, config.bridge);
}
// Register token by code hash (deterministic based on deployment params)
// Include token address, timestamp, and block number to prevent collisions
bytes32 codeHash = keccak256(abi.encodePacked(name, symbol, config.issuer, token, block.timestamp, block.number));
_tokensByCodeHash[codeHash] = token;
emit TokenDeployed(
token,
codeHash,
name,
symbol,
config.decimals,
config.issuer,
config.defaultLienMode,
config.bridgeOnly,
config.bridge
);
}
/**
* @notice Returns the token address for a given code hash
* @dev Code hash is generated deterministically during token deployment
* @param codeHash The code hash to lookup
* @return Token address (zero address if not found)
*/
function tokenByCodeHash(bytes32 codeHash) external view override returns (address) {
return _tokensByCodeHash[codeHash];
}
}