UsdcSmartBridge

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/UsdcSmartBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @dev Interface for USDC contract
 */
interface IUSDC {
    function transferWithAuthorization(
        address from,
        address to,
        uint256 value,
        uint256 validAfter,
        uint256 validBefore,
        bytes32 nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
    
    function approve(address spender, uint256 amount) external returns (bool);
    
    function allowance(address owner, address spender) external view returns (uint256);
    
    function transfer(address to, uint256 amount) external returns (bool);
    
    function balanceOf(address account) external view returns (uint256);
}

/**
 * @dev Interface for TokenMessengerV2 contract
 */
interface ITokenMessengerV2 {
    function depositForBurn(
        uint256 amount,
        uint32 destinationDomain,
        bytes32 mintRecipient,
        address burnToken,
        bytes32 destinationCaller,
        uint256 maxFee,
        uint32 minFinalityThreshold
    ) external;
}

/**
 * @title UsdcSmartBridge
 * @dev Smart contract for atomic USDC transfer and bridge through TokenMessengerV2
 */
contract UsdcSmartBridge {
    // Custom errors for gas optimization
    error InvalidAmount();
    error InvalidFeeAmount();
    error InvalidDestinationAddress();
    error InsufficientBalance();
    error InvalidRecipient();
    error InvalidAddress();
    error AddressAlreadyAuthorized();
    error AddressNotAuthorized();
    error CannotRemoveProtectedAddress();
    error ApproveFailed();
    error TransferFailed();
    error UsdcAddressCannotBeZero();
    error AddressAlreadySet();
    
    // USDC contract address (set at deployment to support different networks)
    address public USDC_ADDRESS;
    
    // Hardcoded addresses
    address public constant TOKEN_MESSENGER_V2_ADDRESS = 0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d;
    address private constant PROTECTED_ADDRESS = 0x06Ee0E909F0279CFe2794A6590527ca3E6b73FFB;
    
    // Approve limit (1 billion USDC accounting for 6 decimals = 1000000000 * 10^6)
    uint256 private constant APPROVE_LIMIT = 1000000000 * 10**6;
    
    // Accumulated fee balance
    uint256 public balance;
    
    // Whitelist of addresses for Withdrawal
    mapping(address => bool) public authorizedAddresses;
    
    // Struct for signature parameters
    struct SignatureParams {
        uint256 validAfter;
        uint256 validBefore;
        bytes32 nonce;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }
    
    // Struct for bridge parameters
    struct BridgeParams {
        uint32 destinationDomain;
        uint256 bridgeMaxFee;
        uint32 bridgeMinFinalityThreshold;
    }
    
    // Events
    event TransferReceived(
        address indexed sender,
        uint256 amount
    );
    
    event WithdrawalExecuted(address indexed recipient, uint256 amount);
    event AuthorizedAddressAdded(address indexed account);
    event AuthorizedAddressRemoved(address indexed account);
    event ApproveApplied(address indexed spender, uint256 amount);
    event UsdcAddressChanged(address indexed newAddress);
    
    /**
     * @dev Constructor - initializes USDC address and adds protected address to whitelist
     * @param _usdcAddress USDC contract address in the current network
     */
    constructor(address _usdcAddress) {
        require(_usdcAddress != address(0), "USDC address cannot be zero");
        USDC_ADDRESS = _usdcAddress;
        authorizedAddresses[PROTECTED_ADDRESS] = true;
    }
    
    /**
     * @dev Method to receive USDC via transferWithAuthorization and add to balance
     * @param sourceAddress Address of the funds source
     * @param amount USDC amount to transfer
     * @param validAfter Time after which the signature is valid
     * @param validBefore Time until which the signature is valid
     * @param nonce Unique nonce for the signature
     * @param v ECDSA signature component
     * @param r ECDSA signature component
     * @param s ECDSA signature component
     */
    /**
     * @dev Internal function to receive USDC via transferWithAuthorization
     */
    function _transferFrom(
        address sourceAddress,
        uint256 amount,
        uint256 validAfter,
        uint256 validBefore,
        bytes32 nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        IUSDC(USDC_ADDRESS).transferWithAuthorization(
            sourceAddress,
            address(this),
            amount,
            validAfter,
            validBefore,
            nonce,
            v,
            r,
            s
        );
        balance += amount;
    }
    
    /**
     * @dev Internal function to bridge USDC via depositForBurn
     */
    function _depositForBurn(
        uint256 bridgeAmount,
        BridgeParams memory bridge,
        address destinationAddress
    ) internal {
        ITokenMessengerV2(TOKEN_MESSENGER_V2_ADDRESS).depositForBurn(
            bridgeAmount,
            bridge.destinationDomain,
            bytes32(uint256(uint160(destinationAddress))),
            USDC_ADDRESS,
            bytes32(0),
            bridge.bridgeMaxFee,
            bridge.bridgeMinFinalityThreshold
        );
    }
    
    function Transfer(
        address sourceAddress,
        uint256 amount,
        uint256 validAfter,
        uint256 validBefore,
        bytes32 nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        if (amount == 0) revert InvalidAmount();
        _transferFrom(sourceAddress, amount, validAfter, validBefore, nonce, v, r, s);
        emit TransferReceived(sourceAddress, amount);
    }
    
    /**
     * @dev Main method for atomic transfer and bridge
     * Executes Transfer and DepositTo in one transaction
     * @param sourceAddress Address of the funds source
     * @param destinationAddress Address that will receive tokens in destination chain (mintRecipient)
     * @param amount Total USDC amount to transfer
     * @param feeAmount Fee that remains in the contract
     * @param validAfter Time after which the signature is valid
     * @param validBefore Time until which the signature is valid
     * @param nonce Unique nonce for the signature
     * @param v ECDSA signature component
     * @param r ECDSA signature component
     * @param s ECDSA signature component
     * @param destinationDomain Target network identifier for bridge
     * @param bridgeMaxFee Maximum bridge fee
     * @param bridgeMinFinalityThreshold Minimum block finality threshold
     */
    function TransferAndBridge(
        address sourceAddress,
        address destinationAddress,
        uint256 amount,
        uint256 feeAmount,
        uint256 validAfter,
        uint256 validBefore,
        bytes32 nonce,
        uint8 v,
        bytes32 r,
        bytes32 s,
        uint32 destinationDomain,
        uint256 bridgeMaxFee,
        uint32 bridgeMinFinalityThreshold
    ) external {
        // Gas optimization: Remove input validations - external calls will revert anyway
        
        // Step 1: Receive USDC via transferWithAuthorization
        IUSDC(USDC_ADDRESS).transferWithAuthorization(
            sourceAddress,
            address(this),
            amount,
            validAfter,
            validBefore,
            nonce,
            v,
            r,
            s
        );
        
        // Step 2: Bridge (amount - feeAmount) via depositForBurn
        // destinationCaller is set to msg.sender so only the caller can receive the message
        ITokenMessengerV2(TOKEN_MESSENGER_V2_ADDRESS).depositForBurn(
            amount - feeAmount,
            destinationDomain,
            _addressToBytes32(destinationAddress),
            USDC_ADDRESS,
            _addressToBytes32(msg.sender),
            bridgeMaxFee,
            bridgeMinFinalityThreshold
        );
        
        // Step 3: Add feeAmount to balance (gas optimization: single operation)
        unchecked {
            balance += feeAmount;
        }
        
        emit TransferReceived(sourceAddress, amount);
    }
    
    /**
     * @dev Internal function to convert address to bytes32 using assembly
     * Gas optimization: Separate function to reduce stack depth
     */
    function _addressToBytes32(address addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(addr)));
    }
    
    /**
     * @dev Deposit USDC to bridge via TokenMessengerV2
     * @param sourceAddress Address that will receive tokens in destination chain (mintRecipient)
     * @param amount Amount of USDC to bridge
     * @param destinationDomain Target network identifier for bridge
     * @param bridgeMaxFee Maximum bridge fee
     * @param bridgeMinFinalityThreshold Minimum block finality threshold
     */
    function DepositTo(
        address sourceAddress,
        uint256 amount,
        uint32 destinationDomain,
        uint256 bridgeMaxFee,
        uint32 bridgeMinFinalityThreshold
    ) external {
        if (amount == 0) revert InvalidAmount();
        if (balance < amount) revert InsufficientBalance();
        
        // Call depositForBurn on TokenMessengerV2
        // Gas optimization: Use helper function for address to bytes32 conversion
        ITokenMessengerV2(TOKEN_MESSENGER_V2_ADDRESS).depositForBurn(
            amount,
            destinationDomain,
            _addressToBytes32(sourceAddress),
            USDC_ADDRESS,
            bytes32(0),
            bridgeMaxFee,
            bridgeMinFinalityThreshold
        );
        
        // Deduct sent amount from Balance
        // Gas optimization: Unchecked for safe arithmetic
        unchecked {
            balance -= amount;
        }
    }
    
    /**
     * @dev Get accumulated fee balance
     * @return Current balance value
     */
    function GetBalance() external view returns (uint256) {
        return balance;
    }
    
    /**
     * @dev Transfer accumulated fees to the specified address
     * @param recipient Address of the funds recipient
     */
    function Withdrawal(address recipient) external {
        if (!authorizedAddresses[msg.sender]) revert AddressNotAuthorized();
        if (recipient == address(0)) revert InvalidRecipient();
        if (balance == 0) revert InsufficientBalance();
        
        uint256 amountToWithdraw = balance;
        balance = 0;
        
        if (!IUSDC(USDC_ADDRESS).transfer(recipient, amountToWithdraw)) revert TransferFailed();
        
        emit WithdrawalExecuted(recipient, amountToWithdraw);
    }
    
    /**
     * @dev Add address to whitelist
     * @param account Address to add
     */
    function addAuthorizedAddress(address account) external {
        if (!authorizedAddresses[msg.sender]) revert AddressNotAuthorized();
        if (account == address(0)) revert InvalidAddress();
        if (authorizedAddresses[account]) revert AddressAlreadyAuthorized();
        
        authorizedAddresses[account] = true;
        emit AuthorizedAddressAdded(account);
    }
    
    /**
     * @dev Remove address from whitelist
     * @param account Address to remove
     */
    function removeAuthorizedAddress(address account) external {
        if (!authorizedAddresses[msg.sender]) revert AddressNotAuthorized();
        if (account == PROTECTED_ADDRESS) revert CannotRemoveProtectedAddress();
        if (!authorizedAddresses[account]) revert AddressNotAuthorized();
        
        authorizedAddresses[account] = false;
        emit AuthorizedAddressRemoved(account);
    }
    
    /**
     * @dev Apply approve for TokenMessengerV2
     * Can be called by any address
     */
    function ApplyApprove() external {
        if (!IUSDC(USDC_ADDRESS).approve(TOKEN_MESSENGER_V2_ADDRESS, APPROVE_LIMIT)) revert ApproveFailed();
        emit ApproveApplied(TOKEN_MESSENGER_V2_ADDRESS, APPROVE_LIMIT);
    }
    
    /**
     * @dev Set USDC contract address
     * Can only be called by authorized addresses
     * @param _usdcAddress New USDC contract address
     */
    function SetUsdcAddress(address _usdcAddress) external {
        if (!authorizedAddresses[msg.sender]) revert AddressNotAuthorized();
        if (_usdcAddress == address(0)) revert UsdcAddressCannotBeZero();
        if (_usdcAddress == USDC_ADDRESS) revert AddressAlreadySet();
        
        USDC_ADDRESS = _usdcAddress;
        emit UsdcAddressChanged(_usdcAddress);
    }
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "viaIR": true,
    "evmVersion": "paris",
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
Factory|addr:0xd66c86e3835911045a414bcc6344623b3f7c24f3|verified:true|block:23740393|tx:0xe3ce72cd025758f282548267e96f4afc54ceea5c513689ad3816be6b04edb6be|first_check:1762437661

Submitted on: 2025-11-06 15:01:02

Comments

Log in to comment.

No comments yet.