# XFTRoutingFactoryV6

CORE FUNCTIONS

* Single operator&#x20;
* Single whitelisted token set on deployment via constructor
* More tokens can be added to token whitelist map after deployment
* Rail/wallet map is added on construction
* More rails can be added after deployment

MAPS

* Whitelisted tokens

```
NCUSD 0x53e84E18A2885463f791d3E295c63C82a79a2A67
FLUSD 0xe9f8063c0e987a487D886A021778379B52237A5f
PAUSD 0x47efCE54648139BfC65C0313c59810f592e55B3d
```

* Rails to create wallets to

```solidity
mapping(bytes32 => address) private routingToWallet;
mapping(bytes32 => address) private ibanToWallet;
mapping(bytes32 => address) private swiftToWallet;
mapping(bytes32 => address) public cikToWallet;
mapping(bytes32 => address) public leiToWallet;
mapping(bytes32 => address) private fedNowToWallet;
mapping(bytes32 => address) private fedwireToWallet;
mapping(bytes32 => address) private chipsToWallet;
mapping(bytes32 => address) private visaToWallet;
mapping(bytes32 => address) private sunpassToWallet;
mapping(bytes32 => address) private actcardToWallet;
```

COUNTERPARTIES

contracts/XFTRoutingFactoryV6.sol:XFTRoutingFactoryV6\
Operator 0x2f572059DbC598C8acfeA4AF06FE4f7669D1b3b1\
NCUSD 0x53e84E18A2885463f791d3E295c63C82a79a2A67\
FLUSD 0xe9f8063c0e987a487D886A021778379B52237A5f\
PAUSD 0x47efCE54648139BfC65C0313c59810f592e55B3d

RESOURCES

contracts\XFTRoutingFactoryV5.sol:IERC20

```javascript
interface IERC20 {
    function mint(address to, uint256 amount) external;
    function burn(address from, uint256 amount) external;
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}
```

NC Quick Pass <https://www.ncquickpass.com/>

NCUSD 0x53e84E18A2885463f791d3E295c63C82a79a2A67

contracts\XFTRoutingFactoryV5.sol

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IERC20 {
    function mint(address to, uint256 amount) external;
    function burn(address from, uint256 amount) external;
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

contract RoutingWallet {
    address public factory;
    address public owner;

    event WalletTransfer(address indexed token, address indexed to, uint256 amount);

    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    modifier onlyOwnerOrFactory() {
        require(msg.sender == owner || msg.sender == factory, "not authorized");
        _;
    }

    constructor(address _owner) {
        factory = msg.sender;
        owner = _owner;
    }

    function transfer(address token, address to, uint256 amount) external onlyOwnerOrFactory {
        require(IERC20(token).transfer(to, amount), "transfer failed");
        emit WalletTransfer(token, to, amount);
    }

    function balance(address token) external view returns (uint256) {
        return IERC20(token).balanceOf(address(this));
    }
}

contract XFTRoutingFactoryV5 {
    IERC20 public immutable token;
    address public operator;

    mapping(bytes32 => address) private routingToWallet;
    mapping(bytes32 => address) private ibanToWallet;
    mapping(bytes32 => address) private swiftToWallet;
    mapping(bytes32 => address) public cikToWallet;
    mapping(bytes32 => address) public leiToWallet;
    mapping(bytes32 => address) private fedNowToWallet;
    mapping(bytes32 => address) private fedwireToWallet;
    mapping(bytes32 => address) private chipsToWallet;
    mapping(bytes32 => address) private visaToWallet;
    mapping(bytes32 => address) private sunpassToWallet;
    mapping(bytes32 => address) private actcardToWallet;

    struct WalletRec { string rail; string id; address wallet; }

    WalletRec[] private _allWallets;
    mapping(bytes32 => WalletRec[]) private _walletsByRail;

    function _record(string memory rail, string memory id, address wallet) internal {
        _allWallets.push(WalletRec(rail, id, wallet));
        _walletsByRail[keccak256(bytes(rail))].push(WalletRec(rail, id, wallet));
    }

    event DeployWallet(string idType, string idValue, address wallet);
    event Mint(string idType, string idValue, address wallet, uint256 amount);
    event Burn(string idType, string idValue, address wallet, uint256 amount);
    event Transfer(string idType, string fromId, string toId, address fromWallet, address toWallet, uint256 amount);

    error NotOperator();
    error WalletExists();
    error WalletNotFound();

    modifier onlyOp() {
        if (msg.sender != operator) revert NotOperator();
        _;
    }

    constructor(address _token) {
        token = IERC20(_token);
        operator = msg.sender;
    }

    function _salt(string memory id) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(id));
    }

    function _predict(bytes32 salt) internal view returns (address) {
        return address(uint160(uint256(keccak256(
            abi.encodePacked(
                bytes1(0xff),
                address(this),
                salt,
                keccak256(abi.encodePacked(type(RoutingWallet).creationCode, abi.encode(operator)))
            )
        ))));
    }

    // ---------------- ROUTING ----------------
    function predictRouting(string memory routing) public view returns (address) {
        return _predict(_salt(routing));
    }
    function deployRoutingWallet(string memory routing) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(routing);
        if (routingToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        routingToWallet[salt] = wallet;
        _record("ROUTING", routing, wallet);
        emit DeployWallet("ROUTING", routing, wallet);
    }
    function mintToRouting(string memory routing, uint256 amt) external onlyOp {
        bytes32 salt = _salt(routing);
        address wallet = routingToWallet[salt];
        if (wallet == address(0)) wallet = deployRoutingWallet(routing);
        token.mint(wallet, amt);
        emit Mint("ROUTING", routing, wallet, amt);
    }
    function burnFromRouting(string memory routing, uint256 amt) external onlyOp {
        address wallet = routingToWallet[_salt(routing)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("ROUTING", routing, wallet, amt);
    }
    function getRoutingWallet(string memory routing) external view returns (address) {
        return routingToWallet[_salt(routing)];
    }

    // ---------------- IBAN ----------------
    function predictIBAN(string memory iban) public view returns (address) {
        return _predict(_salt(iban));
    }
    function deployIBANWallet(string memory iban) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(iban);
        if (ibanToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        ibanToWallet[salt] = wallet;
        _record("IBAN", iban, wallet);
        emit DeployWallet("IBAN", iban, wallet);
    }
    function mintToIBAN(string memory iban, uint256 amt) external onlyOp {
        bytes32 salt = _salt(iban);
        address wallet = ibanToWallet[salt];
        if (wallet == address(0)) wallet = deployIBANWallet(iban);
        token.mint(wallet, amt);
        emit Mint("IBAN", iban, wallet, amt);
    }
    function burnFromIBAN(string memory iban, uint256 amt) external onlyOp {
        address wallet = ibanToWallet[_salt(iban)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("IBAN", iban, wallet, amt);
    }
    function getIBANWallet(string memory iban) external view returns (address) {
        return ibanToWallet[_salt(iban)];
    }

    // ---------------- SWIFT/BIC ----------------
    function predictSWIFT(string memory swift) public view returns (address) {
        return _predict(_salt(swift));
    }
    function deploySWIFTWallet(string memory swift) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(swift);
        if (swiftToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        swiftToWallet[salt] = wallet;
        _record("SWIFT", swift, wallet);
        emit DeployWallet("SWIFT", swift, wallet);
    }
    function mintToSWIFT(string memory swift, uint256 amt) external onlyOp {
        bytes32 salt = _salt(swift);
        address wallet = swiftToWallet[salt];
        if (wallet == address(0)) wallet = deploySWIFTWallet(swift);
        token.mint(wallet, amt);
        emit Mint("SWIFT", swift, wallet, amt);
    }
    function burnFromSWIFT(string memory swift, uint256 amt) external onlyOp {
        address wallet = swiftToWallet[_salt(swift)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("SWIFT", swift, wallet, amt);
    }
    function getSWIFTWallet(string memory swift) external view returns (address) {
        return swiftToWallet[_salt(swift)];
    }

    // ---------------- CIK ----------------
    function predictCIK(string memory cik) public view returns (address) {
        return _predict(_salt(cik));
    }
    function deployCIKWallet(string memory cik) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(cik);
        if (cikToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        cikToWallet[salt] = wallet;
        _record("CIK", cik, wallet);
        emit DeployWallet("CIK", cik, wallet);
    }
    function mintToCIK(string memory cik, uint256 amt) external onlyOp {
        bytes32 salt = _salt(cik);
        address wallet = cikToWallet[salt];
        if (wallet == address(0)) wallet = deployCIKWallet(cik);
        token.mint(wallet, amt);
        emit Mint("CIK", cik, wallet, amt);
    }
    function burnFromCIK(string memory cik, uint256 amt) external onlyOp {
        address wallet = cikToWallet[_salt(cik)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("CIK", cik, wallet, amt);
    }
    function getCIKWallet(string memory cik) external view returns (address) {
        return cikToWallet[_salt(cik)];
    }

    // ---------------- LEI ----------------
    function predictLEI(string memory lei) public view returns (address) {
        return _predict(_salt(lei));
    }
    function deployLEIWallet(string memory lei) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(lei);
        if (leiToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        leiToWallet[salt] = wallet;
        _record("LEI", lei, wallet);
        emit DeployWallet("LEI", lei, wallet);
    }
    function mintToLEI(string memory lei, uint256 amt) external onlyOp {
        bytes32 salt = _salt(lei);
        address wallet = leiToWallet[salt];
        if (wallet == address(0)) wallet = deployLEIWallet(lei);
        token.mint(wallet, amt);
        emit Mint("LEI", lei, wallet, amt);
    }
    function burnFromLEI(string memory lei, uint256 amt) external onlyOp {
        address wallet = leiToWallet[_salt(lei)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("LEI", lei, wallet, amt);
    }
    function getLEIWallet(string memory lei) external view returns (address) {
        return leiToWallet[_salt(lei)];
    }

    // ---------------- FEDNOW ----------------
    function predictFEDNOW(string memory fednow) public view returns (address) {
        return _predict(_salt(fednow));
    }
    function deployFEDNOWWallet(string memory fednow) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(fednow);
        if (fedNowToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        fedNowToWallet[salt] = wallet;
        _record("FEDNOW", fednow, wallet);
        emit DeployWallet("FEDNOW", fednow, wallet);
    }
    function mintToFEDNOW(string memory fednow, uint256 amt) external onlyOp {
        bytes32 salt = _salt(fednow);
        address wallet = fedNowToWallet[salt];
        if (wallet == address(0)) wallet = deployFEDNOWWallet(fednow);
        token.mint(wallet, amt);
        emit Mint("FEDNOW", fednow, wallet, amt);
    }
    function burnFromFEDNOW(string memory fednow, uint256 amt) external onlyOp {
        address wallet = fedNowToWallet[_salt(fednow)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("FEDNOW", fednow, wallet, amt);
    }
    function getFEDNOWWallet(string memory fednow) external view returns (address) {
        return fedNowToWallet[_salt(fednow)];
    }

    // ---------------- FEDWIRE ----------------
    function predictFEDWIRE(string memory fedwire) public view returns (address) {
        return _predict(_salt(fedwire));
    }
    function deployFEDWIREWallet(string memory fedwire) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(fedwire);
        if (fedwireToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        fedwireToWallet[salt] = wallet;
        _record("FEDWIRE", fedwire, wallet);
        emit DeployWallet("FEDWIRE", fedwire, wallet);
    }
    function mintToFEDWIRE(string memory fedwire, uint256 amt) external onlyOp {
        bytes32 salt = _salt(fedwire);
        address wallet = fedwireToWallet[salt];
        if (wallet == address(0)) wallet = deployFEDWIREWallet(fedwire);
        token.mint(wallet, amt);
        emit Mint("FEDWIRE", fedwire, wallet, amt);
    }
    function burnFromFEDWIRE(string memory fedwire, uint256 amt) external onlyOp {
        address wallet = fedwireToWallet[_salt(fedwire)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("FEDWIRE", fedwire, wallet, amt);
    }
    function getFEDWIREWallet(string memory fedwire) external view returns (address) {
        return fedwireToWallet[_salt(fedwire)];
    }

    // ---------------- CHIPS ----------------
    function predictCHIPS(string memory chips) public view returns (address) {
        return _predict(_salt(chips));
    }
    function deployCHIPSWallet(string memory chips) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(chips);
        if (chipsToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        chipsToWallet[salt] = wallet;
        _record("CHIPS", chips, wallet);
        emit DeployWallet("CHIPS", chips, wallet);
    }
    function mintToCHIPS(string memory chips, uint256 amt) external onlyOp {
        bytes32 salt = _salt(chips);
        address wallet = chipsToWallet[salt];
        if (wallet == address(0)) wallet = deployCHIPSWallet(chips);
        token.mint(wallet, amt);
        emit Mint("CHIPS", chips, wallet, amt);
    }
    function burnFromCHIPS(string memory chips, uint256 amt) external onlyOp {
        address wallet = chipsToWallet[_salt(chips)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("CHIPS", chips, wallet, amt);
    }
    function getCHIPSWallet(string memory chips) external view returns (address) {
        return chipsToWallet[_salt(chips)];
    }

    // ---------------- VISA ----------------
    function predictVISA(string memory visa) public view returns (address) {
        return _predict(_salt(visa));
    }
    function deployVISAWallet(string memory pan) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(pan);
        if (visaToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        visaToWallet[salt] = wallet;
        _record("VISA", pan, wallet);
        emit DeployWallet("VISA", pan, wallet);
    }
    function mintToVISA(string memory visa, uint256 amt) external onlyOp {
        bytes32 salt = _salt(visa);
        address wallet = visaToWallet[salt];
        if (wallet == address(0)) wallet = deployVISAWallet(visa);
        token.mint(wallet, amt);
        emit Mint("VISA", visa, wallet, amt);
    }
    function burnFromVISA(string memory visa, uint256 amt) external onlyOp {
        address wallet = visaToWallet[_salt(visa)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("VISA", visa, wallet, amt);
    }
    function getVISAWallet(string memory visa) external view returns (address) {
        return visaToWallet[_salt(visa)];
    }
    function transferVISA(
        string memory fromVisa,
        string memory toVisa, 
        uint256 amount
    ) external onlyOp {
        address fromWallet = visaToWallet[_salt(fromVisa)];
        address toWallet = visaToWallet[_salt(toVisa)];
        
        if (fromWallet == address(0)) revert WalletNotFound();
        if (toWallet == address(0)) revert WalletNotFound();
        
        RoutingWallet(fromWallet).transfer(address(token), toWallet, amount);
        emit Transfer("VISA", fromVisa, toVisa, fromWallet, toWallet, amount);
    }

    // ---------------- SUNPASS ----------------
    function predictSUNPASS(string memory sunpass) public view returns (address) {
        return _predict(_salt(sunpass));
    }
    function deploySUNPASSWallet(string memory pan) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(pan);
        if (sunpassToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        sunpassToWallet[salt] = wallet;
        _record("SUNPASS", pan, wallet);
        emit DeployWallet("SUNPASS", pan, wallet);
    }
    function mintToSUNPASS(string memory sunpass, uint256 amt) external onlyOp {
        bytes32 salt = _salt(sunpass);
        address wallet = sunpassToWallet[salt];
        if (wallet == address(0)) wallet = deploySUNPASSWallet(sunpass);
        token.mint(wallet, amt);
        emit Mint("SUNPASS", sunpass, wallet, amt);
    }
    function burnFromSUNPASS(string memory sunpass, uint256 amt) external onlyOp {
        address wallet = sunpassToWallet[_salt(sunpass)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("SUNPASS", sunpass, wallet, amt);
    }
    function getSUNPASSWallet(string memory sunpass) external view returns (address) {
        return sunpassToWallet[_salt(sunpass)];
    }
    function transferSUNPASS(
        string memory fromSunPass,
        string memory toSunPass, 
        uint256 amount
    ) external onlyOp {
        address fromWallet = sunpassToWallet[_salt(fromSunPass)];
        address toWallet = sunpassToWallet[_salt(toSunPass)];
        
        if (fromWallet == address(0)) revert WalletNotFound();
        if (toWallet == address(0)) revert WalletNotFound();
        
        RoutingWallet(fromWallet).transfer(address(token), toWallet, amount);
        emit Transfer("SUNPASS", fromSunPass, toSunPass, fromWallet, toWallet, amount);
    }

    // ---------------- ACT CARD ----------------
    function predictACTCARD(string memory actcard) public view returns (address) {
        return _predict(_salt(actcard));
    }
    function deployACTCARDWallet(string memory pan) public onlyOp returns (address wallet) {
        bytes32 salt = _salt(pan);
        if (actcardToWallet[salt] != address(0)) revert WalletExists();
        wallet = address(new RoutingWallet{salt: salt}(operator));
        actcardToWallet[salt] = wallet;
        _record("ACTCARD", pan, wallet);
        emit DeployWallet("ACTCARD", pan, wallet);
    }
    function mintToACTCARD(string memory actcard, uint256 amt) external onlyOp {
        bytes32 salt = _salt(actcard);
        address wallet = actcardToWallet[salt];
        if (wallet == address(0)) wallet = deployACTCARDWallet(actcard);
        token.mint(wallet, amt);
        emit Mint("ACTCARD", actcard, wallet, amt);
    }
    function burnFromACTCARD(string memory actcard, uint256 amt) external onlyOp {
        address wallet = actcardToWallet[_salt(actcard)];
        if (wallet == address(0)) revert WalletNotFound();
        token.burn(wallet, amt);
        emit Burn("ACTCARD", actcard, wallet, amt);
    }
    function getACTCARDWallet(string memory actcard) external view returns (address) {
        return actcardToWallet[_salt(actcard)];
    }
    function transferACTCARD(
        string memory fromACTCard,
        string memory toACTCard, 
        uint256 amount
    ) external onlyOp {
        address fromWallet = actcardToWallet[_salt(fromACTCard)];
        address toWallet = actcardToWallet[_salt(toACTCard)];
        
        if (fromWallet == address(0)) revert WalletNotFound();
        if (toWallet == address(0)) revert WalletNotFound();
        
        RoutingWallet(fromWallet).transfer(address(token), toWallet, amount);
        emit Transfer("ACTCARD", fromACTCard, toACTCard, fromWallet, toWallet, amount);
    }
    // ---------------- WALLETS ----------------
    function getAllWallets() external view returns (WalletRec[] memory) {
        return _allWallets;
    }
    function getWalletsByRail(string memory rail) external view returns (WalletRec[] memory) {
        return _walletsByRail[keccak256(bytes(rail))];
    }
    function getVisaWallets() external view returns (WalletRec[] memory) {
        return _walletsByRail[keccak256(bytes("VISA"))];
    }
    function getSunPassWallets() external view returns (WalletRec[] memory) {
        return _walletsByRail[keccak256(bytes("SUNPASS"))];
    }
    function getACTCardWallets() external view returns (WalletRec[] memory) {
        return _walletsByRail[keccak256(bytes("ACTCARD"))];
    }
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xft.finance/idn/technical/address-facilities/xftroutingfactoryv6.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
