Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
0x60806040 | 21117964 | 148 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
DaimoPayCCTPBridger
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 999999 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.12; import "openzeppelin-contracts/contracts/access/Ownable2Step.sol"; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/IDaimoPayBridger.sol"; import "../../vendor/cctp/ITokenMinter.sol"; import "../../vendor/cctp/ICCTPTokenMessenger.sol"; /// @title Bridger implementation for Circle's Cross-Chain Transfer Protocol (CCTP) /// @author The Daimo team /// @custom:security-contact [email protected] /// /// @dev Bridges assets from to a destination chain using CCTP. The only supported /// bridge token is USDC. contract DaimoPayCCTPBridger is IDaimoPayBridger, Ownable2Step { using SafeERC20 for IERC20; struct CCTPBridgeRoute { uint32 domain; address bridgeTokenOut; } // CCTP TokenMinter for this chain. Used to identify the CCTP token on the // current chain. ITokenMinter public tokenMinter; // CCTP TokenMessenger for this chain. Used to initiate the CCTP bridge. ICCTPTokenMessenger public cctpMessenger; // Map destination chainId to CCTP domain and the bridge token address on the // destination chain. mapping(uint256 toChainId => CCTPBridgeRoute bridgeRoute) public bridgeRouteMapping; event BridgeRouteAdded( uint256 indexed toChainId, CCTPBridgeRoute bridgeRoute ); event BridgeRouteRemoved( uint256 indexed toChainId, CCTPBridgeRoute bridgeRoute ); /// Specify the CCTP chain IDs and domains that this bridger will support. constructor( address _owner, ITokenMinter _tokenMinter, ICCTPTokenMessenger _cctpMessenger, uint256[] memory _toChainIds, CCTPBridgeRoute[] memory _bridgeRoutes ) Ownable(_owner) { tokenMinter = _tokenMinter; cctpMessenger = _cctpMessenger; _setBridgeRoutes({ toChainIds: _toChainIds, bridgeRoutes: _bridgeRoutes }); } // ----- ADMIN FUNCTIONS ----- /// Add a new supported CCTP recipient chain. function setBridgeRoutes( uint256[] memory toChainIds, CCTPBridgeRoute[] memory bridgeRoutes ) public onlyOwner { _setBridgeRoutes({toChainIds: toChainIds, bridgeRoutes: bridgeRoutes}); } function _setBridgeRoutes( uint256[] memory toChainIds, CCTPBridgeRoute[] memory bridgeRoutes ) private { uint256 n = toChainIds.length; require(n == bridgeRoutes.length, "DPCCTPB: wrong bridgeRoutes length"); for (uint256 i = 0; i < n; ++i) { bridgeRouteMapping[toChainIds[i]] = bridgeRoutes[i]; emit BridgeRouteAdded({ toChainId: toChainIds[i], bridgeRoute: bridgeRoutes[i] }); } } /// Remove a supported CCTP recipient chain. function removeBridgeRoutes(uint256[] memory toChainIds) public onlyOwner { for (uint256 i = 0; i < toChainIds.length; ++i) { CCTPBridgeRoute memory bridgeRoute = bridgeRouteMapping[ toChainIds[i] ]; delete bridgeRouteMapping[toChainIds[i]]; emit BridgeRouteRemoved({ toChainId: toChainIds[i], bridgeRoute: bridgeRoute }); } } function addressToBytes32(address addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(addr))); } // ----- BRIDGER FUNCTIONS ----- /// Given a list of bridge token options, find the index of the bridge token /// that matches the correct bridge token out. Return the length of the array /// if no match is found. function _findBridgeTokenOut( TokenAmount[] memory bridgeTokenOutOptions, address bridgeTokenOut ) internal pure returns (uint256 index) { uint256 n = bridgeTokenOutOptions.length; for (uint256 i = 0; i < n; ++i) { if (address(bridgeTokenOutOptions[i].token) == bridgeTokenOut) { return i; } } return n; } /// Get the CCTP bridge token address and amount for the current chain. /// CCTP does 1 to 1 token bridging, so the amount of tokens to bridge is /// the same as toAmount. function _getBridgeData( uint256 toChainId, TokenAmount[] memory bridgeTokenOutOptions ) internal view returns ( address inToken, uint256 inAmount, address outToken, uint256 outAmount, uint32 toDomain ) { CCTPBridgeRoute memory bridgeRoute = bridgeRouteMapping[toChainId]; require( bridgeRoute.bridgeTokenOut != address(0), "DPCCTPB: bridge route not found" ); uint256 index = _findBridgeTokenOut( bridgeTokenOutOptions, bridgeRoute.bridgeTokenOut ); // If the index is the length of the array, then the bridge token out // was not found in the list of options. require( index < bridgeTokenOutOptions.length, "DPCCTPB: bad bridge token" ); toDomain = bridgeRoute.domain; outToken = bridgeRoute.bridgeTokenOut; outAmount = bridgeTokenOutOptions[index].amount; inToken = tokenMinter.getLocalToken( bridgeRoute.domain, addressToBytes32(bridgeRoute.bridgeTokenOut) ); inAmount = outAmount; } function getBridgeTokenIn( uint256 toChainId, TokenAmount[] memory bridgeTokenOutOptions ) external view returns (address bridgeTokenIn, uint256 inAmount) { (address _bridgeTokenIn, uint256 _inAmount, , , ) = _getBridgeData( toChainId, bridgeTokenOutOptions ); bridgeTokenIn = _bridgeTokenIn; inAmount = _inAmount; } /// Initiate a bridge to a destination chain using CCTP. function sendToChain( uint256 toChainId, address toAddress, TokenAmount[] memory bridgeTokenOutOptions, bytes calldata /* extraData */ ) public { require(toChainId != block.chainid, "DPCCTPB: same chain"); ( address inToken, uint256 inAmount, address outToken, uint256 outAmount, uint32 toDomain ) = _getBridgeData(toChainId, bridgeTokenOutOptions); require(outAmount > 0, "DPCCTPB: zero amount"); // Move input token from caller to this contract and approve CCTP. IERC20(inToken).safeTransferFrom({ from: msg.sender, to: address(this), value: inAmount }); IERC20(inToken).forceApprove({ spender: address(cctpMessenger), value: inAmount }); cctpMessenger.depositForBurn({ amount: inAmount, destinationDomain: toDomain, mintRecipient: addressToBytes32(toAddress), burnToken: address(inToken) }); emit BridgeInitiated({ fromAddress: msg.sender, fromToken: inToken, fromAmount: inAmount, toChainId: toChainId, toAddress: toAddress, toToken: outToken, toAmount: outAmount }); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// 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/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: GPL-3.0-or-later pragma solidity ^0.8.12; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import "../pay/TokenUtils.sol"; /// @notice Bridges assets automatically. Specifically, it lets any market maker /// initiate a bridge transaction to another chain. interface IDaimoPayBridger { /// @notice Emitted when a bridge transaction is initiated event BridgeInitiated( address fromAddress, address fromToken, uint256 fromAmount, uint256 toChainId, address toAddress, address toToken, uint256 toAmount ); /// @dev Get the bridge route for the given output token options on /// destination chain. function getBridgeTokenIn( uint256 toChainId, TokenAmount[] memory bridgeTokenOutOptions ) external view returns (address bridgeTokenIn, uint256 inAmount); /// @dev Initiate a bridge. Guarantees that one of the bridge token options /// (bridgeTokenOut, outAmount) shows up in (toAddress) on (toChainId). /// Otherwise, reverts. function sendToChain( uint256 toChainId, address toAddress, TokenAmount[] memory bridgeTokenOutOptions, bytes calldata extraData ) external; }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.12; /** * @title ITokenMinter * @notice interface for minter of tokens that are mintable, burnable, and interchangeable * across domains. */ interface ITokenMinter { /** * @notice Mints `amount` of local tokens corresponding to the * given (`sourceDomain`, `burnToken`) pair, to `to` address. * @dev reverts if the (`sourceDomain`, `burnToken`) pair does not * map to a nonzero local token address. This mapping can be queried using * getLocalToken(). * @param sourceDomain Source domain where `burnToken` was burned. * @param burnToken Burned token address as bytes32. * @param to Address to receive minted tokens, corresponding to `burnToken`, * on this domain. * @param amount Amount of tokens to mint. Must be less than or equal * to the minterAllowance of this TokenMinter for given `_mintToken`. * @return mintToken token minted. */ function mint( uint32 sourceDomain, bytes32 burnToken, address to, uint256 amount ) external returns (address mintToken); /** * @notice Burn tokens owned by this ITokenMinter. * @param burnToken burnable token. * @param amount amount of tokens to burn. Must be less than or equal to this ITokenMinter's * account balance of the given `_burnToken`. */ function burn(address burnToken, uint256 amount) external; /** * @notice Get the local token associated with the given remote domain and token. * @param remoteDomain Remote domain * @param remoteToken Remote token * @return local token address */ function getLocalToken( uint32 remoteDomain, bytes32 remoteToken ) external view returns (address); /** * @notice Set the token controller of this ITokenMinter. Token controller * is responsible for mapping local tokens to remote tokens, and managing * token-specific limits * @param newTokenController new token controller address */ function setTokenController(address newTokenController) external; }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.12; /** * @title ICCTPTokenMessenger * @notice Initiates CCTP transfers. Interface derived from TokenMessenger.sol. */ interface ICCTPTokenMessenger { /** * @notice Deposits and burns tokens from sender to be minted on destination domain. * Emits a `DepositForBurn` event. * @dev reverts if: * - given burnToken is not supported * - given destinationDomain has no TokenMessenger registered * - transferFrom() reverts. For example, if sender's burnToken balance or approved allowance * to this contract is less than `amount`. * - burn() reverts. For example, if `amount` is 0. * - MessageTransmitter returns false or reverts. * @param amount amount of tokens to burn * @param destinationDomain destination domain * @param mintRecipient address of mint recipient on destination domain * @param burnToken address of contract to burn deposited tokens, on local domain * @return _nonce unique nonce reserved by message */ function depositForBurn( uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken ) external returns (uint64 _nonce); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// 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(); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.12; import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @dev Asset amount, e.g. $100 USDC or 0.1 ETH struct TokenAmount { /// @dev Zero address = native asset, e.g. ETH IERC20 token; uint256 amount; } /// @dev Represents a destination address + optional arbitrary contract call struct Call { /// @dev Destination receiving address or contract address to; /// @dev Native token amount for call, or 0 uint256 value; /// @dev Calldata for call, or empty = no contract call bytes data; } /** Utility functions that work for both ERC20 and native tokens. */ library TokenUtils { using SafeERC20 for IERC20; /** Returns ERC20 or ETH balance. */ function getBalanceOf( IERC20 token, address addr ) internal view returns (uint256) { if (address(token) == address(0)) { return addr.balance; } else { return token.balanceOf(addr); } } /** Approves a token transfer. */ function approve(IERC20 token, address spender, uint256 amount) internal { if (address(token) != address(0)) { token.approve({spender: spender, value: amount}); } // Do nothing for native token. } /** Sends an ERC20 or ETH transfer. For ETH, verify call success. */ function transfer( IERC20 token, address payable recipient, uint256 amount ) internal { if (address(token) != address(0)) { token.safeTransfer({to: recipient, value: amount}); } else { // Native token transfer (bool success, ) = recipient.call{value: amount}(""); require(success, "TokenUtils: ETH transfer failed"); } } function transferFrom( IERC20 token, address from, address to, uint256 amount ) internal { require( address(token) != address(0), "TokenUtils: ETH transferFrom must be caller" ); token.safeTransferFrom({from: from, to: to, value: amount}); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
{ "remappings": [ "account-abstraction/=lib/account-abstraction/contracts/", "@axelar-network/=lib/axelar-gmp-sdk-solidity/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "p256-verifier/=lib/p256-verifier/src/", "@uniswap/v3-core/=lib/v3-core/", "@uniswap/v3-periphery/=lib/v3-periphery/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "axelar-gmp-sdk-solidity/=lib/axelar-gmp-sdk-solidity/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "solmate/=lib/solmate/src/", "v3-core/=lib/v3-core/contracts/", "v3-periphery/=lib/v3-periphery/contracts/" ], "optimizer": { "enabled": true, "runs": 999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract ITokenMinter","name":"_tokenMinter","type":"address"},{"internalType":"contract ICCTPTokenMessenger","name":"_cctpMessenger","type":"address"},{"internalType":"uint256[]","name":"_toChainIds","type":"uint256[]"},{"components":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"bridgeTokenOut","type":"address"}],"internalType":"struct DaimoPayCCTPBridger.CCTPBridgeRoute[]","name":"_bridgeRoutes","type":"tuple[]"}],"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":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"address","name":"fromToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toChainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"}],"name":"BridgeInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"toChainId","type":"uint256"},{"components":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"bridgeTokenOut","type":"address"}],"indexed":false,"internalType":"struct DaimoPayCCTPBridger.CCTPBridgeRoute","name":"bridgeRoute","type":"tuple"}],"name":"BridgeRouteAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"toChainId","type":"uint256"},{"components":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"bridgeTokenOut","type":"address"}],"indexed":false,"internalType":"struct DaimoPayCCTPBridger.CCTPBridgeRoute","name":"bridgeRoute","type":"tuple"}],"name":"BridgeRouteRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChainId","type":"uint256"}],"name":"bridgeRouteMapping","outputs":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"bridgeTokenOut","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cctpMessenger","outputs":[{"internalType":"contract ICCTPTokenMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChainId","type":"uint256"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"bridgeTokenOutOptions","type":"tuple[]"}],"name":"getBridgeTokenIn","outputs":[{"internalType":"address","name":"bridgeTokenIn","type":"address"},{"internalType":"uint256","name":"inAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toChainIds","type":"uint256[]"}],"name":"removeBridgeRoutes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"address","name":"toAddress","type":"address"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"bridgeTokenOutOptions","type":"tuple[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"sendToChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toChainIds","type":"uint256[]"},{"components":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"address","name":"bridgeTokenOut","type":"address"}],"internalType":"struct DaimoPayCCTPBridger.CCTPBridgeRoute[]","name":"bridgeRoutes","type":"tuple[]"}],"name":"setBridgeRoutes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenMinter","outputs":[{"internalType":"contract ITokenMinter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052346103275761183a8038038061001981610352565b928339810160a0828203126103275761003182610377565b60208301516001600160a01b0381169291908390036103275760408401516001600160a01b03811691908290036103275760608501516001600160401b0381116103275785019483601f87011215610327578551956100976100928861038b565b610352565b9660208089838152019160051b8301019186831161032757602001905b828210610342575050506080810151906001600160401b038211610327570183601f82011215610327578051906100ed6100928361038b565b9460208087858152019360061b8301019181831161032757602001925b8284106102ce575050505060018060a01b03169283156102b857600180546001600160a01b0319908116909155600080549182168617815560405195916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a360018060a01b0319600254161760025560018060a01b031960035416176003558251918151830361026b575060005b8281106101ba5760405161146d90816103cd8239f35b806101c7600192846103a2565b516101d282876103a2565b51600052600460205260406000209063ffffffff81511682549160206401000000008760c01b0391015160201b1691858060c01b0319161717905561021781866103a2565b517f727da3b1d3a958e514361facf35c17ead5a3aebcc08d21df9ab1a0d8537f0366604061024584876103a2565b5181519063ffffffff81511682526020878060a01b03910151166020820152a2016101a4565b62461bcd60e51b815260206004820152602260248201527f445043435450423a2077726f6e6720627269646765526f75746573206c656e676044820152610e8d60f31b6064820152608490fd5b631e4fbdf760e01b600052600060045260246000fd5b6040848303126103275760408051919082016001600160401b0381118382101761032c5760405284519063ffffffff82168203610327578260209260409452610318838801610377565b8382015281520193019261010a565b600080fd5b634e487b7160e01b600052604160045260246000fd5b81518152602091820191016100b4565b6040519190601f01601f191682016001600160401b0381118382101761032c57604052565b51906001600160a01b038216820361032757565b6001600160401b03811161032c5760051b60200190565b80518210156103b65760209160051b010190565b634e487b7160e01b600052603260045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c90816302443a6c14610d8e575080631c59e972146108f45780633a4beec8146108a257806359cfc1cc14610761578063715018a61461069d57806373787b97146103f557806379ba5097146102e75780638da5cb5b14610295578063cfb3647b14610243578063e30c3978146101f1578063f2fde38b1461012f5763f80e0a42146100a357600080fd5b3461012a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760243567ffffffffffffffff811161012a576100f56100fd913690600401610e9d565b600435610fde565b50506040805173ffffffffffffffffffffffffffffffffffffffff94909416845260208401929092525090f35b600080fd5b3461012a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043573ffffffffffffffffffffffffffffffffffffffff811680910361012a5761018761120e565b807fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015573ffffffffffffffffffffffffffffffffffffffff600054167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700600080a3005b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a573373ffffffffffffffffffffffffffffffffffffffff60015416036103c7577fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155600054337fffffffffffffffffffffffff000000000000000000000000000000000000000082161760005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b3461012a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043567ffffffffffffffff811161012a57610444903690600401610f3e565b60243567ffffffffffffffff811161012a573660238201121561012a57806004013561046f81610e85565b9161047d6040519384610e44565b8183526024602084019260061b8201019036821161012a57602401915b81831061063d575050506104ac61120e565b815190805182036105b95760005b8281106104c357005b806104d060019284610f9b565b516104db8287610f9b565b51600052600460205260406000209063ffffffff8151167fffffffffffffffff00000000000000000000000000000000000000000000000077ffffffffffffffffffffffffffffffffffffffff000000006020855494015160201b169216171790556105478186610f9b565b517f727da3b1d3a958e514361facf35c17ead5a3aebcc08d21df9ab1a0d8537f03666105b06105768487610f9b565b5160405191829182919091602073ffffffffffffffffffffffffffffffffffffffff81604084019563ffffffff8151168552015116910152565b0390a2016104ba565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f445043435450423a2077726f6e6720627269646765526f75746573206c656e6760448201527f74680000000000000000000000000000000000000000000000000000000000006064820152fd5b60408336031261012a576040519061065482610df9565b833563ffffffff8116810361012a57825260208401359073ffffffffffffffffffffffffffffffffffffffff8216820361012a578260209283604095015281520192019161049a565b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a576106d461120e565b7fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155600073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461012a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043567ffffffffffffffff811161012a576107b0903690600401610f3e565b6107b861120e565b60005b81518110156108a057806107d160019284610f9b565b516000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6040519161080183610df9565b5463ffffffff8116835260201c16602082015261081e8285610f9b565b516000526004602052600060408120557fee916dfd1f2dd308c32f05e4bdef9d466ff4cf2c53f7df1d308317f6693d45e561089761085c8487610f9b565b519260405191829182919091602073ffffffffffffffffffffffffffffffffffffffff81604084019563ffffffff8151168552015116910152565b0390a2016107bb565b005b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b3461012a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043560243573ffffffffffffffffffffffffffffffffffffffff811680910361012a5760443567ffffffffffffffff811161012a57610967903690600401610e9d565b60643567ffffffffffffffff811161012a573660238201121561012a57806004013567ffffffffffffffff811161012a573691016024011161012a57468314610d30576109b49083610fde565b94919290938415610cd25773ffffffffffffffffffffffffffffffffffffffff1694610a296040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015283606482015260648152610a23608482610e44565b876112a7565b73ffffffffffffffffffffffffffffffffffffffff60035416604051600080602083017f095ea7b3000000000000000000000000000000000000000000000000000000008152610ad084610aa48988602484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101865285610e44565b835190828c5af1610adf61133c565b81610ca3575b5080610c99575b15610c40575b5050602063ffffffff608473ffffffffffffffffffffffffffffffffffffffff6003541693600060405195869485937f6fd3504e0000000000000000000000000000000000000000000000000000000085528960048601521660248401528860448401528b60648401525af18015610c3457610bd0575b7f7a1aaa549d494a115465b34eba936c63fadb6c733c73b1aa66b46ff791df584760e0878773ffffffffffffffffffffffffffffffffffffffff88888d896040519633885260208801526040870152606086015260808501521660a083015260c0820152a1005b60209594939195813d602011610c2c575b81610bee60209383610e44565b8101031261012a57519167ffffffffffffffff8316830361012a5793949293909290915073ffffffffffffffffffffffffffffffffffffffff610b69565b3d9150610be1565b6040513d6000823e3d90fd5b610a23610c9292604051907f095ea7b300000000000000000000000000000000000000000000000000000000602083015260248201526000604482015260448152610c8c606482610e44565b896112a7565b8780610af2565b50873b1515610aec565b8051801592508215610cb8575b50508a610ae5565b610ccb925060208091830101910161128f565b8a80610cb0565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f445043435450423a207a65726f20616d6f756e740000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f445043435450423a2073616d6520636861696e000000000000000000000000006044820152fd5b3461012a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57604090600435600052600460205273ffffffffffffffffffffffffffffffffffffffff826000205463ffffffff8116835260201c166020820152f35b6040810190811067ffffffffffffffff821117610e1557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610e1557604052565b67ffffffffffffffff8111610e155760051b60200190565b81601f8201121561012a57803590610eb482610e85565b92610ec26040519485610e44565b82845260208085019360061b8301019181831161012a57602001925b828410610eec575050505090565b60408483031261012a5760405190610f0382610df9565b84359073ffffffffffffffffffffffffffffffffffffffff8216820361012a5782602092604094528287013583820152815201930192610ede565b9080601f8301121561012a578135610f5581610e85565b92610f636040519485610e44565b81845260208085019260051b82010192831161012a57602001905b828210610f8b5750505090565b8135815260209182019101610f7e565b8051821015610faf5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919091600052600460205260406000209173ffffffffffffffffffffffffffffffffffffffff6040519361101185610df9565b5463ffffffff8116855260201c166020840190808252156111b05761104d73ffffffffffffffffffffffffffffffffffffffff8251168361122f565b9382518510156111525760208061108463ffffffff8451169773ffffffffffffffffffffffffffffffffffffffff86511696610f9b565b51015192604473ffffffffffffffffffffffffffffffffffffffff63ffffffff81600254169551169251169160405194859384927f78a0565e000000000000000000000000000000000000000000000000000000008452600484015260248301525afa908115610c34576000916110fc575b50938193565b6020813d60201161114a575b8161111560209383610e44565b8101031261114657519073ffffffffffffffffffffffffffffffffffffffff821682036111435750386110f6565b80fd5b5080fd5b3d9150611108565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f445043435450423a206261642062726964676520746f6b656e000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f445043435450423a2062726964676520726f757465206e6f7420666f756e64006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff6000541633036103c757565b80519160005b8381106112425750505090565b73ffffffffffffffffffffffffffffffffffffffff6112618285610f9b565b51511673ffffffffffffffffffffffffffffffffffffffff83161461128857600101611235565b9250505090565b9081602091031261012a5751801515810361012a5790565b60008073ffffffffffffffffffffffffffffffffffffffff6112de93169360208151910182865af16112d761133c565b908361139a565b8051908115159182611321575b50506112f45750565b7f5274afe70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b611334925060208091830101910161128f565b1538806112eb565b3d15611395573d9067ffffffffffffffff8211610e15576040519161138960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184610e44565b82523d6000602084013e565b606090565b906113d957508051156113af57805190602001fd5b7f1425ea420000000000000000000000000000000000000000000000000000000060005260046000fd5b8151158061142e575b6113ea575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b50803b156113e256fea2646970667358221220524063531dd6bdaa3a0b6ac3d4182660ade0b79872b172d613207b84421d4bd764736f6c634300081a00330000000000000000000000002f321372e8a9755cd2ca6114eb8da32a14f8100b000000000000000000000000c4922d64a24675e16e1586e3e3aa56c06fabe907000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000a86a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000000003000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000000006000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000000070000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c90816302443a6c14610d8e575080631c59e972146108f45780633a4beec8146108a257806359cfc1cc14610761578063715018a61461069d57806373787b97146103f557806379ba5097146102e75780638da5cb5b14610295578063cfb3647b14610243578063e30c3978146101f1578063f2fde38b1461012f5763f80e0a42146100a357600080fd5b3461012a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760243567ffffffffffffffff811161012a576100f56100fd913690600401610e9d565b600435610fde565b50506040805173ffffffffffffffffffffffffffffffffffffffff94909416845260208401929092525090f35b600080fd5b3461012a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043573ffffffffffffffffffffffffffffffffffffffff811680910361012a5761018761120e565b807fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015573ffffffffffffffffffffffffffffffffffffffff600054167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700600080a3005b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a573373ffffffffffffffffffffffffffffffffffffffff60015416036103c7577fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155600054337fffffffffffffffffffffffff000000000000000000000000000000000000000082161760005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b3461012a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043567ffffffffffffffff811161012a57610444903690600401610f3e565b60243567ffffffffffffffff811161012a573660238201121561012a57806004013561046f81610e85565b9161047d6040519384610e44565b8183526024602084019260061b8201019036821161012a57602401915b81831061063d575050506104ac61120e565b815190805182036105b95760005b8281106104c357005b806104d060019284610f9b565b516104db8287610f9b565b51600052600460205260406000209063ffffffff8151167fffffffffffffffff00000000000000000000000000000000000000000000000077ffffffffffffffffffffffffffffffffffffffff000000006020855494015160201b169216171790556105478186610f9b565b517f727da3b1d3a958e514361facf35c17ead5a3aebcc08d21df9ab1a0d8537f03666105b06105768487610f9b565b5160405191829182919091602073ffffffffffffffffffffffffffffffffffffffff81604084019563ffffffff8151168552015116910152565b0390a2016104ba565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f445043435450423a2077726f6e6720627269646765526f75746573206c656e6760448201527f74680000000000000000000000000000000000000000000000000000000000006064820152fd5b60408336031261012a576040519061065482610df9565b833563ffffffff8116810361012a57825260208401359073ffffffffffffffffffffffffffffffffffffffff8216820361012a578260209283604095015281520192019161049a565b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a576106d461120e565b7fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155600073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461012a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043567ffffffffffffffff811161012a576107b0903690600401610f3e565b6107b861120e565b60005b81518110156108a057806107d160019284610f9b565b516000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6040519161080183610df9565b5463ffffffff8116835260201c16602082015261081e8285610f9b565b516000526004602052600060408120557fee916dfd1f2dd308c32f05e4bdef9d466ff4cf2c53f7df1d308317f6693d45e561089761085c8487610f9b565b519260405191829182919091602073ffffffffffffffffffffffffffffffffffffffff81604084019563ffffffff8151168552015116910152565b0390a2016107bb565b005b3461012a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b3461012a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a5760043560243573ffffffffffffffffffffffffffffffffffffffff811680910361012a5760443567ffffffffffffffff811161012a57610967903690600401610e9d565b60643567ffffffffffffffff811161012a573660238201121561012a57806004013567ffffffffffffffff811161012a573691016024011161012a57468314610d30576109b49083610fde565b94919290938415610cd25773ffffffffffffffffffffffffffffffffffffffff1694610a296040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015283606482015260648152610a23608482610e44565b876112a7565b73ffffffffffffffffffffffffffffffffffffffff60035416604051600080602083017f095ea7b3000000000000000000000000000000000000000000000000000000008152610ad084610aa48988602484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101865285610e44565b835190828c5af1610adf61133c565b81610ca3575b5080610c99575b15610c40575b5050602063ffffffff608473ffffffffffffffffffffffffffffffffffffffff6003541693600060405195869485937f6fd3504e0000000000000000000000000000000000000000000000000000000085528960048601521660248401528860448401528b60648401525af18015610c3457610bd0575b7f7a1aaa549d494a115465b34eba936c63fadb6c733c73b1aa66b46ff791df584760e0878773ffffffffffffffffffffffffffffffffffffffff88888d896040519633885260208801526040870152606086015260808501521660a083015260c0820152a1005b60209594939195813d602011610c2c575b81610bee60209383610e44565b8101031261012a57519167ffffffffffffffff8316830361012a5793949293909290915073ffffffffffffffffffffffffffffffffffffffff610b69565b3d9150610be1565b6040513d6000823e3d90fd5b610a23610c9292604051907f095ea7b300000000000000000000000000000000000000000000000000000000602083015260248201526000604482015260448152610c8c606482610e44565b896112a7565b8780610af2565b50873b1515610aec565b8051801592508215610cb8575b50508a610ae5565b610ccb925060208091830101910161128f565b8a80610cb0565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f445043435450423a207a65726f20616d6f756e740000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f445043435450423a2073616d6520636861696e000000000000000000000000006044820152fd5b3461012a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012a57604090600435600052600460205273ffffffffffffffffffffffffffffffffffffffff826000205463ffffffff8116835260201c166020820152f35b6040810190811067ffffffffffffffff821117610e1557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610e1557604052565b67ffffffffffffffff8111610e155760051b60200190565b81601f8201121561012a57803590610eb482610e85565b92610ec26040519485610e44565b82845260208085019360061b8301019181831161012a57602001925b828410610eec575050505090565b60408483031261012a5760405190610f0382610df9565b84359073ffffffffffffffffffffffffffffffffffffffff8216820361012a5782602092604094528287013583820152815201930192610ede565b9080601f8301121561012a578135610f5581610e85565b92610f636040519485610e44565b81845260208085019260051b82010192831161012a57602001905b828210610f8b5750505090565b8135815260209182019101610f7e565b8051821015610faf5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919091600052600460205260406000209173ffffffffffffffffffffffffffffffffffffffff6040519361101185610df9565b5463ffffffff8116855260201c166020840190808252156111b05761104d73ffffffffffffffffffffffffffffffffffffffff8251168361122f565b9382518510156111525760208061108463ffffffff8451169773ffffffffffffffffffffffffffffffffffffffff86511696610f9b565b51015192604473ffffffffffffffffffffffffffffffffffffffff63ffffffff81600254169551169251169160405194859384927f78a0565e000000000000000000000000000000000000000000000000000000008452600484015260248301525afa908115610c34576000916110fc575b50938193565b6020813d60201161114a575b8161111560209383610e44565b8101031261114657519073ffffffffffffffffffffffffffffffffffffffff821682036111435750386110f6565b80fd5b5080fd5b3d9150611108565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f445043435450423a206261642062726964676520746f6b656e000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f445043435450423a2062726964676520726f757465206e6f7420666f756e64006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff6000541633036103c757565b80519160005b8381106112425750505090565b73ffffffffffffffffffffffffffffffffffffffff6112618285610f9b565b51511673ffffffffffffffffffffffffffffffffffffffff83161461128857600101611235565b9250505090565b9081602091031261012a5751801515810361012a5790565b60008073ffffffffffffffffffffffffffffffffffffffff6112de93169360208151910182865af16112d761133c565b908361139a565b8051908115159182611321575b50506112f45750565b7f5274afe70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b611334925060208091830101910161128f565b1538806112eb565b3d15611395573d9067ffffffffffffffff8211610e15576040519161138960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184610e44565b82523d6000602084013e565b606090565b906113d957508051156113af57805190602001fd5b7f1425ea420000000000000000000000000000000000000000000000000000000060005260046000fd5b8151158061142e575b6113ea575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b50803b156113e256fea2646970667358221220524063531dd6bdaa3a0b6ac3d4182660ade0b79872b172d613207b84421d4bd764736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002f321372e8a9755cd2ca6114eb8da32a14f8100b000000000000000000000000c4922d64a24675e16e1586e3e3aa56c06fabe907000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000a86a000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000a4b10000000000000000000000000000000000000000000000000000000000002105000000000000000000000000000000000000000000000000000000000000008900000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff850000000000000000000000000000000000000000000000000000000000000003000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000000000000000000000000000000000000000000006000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000000070000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359
-----Decoded View---------------
Arg [0] : _owner (address): 0x2F321372E8A9755CD2Ca6114eB8da32A14F8100b
Arg [1] : _tokenMinter (address): 0xc4922d64a24675E16e1586e3e3Aa56C06fABe907
Arg [2] : _cctpMessenger (address): 0xBd3fa81B58Ba92a82136038B25aDec7066af3155
Arg [3] : _toChainIds (uint256[]): 1,43114,10,42161,8453,137
Arg [4] : _bridgeRoutes (tuple[]): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput],System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
25 Constructor Arguments found :
Arg [0] : 0000000000000000000000002f321372e8a9755cd2ca6114eb8da32a14f8100b
Arg [1] : 000000000000000000000000c4922d64a24675e16e1586e3e3aa56c06fabe907
Arg [2] : 000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [7] : 000000000000000000000000000000000000000000000000000000000000a86a
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [9] : 000000000000000000000000000000000000000000000000000000000000a4b1
Arg [10] : 0000000000000000000000000000000000000000000000000000000000002105
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000089
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [14] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [16] : 000000000000000000000000b97ef9ef8734c71904d8002f8b6bc66dd9c48a6e
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [18] : 0000000000000000000000000b2c639c533813f4aa9d7837caf62653d097ff85
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [20] : 000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [22] : 000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [24] : 0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.