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.0;
/**
* @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 {
// 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;
// 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 = IUSDC(USDC_ADDRESS);
usdc.transferWithAuthorization(
sourceAddress,
address(this),
amount,
validAfter,
validBefore,
nonce,
v,
r,
s
);
balance += amount;
}
function Transfer(
address sourceAddress,
uint256 amount,
uint256 validAfter,
uint256 validBefore,
bytes32 nonce,
uint8 v,
bytes32 r,
bytes32 s
) external {
require(amount > 0, "Amount must be greater than 0");
_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 (and mintRecipient for bridge)
* @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,
uint256 amount,
uint256 feeAmount,
uint256 validAfter,
uint256 validBefore,
bytes32 nonce,
uint8 v,
bytes32 r,
bytes32 s,
uint32 destinationDomain,
uint256 bridgeMaxFee,
uint32 bridgeMinFinalityThreshold
) external {
require(amount > 0, "Amount must be greater than 0");
require(feeAmount < amount, "FeeAmount must be less than amount");
uint256 bridgeAmount = amount - feeAmount;
// Step 1: Receive USDC via transferWithAuthorization and add entire amount to balance
// After this step: balance = amount
_transferFrom(sourceAddress, amount, validAfter, validBefore, nonce, v, r, s);
// Step 2: Bridge bridgeAmount via depositForBurn (tokens are physically sent)
// After this step: tokens are sent, but balance still = amount
{
bytes32 mintRecipient = bytes32(uint256(uint160(sourceAddress)));
ITokenMessengerV2 tokenMessenger = ITokenMessengerV2(TOKEN_MESSENGER_V2_ADDRESS);
tokenMessenger.depositForBurn(
bridgeAmount,
destinationDomain,
mintRecipient,
USDC_ADDRESS,
bytes32(0),
bridgeMaxFee,
bridgeMinFinalityThreshold
);
}
// Step 3: Deduct bridged amount from balance
// After this step: balance = amount - bridgeAmount = feeAmount ✓
balance -= bridgeAmount;
// Emit event for transfer
emit TransferReceived(sourceAddress, amount);
}
/**
* @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 {
require(amount > 0, "Amount must be greater than 0");
require(balance >= amount, "Insufficient balance");
// Call depositForBurn on TokenMessengerV2
{
bytes32 mintRecipient = bytes32(uint256(uint160(sourceAddress)));
ITokenMessengerV2 tokenMessenger = ITokenMessengerV2(TOKEN_MESSENGER_V2_ADDRESS);
tokenMessenger.depositForBurn(
amount,
destinationDomain,
mintRecipient,
USDC_ADDRESS,
bytes32(0),
bridgeMaxFee,
bridgeMinFinalityThreshold
);
}
// Deduct sent amount from Balance
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 {
require(authorizedAddresses[msg.sender], "Sender is not authorized");
require(recipient != address(0), "Invalid recipient address");
require(balance > 0, "Balance is zero");
uint256 amountToWithdraw = balance;
balance = 0;
IUSDC usdc = IUSDC(USDC_ADDRESS);
require(usdc.transfer(recipient, amountToWithdraw), "Transfer failed");
emit WithdrawalExecuted(recipient, amountToWithdraw);
}
/**
* @dev Add address to whitelist
* @param account Address to add
*/
function addAuthorizedAddress(address account) external {
require(authorizedAddresses[msg.sender], "Sender is not authorized");
require(account != address(0), "Invalid address");
require(!authorizedAddresses[account], "Address already authorized");
authorizedAddresses[account] = true;
emit AuthorizedAddressAdded(account);
}
/**
* @dev Remove address from whitelist
* @param account Address to remove
*/
function removeAuthorizedAddress(address account) external {
require(authorizedAddresses[msg.sender], "Sender is not authorized");
require(account != PROTECTED_ADDRESS, "Cannot remove protected address");
require(authorizedAddresses[account], "Address is not authorized");
authorizedAddresses[account] = false;
emit AuthorizedAddressRemoved(account);
}
/**
* @dev Apply approve for TokenMessengerV2
* Can be called by any address
*/
function ApplyApprove() external {
IUSDC usdc = IUSDC(USDC_ADDRESS);
require(usdc.approve(TOKEN_MESSENGER_V2_ADDRESS, APPROVE_LIMIT), "Approve failed");
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 {
require(authorizedAddresses[msg.sender], "Sender is not authorized");
require(_usdcAddress != address(0), "USDC address cannot be zero");
require(_usdcAddress != USDC_ADDRESS, "Address is already set");
USDC_ADDRESS = _usdcAddress;
emit UsdcAddressChanged(_usdcAddress);
}
}
"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}
}}
Submitted on: 2025-11-04 09:47:04
Comments
Log in to comment.
No comments yet.