Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 100 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Ccip Send | 21051787 | 419 days ago | IN | 0.00023 ETH | 0.00130537 | ||||
| Ccip Send | 21040738 | 420 days ago | IN | 0.00022092 ETH | 0.00135232 | ||||
| Ccip Send | 21040681 | 420 days ago | IN | 0.00022092 ETH | 0.0009155 | ||||
| Ccip Send | 21040215 | 420 days ago | IN | 0.00021965 ETH | 0.00117166 | ||||
| Ccip Send | 21040174 | 420 days ago | IN | 0.00021965 ETH | 0.00131562 | ||||
| Ccip Send | 21040047 | 420 days ago | IN | 0.00021965 ETH | 0.00118656 | ||||
| Ccip Send | 20975217 | 429 days ago | IN | 0.00021781 ETH | 0.0031166 | ||||
| Ccip Send | 20967991 | 430 days ago | IN | 0.00021408 ETH | 0.0030778 | ||||
| Ccip Send | 20955971 | 432 days ago | IN | 0.00022701 ETH | 0.00249764 | ||||
| Ccip Send | 20909777 | 438 days ago | IN | 0.00022924 ETH | 0.00130092 | ||||
| Ccip Send | 20892582 | 441 days ago | IN | 0.00023563 ETH | 0.00263278 | ||||
| Ccip Send | 20891303 | 441 days ago | IN | 0.00024502 ETH | 0.00159357 | ||||
| Ccip Send | 20889302 | 441 days ago | IN | 0.00023827 ETH | 0.00098439 | ||||
| Ccip Send | 20889274 | 441 days ago | IN | 0.00024454 ETH | 0.00112151 | ||||
| Ccip Send | 20889263 | 441 days ago | IN | 0.00023827 ETH | 0.00124114 | ||||
| Ccip Send | 20889258 | 441 days ago | IN | 0.00024454 ETH | 0.00122705 | ||||
| Ccip Send | 20889246 | 441 days ago | IN | 0.00023827 ETH | 0.00124352 | ||||
| Ccip Send | 20888963 | 441 days ago | IN | 0.00023827 ETH | 0.00112281 | ||||
| Ccip Send | 20876171 | 443 days ago | IN | 0.00023524 ETH | 0.00146056 | ||||
| Ccip Send | 20715763 | 466 days ago | IN | 0.00024064 ETH | 0.00108286 | ||||
| Ccip Send | 20711436 | 466 days ago | IN | 0.0002413 ETH | 0.00032346 | ||||
| Ccip Send | 20677712 | 471 days ago | IN | 0.00024067 ETH | 0.00190282 | ||||
| Ccip Send | 20586357 | 484 days ago | IN | 0.0002143 ETH | 0.00026647 | ||||
| Ccip Send | 20567435 | 486 days ago | IN | 0.00021577 ETH | 0.0004159 | ||||
| Ccip Send | 20561937 | 487 days ago | IN | 0.00025875 ETH | 0.00114918 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Ccip Send | 21051787 | 419 days ago | 0.00020612 ETH | ||||
| Transfer | 21051787 | 419 days ago | 0.00002387 ETH | ||||
| Ccip Send | 21040738 | 420 days ago | 0.00020083 ETH | ||||
| Transfer | 21040738 | 420 days ago | 0.00002008 ETH | ||||
| Ccip Send | 21040681 | 420 days ago | 0.00020083 ETH | ||||
| Transfer | 21040681 | 420 days ago | 0.00002008 ETH | ||||
| Ccip Send | 21040215 | 420 days ago | 0.00019968 ETH | ||||
| Transfer | 21040215 | 420 days ago | 0.00001996 ETH | ||||
| Ccip Send | 21040174 | 420 days ago | 0.00019968 ETH | ||||
| Transfer | 21040174 | 420 days ago | 0.00001996 ETH | ||||
| Ccip Send | 21040047 | 420 days ago | 0.00019968 ETH | ||||
| Transfer | 21040047 | 420 days ago | 0.00001996 ETH | ||||
| Ccip Send | 20975217 | 429 days ago | 0.00019801 ETH | ||||
| Transfer | 20975217 | 429 days ago | 0.0000198 ETH | ||||
| Ccip Send | 20967991 | 430 days ago | 0.00019462 ETH | ||||
| Transfer | 20967991 | 430 days ago | 0.00001946 ETH | ||||
| Ccip Send | 20955971 | 432 days ago | 0.00020637 ETH | ||||
| Transfer | 20955971 | 432 days ago | 0.00002063 ETH | ||||
| Ccip Send | 20909777 | 438 days ago | 0.0002084 ETH | ||||
| Transfer | 20909777 | 438 days ago | 0.00002084 ETH | ||||
| Ccip Send | 20892582 | 441 days ago | 0.00021421 ETH | ||||
| Transfer | 20892582 | 441 days ago | 0.00002142 ETH | ||||
| Ccip Send | 20891303 | 441 days ago | 0.00022275 ETH | ||||
| Transfer | 20891303 | 441 days ago | 0.00002227 ETH | ||||
| Ccip Send | 20889302 | 441 days ago | 0.00021661 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CCIPBridgeProxy
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import { IRouterClient } from '@ccip/interfaces/IRouterClient.sol';
import { Client } from '@ccip/libraries/Client.sol';
import { SafeERC20, IERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
contract CCIPBridgeProxy {
using SafeERC20 for IERC20;
/******************* Errors *******************/
error InvalidValue();
error FeeRefundFail();
/******************* Constants *******************/
IRouterClient internal immutable ROUTER;
IERC20 internal immutable TOKEN;
/******************* Constructor *******************/
constructor(IRouterClient router, IERC20 token) {
ROUTER = router;
TOKEN = token;
token.approve(address(router), type(uint256).max);
}
/******************* Non-View Functions *******************/
/// @notice Transfers tokens to receiver on the destination chain using CCIP.
/// @notice Pay for fees in native.
/// @param destinationChainSelector The CCIP identifier for the destination blockchain.
/// @param receiver The address of the receiver on the destination blockchain.
/// @param amount The TRUF amount.
function ccipSend(
uint64 destinationChainSelector,
address receiver,
uint256 amount
) external payable returns (bytes32 messageId) {
Client.EVM2AnyMessage memory message = _buildCCIPMessage(receiver, amount);
uint256 fee = ROUTER.getFee(destinationChainSelector, message);
if (fee > msg.value) revert InvalidValue();
if (msg.value > fee) {
(bool success, ) = msg.sender.call{ value: msg.value - fee }('');
if (success == false) revert FeeRefundFail();
}
SafeERC20.safeTransferFrom(TOKEN, msg.sender, address(this), amount);
messageId = ROUTER.ccipSend{ value: fee }(destinationChainSelector, message);
}
/******************* View Functions *******************/
/// @notice Get the fee for any given transfer.
/// @notice Pay for fees in native.
/// @param destinationChainSelector The CCIP identifier for the destination blockchain.
/// @param receiver The address of the receiver on the destination blockchain.
/// @param amount The TRUF amount.
function getFee(uint64 destinationChainSelector, address receiver, uint256 amount) external view returns (uint256 fee) {
Client.EVM2AnyMessage memory message = _buildCCIPMessage(receiver, amount);
return ROUTER.getFee(destinationChainSelector, message);
}
/// @notice Get the address of the router.
/// @notice Immutable.
/// @return The router address.
function getRouter() external view returns (address) {
return address(ROUTER);
}
/// @notice Get the address of the TRUF token.
/// @notice Immutable.
/// @return The TRUF token address.
function getToken() external view returns (address) {
return address(TOKEN);
}
/******************* Internal Functions *******************/
/// @notice Build the CCIP message for the token transfer.
/// @dev This function will create an EVM2AnyMessage struct with all the necessary information for the token transfer.
/// @param receiver The address of the receiver for the tokens.
/// @param amount The amount of tokens to be sent.
/// @return Client.EVM2AnyMessage Returns an EVM2AnyMessage struct which contains the CCIP message information.
function _buildCCIPMessage(address receiver, uint256 amount) private view returns (Client.EVM2AnyMessage memory) {
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
tokenAmounts[0] = Client.EVMTokenAmount({ token: address(TOKEN), amount: amount });
// Create an EVM2AnyMessage struct with the necessary information for sending a CCIP message
return
Client.EVM2AnyMessage({
receiver: abi.encode(receiver),
data: '',
tokenAmounts: tokenAmounts,
extraArgs: Client._argsToBytes(
// Setting gas limit to 0 as we are not sending any data
Client.EVMExtraArgsV1({ gasLimit: 0 })
),
feeToken: address(0)
});
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Client} from "../libraries/Client.sol";
interface IRouterClient {
error UnsupportedDestinationChain(uint64 destChainSelector);
error InsufficientFeeTokenAmount();
error InvalidMsgValue();
/// @notice Checks if the given chain ID is supported for sending/receiving.
/// @param chainSelector The chain to check.
/// @return supported is true if it is supported, false if not.
function isChainSupported(uint64 chainSelector) external view returns (bool supported);
/// @notice Gets a list of all supported tokens which can be sent or received
/// to/from a given chain id.
/// @param chainSelector The chainSelector.
/// @return tokens The addresses of all tokens that are supported.
function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory tokens);
/// @param destinationChainSelector The destination chainSelector
/// @param message The cross-chain CCIP message including data and/or tokens
/// @return fee returns execution fee for the message
/// delivery to destination chain, denominated in the feeToken specified in the message.
/// @dev Reverts with appropriate reason upon invalid message.
function getFee(
uint64 destinationChainSelector,
Client.EVM2AnyMessage memory message
) external view returns (uint256 fee);
/// @notice Request a message to be sent to the destination chain
/// @param destinationChainSelector The destination chain ID
/// @param message The cross-chain CCIP message including data and/or tokens
/// @return messageId The message ID
/// @dev Note if msg.value is larger than the required fee (from getFee) we accept
/// the overpayment with no refund.
/// @dev Reverts with appropriate reason upon invalid message.
function ccipSend(
uint64 destinationChainSelector,
Client.EVM2AnyMessage calldata message
) external payable returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// End consumer library.
library Client {
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct EVMTokenAmount {
address token; // token address on the local chain.
uint256 amount; // Amount of tokens.
}
struct Any2EVMMessage {
bytes32 messageId; // MessageId corresponding to ccipSend on source.
uint64 sourceChainSelector; // Source chain selector.
bytes sender; // abi.decode(sender) if coming from an EVM chain.
bytes data; // payload sent in original message.
EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation.
}
// If extraArgs is empty bytes, the default is 200k gas limit.
struct EVM2AnyMessage {
bytes receiver; // abi.encode(receiver address) for dest EVM chains
bytes data; // Data payload
EVMTokenAmount[] tokenAmounts; // Token transfers
address feeToken; // Address of feeToken. address(0) means you will send msg.value.
bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)
}
// bytes4(keccak256("CCIP EVMExtraArgsV1"));
bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;
struct EVMExtraArgsV1 {
uint256 gasLimit;
}
function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts_v5.0.2/contracts/",
"@openzeppelin_v4.8.0/contracts/=lib/openzeppelin-contracts_v4.8.0/contracts/",
"@openzeppelin_v4.9.0/contracts/=lib/openzeppelin-contracts_v4.9.0/contracts/",
"@ccip/=lib/ccip_v2.9.1-ccip1.4.8-release/contracts/src/v0.8/ccip/",
"ccip_v2.9.1-ccip1.4.8-release/=lib/ccip_v2.9.1-ccip1.4.8-release/contracts/",
"ds-test/=lib/openzeppelin-contracts_v4.9.0/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts_v4.9.0/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts_v4.8.0/=lib/openzeppelin-contracts_v4.8.0/",
"openzeppelin-contracts_v4.9.0/=lib/openzeppelin-contracts_v4.9.0/",
"openzeppelin-contracts_v5.0.2/=lib/openzeppelin-contracts_v5.0.2/",
"openzeppelin/=lib/openzeppelin-contracts_v4.9.0/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IRouterClient","name":"router","type":"address"},{"internalType":"contract IERC20","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"FeeRefundFail","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"uint64","name":"destinationChainSelector","type":"uint64"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ccipSend","outputs":[{"internalType":"bytes32","name":"messageId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"destinationChainSelector","type":"uint64"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c060405234801561001057600080fd5b50604051610ad2380380610ad283398101604081905261002f916100d1565b6001600160a01b03828116608081905290821660a081905260405163095ea7b360e01b8152600481019290925260001960248301529063095ea7b3906044016020604051808303816000875af115801561008d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b1919061010b565b505050610134565b6001600160a01b03811681146100ce57600080fd5b50565b600080604083850312156100e457600080fd5b82516100ef816100b9565b6020840151909250610100816100b9565b809150509250929050565b60006020828403121561011d57600080fd5b8151801515811461012d57600080fd5b9392505050565b60805160a05161095861017a600039600081816053015281816102f6015261044201526000818160cd0152818161012b015281816101c1015261033401526109586000f3fe60806040526004361061003f5760003560e01c806321df0da7146100445780637cf9636714610090578063b0f479a1146100be578063de1ecedb146100f1575b600080fd5b34801561005057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c57600080fd5b506100b06100ab366004610710565b610104565b604051908152602001610087565b3480156100ca57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610073565b6100b06100ff366004610710565b6101ae565b60008061011184846103ba565b6040516320487ded60e01b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320487ded9061016290889085906004016107ba565b602060405180830381865afa15801561017f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a39190610894565b9150505b9392505050565b6000806101bb84846103ba565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166320487ded87846040518363ffffffff1660e01b815260040161020d9291906107ba565b602060405180830381865afa15801561022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024e9190610894565b90503481111561027157604051632a9ffab760e21b815260040160405180910390fd5b803411156102f15760003361028683346108ad565b604051600081818185875af1925050503d80600081146102c2576040519150601f19603f3d011682016040523d82523d6000602084013e6102c7565b606091505b50909150508015156000036102ef576040516308d7d53760e01b815260040160405180910390fd5b505b61031d7f000000000000000000000000000000000000000000000000000000000000000033308761054b565b6040516396f4e9f960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906396f4e9f990839061036d908a9087906004016107ba565b60206040518083038185885af115801561038b573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906103b09190610894565b9695505050505050565b6103f56040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b604080516001808252818301909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161040c57905050905060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018481525081600081518110610486576104866108ce565b60209081029190910101526040805160a081019091526001600160a01b03851660c08201528060e08101604051602081830303815290604052815260200160405180602001604052806000815250815260200182815260200160006001600160a01b0316815260200161053f6040518060200160405280600081525060408051915160248084019190915281518084039091018152604490920190526020810180516001600160e01b03166397a657c960e01b17905290565b90529150505b92915050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526105a59085906105ab565b50505050565b60006105c06001600160a01b03841683610618565b905080516000141580156105e55750808060200190518101906105e391906108e4565b155b1561061357604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b505050565b60606101a78383600084600080856001600160a01b0316848660405161063e9190610906565b60006040518083038185875af1925050503d806000811461067b576040519150601f19603f3d011682016040523d82523d6000602084013e610680565b606091505b50915091506103b08683836060826106a05761069b826106e7565b6101a7565b81511580156106b757506001600160a01b0384163b155b156106e057604051639996b31560e01b81526001600160a01b038516600482015260240161060a565b50806101a7565b8051156106f75780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60008060006060848603121561072557600080fd5b833567ffffffffffffffff8116811461073d57600080fd5b925060208401356001600160a01b038116811461075957600080fd5b929592945050506040919091013590565b60005b8381101561078557818101518382015260200161076d565b50506000910152565b600081518084526107a681602086016020860161076a565b601f01601f19169290920160200192915050565b6000604067ffffffffffffffff8516835260208181850152845160a0838601526107e760e086018261078e565b905081860151603f1980878403016060880152610804838361078e565b88860151888203830160808a01528051808352908601945060009350908501905b8084101561085757845180516001600160a01b0316835286015186830152938501936001939093019290860190610825565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550610886818761078e565b9a9950505050505050505050565b6000602082840312156108a657600080fd5b5051919050565b8181038181111561054557634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000602082840312156108f657600080fd5b815180151581146101a757600080fd5b6000825161091881846020870161076a565b919091019291505056fea26469706673582212205e06154ae955af7dd12c77e05a69e4b13f499219d86352e34da906e90a23cf3f64736f6c6343000814003300000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca
Deployed Bytecode
0x60806040526004361061003f5760003560e01c806321df0da7146100445780637cf9636714610090578063b0f479a1146100be578063de1ecedb146100f1575b600080fd5b34801561005057600080fd5b507f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca5b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c57600080fd5b506100b06100ab366004610710565b610104565b604051908152602001610087565b3480156100ca57600080fd5b507f00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d610073565b6100b06100ff366004610710565b6101ae565b60008061011184846103ba565b6040516320487ded60e01b81529091506001600160a01b037f00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d16906320487ded9061016290889085906004016107ba565b602060405180830381865afa15801561017f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a39190610894565b9150505b9392505050565b6000806101bb84846103ba565b905060007f00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d6001600160a01b03166320487ded87846040518363ffffffff1660e01b815260040161020d9291906107ba565b602060405180830381865afa15801561022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024e9190610894565b90503481111561027157604051632a9ffab760e21b815260040160405180910390fd5b803411156102f15760003361028683346108ad565b604051600081818185875af1925050503d80600081146102c2576040519150601f19603f3d011682016040523d82523d6000602084013e6102c7565b606091505b50909150508015156000036102ef576040516308d7d53760e01b815260040160405180910390fd5b505b61031d7f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca33308761054b565b6040516396f4e9f960e01b81526001600160a01b037f00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d16906396f4e9f990839061036d908a9087906004016107ba565b60206040518083038185885af115801561038b573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906103b09190610894565b9695505050505050565b6103f56040518060a0016040528060608152602001606081526020016060815260200160006001600160a01b03168152602001606081525090565b604080516001808252818301909252600091816020015b604080518082019091526000808252602082015281526020019060019003908161040c57905050905060405180604001604052807f00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca6001600160a01b031681526020018481525081600081518110610486576104866108ce565b60209081029190910101526040805160a081019091526001600160a01b03851660c08201528060e08101604051602081830303815290604052815260200160405180602001604052806000815250815260200182815260200160006001600160a01b0316815260200161053f6040518060200160405280600081525060408051915160248084019190915281518084039091018152604490920190526020810180516001600160e01b03166397a657c960e01b17905290565b90529150505b92915050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526105a59085906105ab565b50505050565b60006105c06001600160a01b03841683610618565b905080516000141580156105e55750808060200190518101906105e391906108e4565b155b1561061357604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b505050565b60606101a78383600084600080856001600160a01b0316848660405161063e9190610906565b60006040518083038185875af1925050503d806000811461067b576040519150601f19603f3d011682016040523d82523d6000602084013e610680565b606091505b50915091506103b08683836060826106a05761069b826106e7565b6101a7565b81511580156106b757506001600160a01b0384163b155b156106e057604051639996b31560e01b81526001600160a01b038516600482015260240161060a565b50806101a7565b8051156106f75780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60008060006060848603121561072557600080fd5b833567ffffffffffffffff8116811461073d57600080fd5b925060208401356001600160a01b038116811461075957600080fd5b929592945050506040919091013590565b60005b8381101561078557818101518382015260200161076d565b50506000910152565b600081518084526107a681602086016020860161076a565b601f01601f19169290920160200192915050565b6000604067ffffffffffffffff8516835260208181850152845160a0838601526107e760e086018261078e565b905081860151603f1980878403016060880152610804838361078e565b88860151888203830160808a01528051808352908601945060009350908501905b8084101561085757845180516001600160a01b0316835286015186830152938501936001939093019290860190610825565b5060608901516001600160a01b031660a08901526080890151888203830160c08a01529550610886818761078e565b9a9950505050505050505050565b6000602082840312156108a657600080fd5b5051919050565b8181038181111561054557634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000602082840312156108f657600080fd5b815180151581146101a757600080fd5b6000825161091881846020870161076a565b919091019291505056fea26469706673582212205e06154ae955af7dd12c77e05a69e4b13f499219d86352e34da906e90a23cf3f64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca
-----Decoded View---------------
Arg [0] : router (address): 0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D
Arg [1] : token (address): 0x38C2a4a7330b22788374B8Ff70BBa513C8D848cA
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000080226fc0ee2b096224eeac085bb9a8cba1146f7d
Arg [1] : 00000000000000000000000038c2a4a7330b22788374b8ff70bba513c8d848ca
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.