Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m3s
CI/CD Pipeline / Security Scanning (push) Successful in 2m18s
CI/CD Pipeline / Lint and Format (push) Failing after 34s
CI/CD Pipeline / Terraform Validation (push) Failing after 20s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 22s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 40s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 49s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 21s
Validation / validate-genesis (push) Successful in 25s
Validation / validate-terraform (push) Failing after 21s
Validation / validate-kubernetes (push) Failing after 8s
Validation / validate-smart-contracts (push) Failing after 8s
Validation / validate-security (push) Failing after 1m11s
Validation / validate-documentation (push) Failing after 14s
Verify Deployment / Verify Deployment (push) Failing after 45s
Ship AddressActivityRegistry V1/V2, ISO20022IntakeGateway, Chain138ParticipantSurface, checkpoint hub contracts, checkpoint-core package, aggregator/indexer/sdk services, relay profile guards, M00 diamond bridge facet, and OMNL compliance contracts. Co-authored-by: Cursor <cursoragent@cursor.com>
163 lines
6.0 KiB
Solidity
163 lines
6.0 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "forge-std/Test.sol";
|
|
import "../../contracts/rwa/RWAToken.sol";
|
|
import "../../contracts/rwa/RWATokenRegistry.sol";
|
|
import "../../contracts/rwa/RWATokenFactory.sol";
|
|
import "../../contracts/rwa/IRWATokenFactory.sol";
|
|
import "../../contracts/rwa/IRWAToken.sol";
|
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
import "../../contracts/rwa/RWATokenInterfaces.sol";
|
|
/// @dev Minimal UAR stub so rwa-scoped `forge test` does not pull the full upgradeable registry tree.
|
|
contract MockUniversalAssetRegistry {
|
|
bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");
|
|
mapping(address => bool) private _active;
|
|
|
|
function grantRole(bytes32, address) external {}
|
|
|
|
function registerRWAIndexAsset(
|
|
address tokenAddress,
|
|
string calldata,
|
|
string calldata,
|
|
uint8,
|
|
string calldata
|
|
) external {
|
|
_active[tokenAddress] = true;
|
|
}
|
|
|
|
function isAssetActive(address token) external view returns (bool) {
|
|
return _active[token];
|
|
}
|
|
}
|
|
|
|
contract RWATokenFactoryTest is Test {
|
|
bytes32 internal constant METHODOLOGY_HASH =
|
|
0x6b6e599d0ba31d048b49302e263a12f0c59502f67a35100ad5c65b503b1d4b82;
|
|
|
|
RWATokenRegistry public registry;
|
|
RWATokenFactory public factory;
|
|
MockUniversalAssetRegistry public uar;
|
|
|
|
address public admin = address(0xA11CE);
|
|
address public owner = address(0xB0B);
|
|
address public publisher = address(0xC0DE);
|
|
|
|
function setUp() public {
|
|
vm.startPrank(admin);
|
|
uar = new MockUniversalAssetRegistry();
|
|
registry = new RWATokenRegistry(admin);
|
|
factory = new RWATokenFactory(admin, address(registry), address(uar));
|
|
registry.grantRole(registry.REGISTRAR_ROLE(), address(factory));
|
|
uar.grantRole(uar.REGISTRAR_ROLE(), address(factory));
|
|
factory.grantRole(factory.DEPLOYER_ROLE(), admin);
|
|
vm.stopPrank();
|
|
}
|
|
|
|
function test_deployLiXAU_registersInRegistryAndUAR() public {
|
|
vm.prank(admin);
|
|
address token = factory.deployRWAIndex(
|
|
IRWATokenFactory.RWAProductConfig({
|
|
indexTicker: "LiXAU",
|
|
name: "XAU Liquidity Index (M00)",
|
|
symbol: "LiXAU",
|
|
decimals: 6,
|
|
assetClass: "Commodities",
|
|
assetGroup: "Precious Metals",
|
|
instrumentType: "Commodity Index",
|
|
underlyingAsset: "Gold",
|
|
gruLayer: "M00",
|
|
jurisdiction: "International",
|
|
initialOwner: owner,
|
|
complianceAdmin: admin,
|
|
indexPublisher: publisher,
|
|
initialIndexValue: 1_050_000,
|
|
initialSupply: 0,
|
|
methodologyDocumentHash: METHODOLOGY_HASH,
|
|
registerInUniversalAssetRegistry: true
|
|
})
|
|
);
|
|
|
|
assertEq(IRWAToken(token).methodologyDocumentHash(), METHODOLOGY_HASH);
|
|
assertTrue(registry.isRegistered("LiXAU"));
|
|
assertEq(registry.getToken("LiXAU"), token);
|
|
|
|
IRWAToken rwa = IRWAToken(token);
|
|
assertTrue(rwa.isRwaIndex());
|
|
assertFalse(rwa.isEmoney());
|
|
assertEq(rwa.indexValue(), 1_050_000);
|
|
assertEq(keccak256(bytes(rwa.indexTicker())), keccak256("LiXAU"));
|
|
|
|
assertTrue(uar.isAssetActive(token));
|
|
}
|
|
|
|
function test_revert_duplicateTicker() public {
|
|
IRWATokenFactory.RWAProductConfig memory cfg = _liXauConfig();
|
|
vm.prank(admin);
|
|
factory.deployRWAIndex(cfg);
|
|
vm.prank(admin);
|
|
vm.expectRevert("RWATokenFactory: already registered");
|
|
factory.deployRWAIndex(cfg);
|
|
}
|
|
|
|
function test_revert_invalidTicker() public {
|
|
IRWATokenFactory.RWAProductConfig memory cfg = _liXauConfig();
|
|
cfg.indexTicker = "cUSDT";
|
|
vm.prank(admin);
|
|
vm.expectRevert();
|
|
factory.deployRWAIndex(cfg);
|
|
}
|
|
|
|
function test_indexPublisherUpdatesValue() public {
|
|
vm.prank(admin);
|
|
address token = factory.deployRWAIndex(_liXauConfig());
|
|
vm.prank(publisher);
|
|
IRWAToken(token).updateIndexValue(2_000_000);
|
|
assertEq(IRWAToken(token).indexValue(), 2_000_000);
|
|
}
|
|
|
|
function test_eip165_and_eip712_domain() public {
|
|
vm.prank(admin);
|
|
address token = factory.deployRWAIndex(_liXauConfig());
|
|
IRWAToken165 rwa = IRWAToken165(token);
|
|
assertTrue(rwa.supportsInterface(type(IRWAToken).interfaceId));
|
|
assertTrue(rwa.supportsInterface(type(IERC20).interfaceId));
|
|
assertTrue(rwa.supportsInterface(type(IERC20Metadata).interfaceId));
|
|
assertEq(rwa.eip20Version(), "1.0.0");
|
|
assertTrue(rwa.eip712DomainSeparator() != bytes32(0));
|
|
bytes32 h = rwa.hashIndexValueAttestation("LiXAU", 1_100_000, 1, block.timestamp + 3600);
|
|
assertTrue(h != bytes32(0));
|
|
}
|
|
|
|
function test_revert_zeroMethodologyHash() public {
|
|
IRWATokenFactory.RWAProductConfig memory cfg = _liXauConfig();
|
|
cfg.methodologyDocumentHash = bytes32(0);
|
|
vm.prank(admin);
|
|
vm.expectRevert("RWATokenFactory: methodology");
|
|
factory.deployRWAIndex(cfg);
|
|
}
|
|
|
|
function _liXauConfig() internal view returns (IRWATokenFactory.RWAProductConfig memory) {
|
|
return IRWATokenFactory.RWAProductConfig({
|
|
indexTicker: "LiXAU",
|
|
name: "XAU Liquidity Index (M00)",
|
|
symbol: "LiXAU",
|
|
decimals: 6,
|
|
assetClass: "Commodities",
|
|
assetGroup: "Precious Metals",
|
|
instrumentType: "Commodity Index",
|
|
underlyingAsset: "Gold",
|
|
gruLayer: "M00",
|
|
jurisdiction: "International",
|
|
initialOwner: owner,
|
|
complianceAdmin: admin,
|
|
indexPublisher: publisher,
|
|
initialIndexValue: 1_000_000,
|
|
initialSupply: 0,
|
|
methodologyDocumentHash: METHODOLOGY_HASH,
|
|
registerInUniversalAssetRegistry: false
|
|
});
|
|
}
|
|
}
|