> For the complete documentation index, see [llms.txt](https://docs.xft.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xft.finance/idn/technical/address-facilities/xftroutingfactoryv6.md).

# 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"))];
    }
}

```
