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"
]
}
}
}
}}
Submitted on: 2025-11-06 15:01:02
Comments
Log in to comment.
No comments yet.