Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
NonceManager
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 80000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol";
import {INonceManager} from "./interfaces/INonceManager.sol";
import {ITypeAndVersion} from "@chainlink/shared/interfaces/ITypeAndVersion.sol";
import {AuthorizedCallers} from "@chainlink/shared/access/AuthorizedCallers.sol";
/// @title NonceManager
/// @notice NonceManager contract that manages sender nonces for the on/off ramps.
contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion {
error PreviousRampAlreadySet();
event PreviousRampsUpdated(uint64 indexed remoteChainSelector, PreviousRamps prevRamp);
event SkippedIncorrectNonce(uint64 sourceChainSelector, uint64 nonce, bytes sender);
/// @dev Struct that contains the previous on/off ramp addresses.
struct PreviousRamps {
address prevOnRamp; // Previous onRamp.
address prevOffRamp; // Previous offRamp.
}
/// @dev Struct with the chain selector and the previous on/off ramps, same as PreviousRamps but with the chain
/// selector so that an array of these can be passed to the applyPreviousRampsUpdates function.
struct PreviousRampsArgs {
uint64 remoteChainSelector; // ──╮ Chain selector.
bool overrideExistingRamps; // ──╯ Whether to override existing ramps.
PreviousRamps prevRamps; // Previous on/off ramps.
}
string public constant override typeAndVersion = "NonceManager 1.6.0";
/// @dev The previous on/off ramps per chain selector.
mapping(uint64 chainSelector => PreviousRamps previousRamps) private s_previousRamps;
/// @dev The current outbound nonce per sender used on the onRamp.
mapping(uint64 destChainSelector => mapping(address sender => uint64 outboundNonce)) private s_outboundNonces;
/// @dev The current inbound nonce per sender used on the offRamp.
/// Eventually in sync with the outbound nonce in the remote source chain NonceManager, used to enforce that messages
/// are executed in the same order they are sent (assuming they are DON).
mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 inboundNonce)) private s_inboundNonces;
constructor(
address[] memory authorizedCallers
) AuthorizedCallers(authorizedCallers) {}
/// @inheritdoc INonceManager
function getIncrementedOutboundNonce(
uint64 destChainSelector,
address sender
) external onlyAuthorizedCallers returns (uint64) {
uint64 outboundNonce = _getOutboundNonce(destChainSelector, sender) + 1;
s_outboundNonces[destChainSelector][sender] = outboundNonce;
return outboundNonce;
}
/// @notice Returns the outbound nonce for a given sender on a given destination chain.
/// @param destChainSelector The destination chain selector.
/// @param sender The sender address.
/// @return outboundNonce The outbound nonce.
function getOutboundNonce(uint64 destChainSelector, address sender) external view returns (uint64) {
return _getOutboundNonce(destChainSelector, sender);
}
function _getOutboundNonce(uint64 destChainSelector, address sender) private view returns (uint64) {
uint64 outboundNonce = s_outboundNonces[destChainSelector][sender];
// When introducing the NonceManager with existing lanes, we still want to have sequential nonces.
// Referencing the old onRamp preserves sequencing between updates.
if (outboundNonce == 0) {
address prevOnRamp = s_previousRamps[destChainSelector].prevOnRamp;
if (prevOnRamp != address(0)) {
// This gets the current nonce for a sender, not the already incremented nonce like getIncrementedOutboundNonce
// would return.
return IEVM2AnyOnRamp(prevOnRamp).getSenderNonce(sender);
}
}
return outboundNonce;
}
/// @inheritdoc INonceManager
function incrementInboundNonce(
uint64 sourceChainSelector,
uint64 expectedNonce,
bytes calldata sender
) external onlyAuthorizedCallers returns (bool) {
uint64 inboundNonce = _getInboundNonce(sourceChainSelector, sender) + 1;
if (inboundNonce != expectedNonce) {
// If the nonce is not the expected one, this means that there are still messages in flight so we skip
// the nonce increment.
emit SkippedIncorrectNonce(sourceChainSelector, expectedNonce, sender);
return false;
}
s_inboundNonces[sourceChainSelector][sender] = inboundNonce;
return true;
}
/// @notice Returns the inbound nonce for a given sender on a given source chain.
/// @param sourceChainSelector The source chain selector.
/// @param sender The encoded sender address.
/// @return inboundNonce The inbound nonce.
function getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) external view returns (uint64) {
return _getInboundNonce(sourceChainSelector, sender);
}
function _getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) private view returns (uint64) {
uint64 inboundNonce = s_inboundNonces[sourceChainSelector][sender];
// When introducing the NonceManager with existing lanes, we still want to have sequential nonces. Referencing the
// old offRamp to check the expected nonce if none is set for a given sender allows us to skip the current message
// in the current offRamp if it would not be the next according to the old offRamp. This preserves sequencing
// between updates.
if (inboundNonce == 0) {
address prevOffRamp = s_previousRamps[sourceChainSelector].prevOffRamp;
if (prevOffRamp != address(0)) {
// We only expect EVM previous offRamps here so we can safely decode the sender.
return IEVM2AnyOnRamp(prevOffRamp).getSenderNonce(abi.decode(sender, (address)));
}
}
return inboundNonce;
}
/// @notice Updates the previous ramps addresses.
/// @param previousRampsArgs The previous on/off ramps addresses.
function applyPreviousRampsUpdates(
PreviousRampsArgs[] calldata previousRampsArgs
) external onlyOwner {
for (uint256 i = 0; i < previousRampsArgs.length; ++i) {
PreviousRampsArgs calldata previousRampsArg = previousRampsArgs[i];
PreviousRamps storage prevRamps = s_previousRamps[previousRampsArg.remoteChainSelector];
// If the previous ramps are already set then they should not be updated.
// In versions prior to the introduction of the NonceManager contract, nonces were tracked in the on/off ramps.
// This config does a 1-time migration to move the nonce from on/off ramps into NonceManager.
if (prevRamps.prevOnRamp != address(0) || prevRamps.prevOffRamp != address(0)) {
// We do allow explicit overrides as an escape hatch in the case of a misconfiguration.
if (!previousRampsArg.overrideExistingRamps) {
revert PreviousRampAlreadySet();
}
}
prevRamps.prevOnRamp = previousRampsArg.prevRamps.prevOnRamp;
prevRamps.prevOffRamp = previousRampsArg.prevRamps.prevOffRamp;
emit PreviousRampsUpdated(previousRampsArg.remoteChainSelector, previousRampsArg.prevRamps);
}
}
/// @notice Gets the previous onRamp address for the given chain selector.
/// @param chainSelector The chain selector.
/// @return previousRamps The previous on/offRamp addresses.
function getPreviousRamps(
uint64 chainSelector
) external view returns (PreviousRamps memory) {
return s_previousRamps[chainSelector];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IEVM2AnyOnRampClient} from "./IEVM2AnyOnRampClient.sol";
interface IEVM2AnyOnRamp is IEVM2AnyOnRampClient {
/// @notice Gets the next sequence number to be used in the onRamp.
/// @return the next sequence number to be used.
function getExpectedNextSequenceNumber() external view returns (uint64);
/// @notice Get the current nonce for a given sender.
/// @param sender The sender to get the nonce for.
/// @return nonce The current nonce for the sender.
function getSenderNonce(
address sender
) external view returns (uint64 nonce);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolV1} from "./IPool.sol";
import {Client} from "../libraries/Client.sol";
import {IERC20} from "@chainlink/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
interface IEVM2AnyOnRampClient {
/// @notice Get the fee for a given ccip message.
/// @param destChainSelector The destination chain selector.
/// @param message The message to calculate the cost for.
/// @return fee The calculated fee.
function getFee(uint64 destChainSelector, Client.EVM2AnyMessage calldata message) external view returns (uint256 fee);
/// @notice Get the pool for a specific token.
/// @param destChainSelector The destination chain selector.
/// @param sourceToken The source chain token to get the pool for.
/// @return pool Token pool.
function getPoolBySourceToken(uint64 destChainSelector, IERC20 sourceToken) external view returns (IPoolV1);
/// @notice Gets a list of all supported source chain tokens.
/// @param destChainSelector The destination chain selector.
/// @return tokens The addresses of all tokens that this onRamp supports the given destination chain.
function getSupportedTokens(
uint64 destChainSelector
) external view returns (address[] memory tokens);
/// @notice Send a message to the remote chain.
/// @dev only callable by the Router.
/// @dev approve() must have already been called on the token using the this ramp address as the spender.
/// @dev if the contract is paused, this function will revert.
/// @param destChainSelector The destination chain selector.
/// @param message Message struct to send.
/// @param feeTokenAmount Amount of fee tokens for payment.
/// @param originalSender The original initiator of the CCIP request.
/// @return messageId The message id.
function forwardFromRouter(
uint64 destChainSelector,
Client.EVM2AnyMessage memory message,
uint256 feeTokenAmount,
address originalSender
) external returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Contract interface that allows managing sender nonces.
interface INonceManager {
/// @notice Increments the outbound nonce for a given sender on a given destination chain.
/// @param destChainSelector The destination chain selector.
/// @param sender The sender address.
/// @return incrementedOutboundNonce The new outbound nonce.
function getIncrementedOutboundNonce(uint64 destChainSelector, address sender) external returns (uint64);
/// @notice Increments the inbound nonce for a given sender on a given source chain.
/// @notice The increment is only applied if the resulting nonce matches the expectedNonce.
/// @param sourceChainSelector The destination chain selector.
/// @param expectedNonce The expected inbound nonce.
/// @param sender The encoded sender address.
/// @return incremented True if the nonce was incremented, false otherwise.
function incrementInboundNonce(
uint64 sourceChainSelector,
uint64 expectedNonce,
bytes calldata sender
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Pool} from "../libraries/Pool.sol";
import {IERC165} from "@chainlink/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";
/// @notice Shared public interface for multiple V1 pool types.
/// Each pool type handles a different child token model e.g. lock/unlock, mint/burn.
interface IPoolV1 is IERC165 {
/// @notice Lock tokens into the pool or burn the tokens.
/// @param lockOrBurnIn Encoded data fields for the processing of tokens on the source chain.
/// @return lockOrBurnOut Encoded data fields for the processing of tokens on the destination chain.
function lockOrBurn(
Pool.LockOrBurnInV1 calldata lockOrBurnIn
) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut);
/// @notice Releases or mints tokens to the receiver address.
/// @param releaseOrMintIn All data required to release or mint tokens.
/// @return releaseOrMintOut The amount of tokens released or minted on the local chain, denominated
/// in the local token's decimals.
/// @dev The offramp asserts that the balanceOf of the receiver has been incremented by exactly the number
/// of tokens that is returned in ReleaseOrMintOutV1.destinationAmount. If the amounts do not match, the tx reverts.
function releaseOrMint(
Pool.ReleaseOrMintInV1 calldata releaseOrMintIn
) external returns (Pool.ReleaseOrMintOutV1 memory);
/// @notice Checks whether a remote chain is supported in the token pool.
/// @param remoteChainSelector The selector of the remote chain.
/// @return true if the given chain is a permissioned remote chain.
function isSupportedChain(
uint64 remoteChainSelector
) external view returns (bool);
/// @notice Returns if the token pool supports the given token.
/// @param token The address of the token.
/// @return true if the token is supported by the pool.
function isSupportedToken(
address token
) external view returns (bool);
}// 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(EVMExtraArgsV2).
}
// Tag to indicate only a gas limit. Only usable for EVM as destination chain.
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);
}
// Tag to indicate a gas limit (or dest chain equivalent processing units) and Out Of Order Execution. This tag is
// available for multiple chain families. If there is no chain family specific tag, this is the default available
// for a chain.
// Note: not available for Solana VM based chains.
bytes4 public constant GENERIC_EXTRA_ARGS_V2_TAG = 0x181dcf10;
/// @param gasLimit: gas limit for the callback on the destination chain.
/// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to
/// other messages from the same sender. This value's default varies by chain. On some chains, a particular value is
/// enforced, meaning if the expected value is not set, the message request will revert.
/// @dev Fully compatible with the previously existing EVMExtraArgsV2.
struct GenericExtraArgsV2 {
uint256 gasLimit;
bool allowOutOfOrderExecution;
}
// Extra args tag for chains that use the Solana VM.
bytes4 public constant SVM_EXTRA_ARGS_V1_TAG = 0x1f3b3aba;
struct SVMExtraArgsV1 {
uint32 computeUnits;
uint64 accountIsWritableBitmap;
bool allowOutOfOrderExecution;
bytes32 tokenReceiver;
bytes32[] accounts;
}
/// @dev The maximum number of accounts that can be passed in SVMExtraArgs.
uint256 public constant SVM_EXTRA_ARGS_MAX_ACCOUNTS = 64;
function _argsToBytes(
GenericExtraArgsV2 memory extraArgs
) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(GENERIC_EXTRA_ARGS_V2_TAG, extraArgs);
}
function _svmArgsToBytes(
SVMExtraArgsV1 memory extraArgs
) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(SVM_EXTRA_ARGS_V1_TAG, extraArgs);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice This library contains various token pool functions to aid constructing the return data.
library Pool {
// The tag used to signal support for the pool v1 standard.
// bytes4(keccak256("CCIP_POOL_V1"))
bytes4 public constant CCIP_POOL_V1 = 0xaff2afbf;
// The number of bytes in the return data for a pool v1 releaseOrMint call.
// This should match the size of the ReleaseOrMintOutV1 struct.
uint16 public constant CCIP_POOL_V1_RET_BYTES = 32;
// The default max number of bytes in the return data for a pool v1 lockOrBurn call.
// This data can be used to send information to the destination chain token pool. Can be overwritten
// in the TokenTransferFeeConfig.destBytesOverhead if more data is required.
uint32 public constant CCIP_LOCK_OR_BURN_V1_RET_BYTES = 32;
struct LockOrBurnInV1 {
bytes receiver; // The recipient of the tokens on the destination chain, abi encoded.
uint64 remoteChainSelector; // ─╮ The chain ID of the destination chain.
address originalSender; // ─────╯ The original sender of the tx on the source chain.
uint256 amount; // The amount of tokens to lock or burn, denominated in the source token's decimals.
address localToken; // The address on this chain of the token to lock or burn.
}
struct LockOrBurnOutV1 {
// The address of the destination token, abi encoded in the case of EVM chains.
// This value is UNTRUSTED as any pool owner can return whatever value they want.
bytes destTokenAddress;
// Optional pool data to be transferred to the destination chain. Be default this is capped at
// CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead
// has to be set for the specific token.
bytes destPoolData;
}
struct ReleaseOrMintInV1 {
bytes originalSender; // The original sender of the tx on the source chain.
uint64 remoteChainSelector; // ─╮ The chain ID of the source chain.
address receiver; // ───────────╯ The recipient of the tokens on the destination chain.
uint256 amount; // The amount of tokens to release or mint, denominated in the source token's decimals.
address localToken; // The address on this chain of the token to release or mint.
/// @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the
/// expected pool address for the given remoteChainSelector.
bytes sourcePoolAddress; // The address of the source pool, abi encoded in the case of EVM chains.
bytes sourcePoolData; // The data received from the source pool to process the release or mint.
/// @dev WARNING: offchainTokenData is untrusted data.
bytes offchainTokenData; // The offchain data to process the release or mint.
}
struct ReleaseOrMintOutV1 {
// The number of tokens released or minted on the destination chain, denominated in the local token's decimals.
// This value is expected to be equal to the ReleaseOrMintInV1.amount in the case where the source and destination
// chain have the same number of decimals.
uint256 destinationAmount;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
import {Ownable2StepMsgSender} from "./Ownable2StepMsgSender.sol";
import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol";
/// @title The AuthorizedCallers contract
/// @notice A contract that manages multiple authorized callers. Enables restricting access to certain functions to a set of addresses.
contract AuthorizedCallers is Ownable2StepMsgSender {
using EnumerableSet for EnumerableSet.AddressSet;
event AuthorizedCallerAdded(address caller);
event AuthorizedCallerRemoved(address caller);
error UnauthorizedCaller(address caller);
error ZeroAddressNotAllowed();
/// @notice Update args for changing the authorized callers
struct AuthorizedCallerArgs {
address[] addedCallers;
address[] removedCallers;
}
/// @dev Set of authorized callers
EnumerableSet.AddressSet internal s_authorizedCallers;
/// @param authorizedCallers the authorized callers to set
constructor(address[] memory authorizedCallers) {
_applyAuthorizedCallerUpdates(
AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)})
);
}
/// @return authorizedCallers Returns all authorized callers
function getAllAuthorizedCallers() external view returns (address[] memory) {
return s_authorizedCallers.values();
}
/// @notice Updates the list of authorized callers
/// @param authorizedCallerArgs Callers to add and remove. Removals are performed first.
function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyOwner {
_applyAuthorizedCallerUpdates(authorizedCallerArgs);
}
/// @notice Updates the list of authorized callers
/// @param authorizedCallerArgs Callers to add and remove. Removals are performed first.
function _applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) internal {
address[] memory removedCallers = authorizedCallerArgs.removedCallers;
for (uint256 i = 0; i < removedCallers.length; ++i) {
address caller = removedCallers[i];
if (s_authorizedCallers.remove(caller)) {
emit AuthorizedCallerRemoved(caller);
}
}
address[] memory addedCallers = authorizedCallerArgs.addedCallers;
for (uint256 i = 0; i < addedCallers.length; ++i) {
address caller = addedCallers[i];
if (caller == address(0)) {
revert ZeroAddressNotAllowed();
}
s_authorizedCallers.add(caller);
emit AuthorizedCallerAdded(caller);
}
}
/// @notice Checks the sender and reverts if it is anyone other than a listed authorized caller.
function _validateCaller() internal view {
if (!s_authorizedCallers.contains(msg.sender)) {
revert UnauthorizedCaller(msg.sender);
}
}
/// @notice Checks the sender and reverts if it is anyone other than a listed authorized caller.
modifier onlyAuthorizedCallers() {
_validateCaller();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {IOwnable} from "../interfaces/IOwnable.sol";
/// @notice A minimal contract that implements 2-step ownership transfer and nothing more. It's made to be minimal
/// to reduce the impact of the bytecode size on any contract that inherits from it.
contract Ownable2Step is IOwnable {
/// @notice The pending owner is the address to which ownership may be transferred.
address private s_pendingOwner;
/// @notice The owner is the current owner of the contract.
/// @dev The owner is the second storage variable so any implementing contract could pack other state with it
/// instead of the much less used s_pendingOwner.
address private s_owner;
error OwnerCannotBeZero();
error MustBeProposedOwner();
error CannotTransferToSelf();
error OnlyCallableByOwner();
event OwnershipTransferRequested(address indexed from, address indexed to);
event OwnershipTransferred(address indexed from, address indexed to);
constructor(address newOwner, address pendingOwner) {
if (newOwner == address(0)) {
revert OwnerCannotBeZero();
}
s_owner = newOwner;
if (pendingOwner != address(0)) {
_transferOwnership(pendingOwner);
}
}
/// @notice Get the current owner
function owner() public view override returns (address) {
return s_owner;
}
/// @notice Allows an owner to begin transferring ownership to a new address. The new owner needs to call
/// `acceptOwnership` to accept the transfer before any permissions are changed.
/// @param to The address to which ownership will be transferred.
function transferOwnership(address to) public override onlyOwner {
_transferOwnership(to);
}
/// @notice validate, transfer ownership, and emit relevant events
/// @param to The address to which ownership will be transferred.
function _transferOwnership(address to) private {
if (to == msg.sender) {
revert CannotTransferToSelf();
}
s_pendingOwner = to;
emit OwnershipTransferRequested(s_owner, to);
}
/// @notice Allows an ownership transfer to be completed by the recipient.
function acceptOwnership() external override {
if (msg.sender != s_pendingOwner) {
revert MustBeProposedOwner();
}
address oldOwner = s_owner;
s_owner = msg.sender;
s_pendingOwner = address(0);
emit OwnershipTransferred(oldOwner, msg.sender);
}
/// @notice validate access
function _validateOwnership() internal view {
if (msg.sender != s_owner) {
revert OnlyCallableByOwner();
}
}
/// @notice Reverts if called by anyone other than the contract owner.
modifier onlyOwner() {
_validateOwnership();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {Ownable2Step} from "./Ownable2Step.sol";
/// @notice Sets the msg.sender to be the owner of the contract and does not set a pending owner.
contract Ownable2StepMsgSender is Ownable2Step {
constructor() Ownable2Step(msg.sender, address(0)) {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwnable {
function owner() external returns (address);
function transferOwnership(address recipient) external;
function acceptOwnership() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ITypeAndVersion {
function typeAndVersion() external pure returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"evmVersion": "paris",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "none",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 80000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"forge-std/=node_modules/@chainlink/contracts/src/v0.8/vendor/forge-std/src/",
"@chainlink/=node_modules/@chainlink/contracts/src/v0.8/"
],
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address[]","name":"authorizedCallers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotTransferToSelf","type":"error"},{"inputs":[],"name":"MustBeProposedOwner","type":"error"},{"inputs":[],"name":"OnlyCallableByOwner","type":"error"},{"inputs":[],"name":"OwnerCannotBeZero","type":"error"},{"inputs":[],"name":"PreviousRampAlreadySet","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"UnauthorizedCaller","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"AuthorizedCallerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"AuthorizedCallerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"components":[{"internalType":"address","name":"prevOnRamp","type":"address"},{"internalType":"address","name":"prevOffRamp","type":"address"}],"indexed":false,"internalType":"struct NonceManager.PreviousRamps","name":"prevRamp","type":"tuple"}],"name":"PreviousRampsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"sender","type":"bytes"}],"name":"SkippedIncorrectNonce","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"addedCallers","type":"address[]"},{"internalType":"address[]","name":"removedCallers","type":"address[]"}],"internalType":"struct AuthorizedCallers.AuthorizedCallerArgs","name":"authorizedCallerArgs","type":"tuple"}],"name":"applyAuthorizedCallerUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"internalType":"bool","name":"overrideExistingRamps","type":"bool"},{"components":[{"internalType":"address","name":"prevOnRamp","type":"address"},{"internalType":"address","name":"prevOffRamp","type":"address"}],"internalType":"struct NonceManager.PreviousRamps","name":"prevRamps","type":"tuple"}],"internalType":"struct NonceManager.PreviousRampsArgs[]","name":"previousRampsArgs","type":"tuple[]"}],"name":"applyPreviousRampsUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllAuthorizedCallers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"}],"name":"getInboundNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"address","name":"sender","type":"address"}],"name":"getIncrementedOutboundNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"address","name":"sender","type":"address"}],"name":"getOutboundNonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainSelector","type":"uint64"}],"name":"getPreviousRamps","outputs":[{"components":[{"internalType":"address","name":"prevOnRamp","type":"address"},{"internalType":"address","name":"prevOffRamp","type":"address"}],"internalType":"struct NonceManager.PreviousRamps","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"uint64","name":"expectedNonce","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"}],"name":"incrementInboundNonce","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523461020f576117738038038061001981610214565b92833981019060208183031261020f578051906001600160401b03821161020f570181601f8201121561020f578051916001600160401b0383116101c8578260051b9160208061006a818601610214565b80968152019382010191821161020f57602001915b8183106101ef578333156101de57600180546001600160a01b031916331790556020906100ab82610214565b60008152600036813760408051929083016001600160401b038111848210176101c8576040528252808383015260005b8151811015610142576001906001600160a01b036100f98285610239565b5116856101058261027b565b610112575b5050016100db565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1858561010a565b50505160005b81518110156101b9576001600160a01b036101638284610239565b51169081156101a8577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef848361019a600195610379565b50604051908152a101610148565b6342bcdf7f60e11b60005260046000fd5b60405161139990816103da8239f35b634e487b7160e01b600052604160045260246000fd5b639b15e16f60e01b60005260046000fd5b82516001600160a01b038116810361020f5781526020928301920161007f565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176101c857604052565b805182101561024d5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561024d5760005260206000200190600090565b600081815260036020526040902054801561037257600019810181811161035c5760025460001981019190821161035c5780820361030b575b50505060025480156102f557600019016102cf816002610263565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61034461031c61032d936002610263565b90549060031b1c9283926002610263565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806102b4565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146103d357600254680100000000000000008110156101c8576103ba61032d8260018594016002556002610263565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b60003560e01c908163181f5a7714610a94575080632451a627146109a6578063294b5630146108ff57806379ba5097146108165780637a75a094146105f95780638da5cb5b146105a757806391a2749a146103bd578063bf18402a14610373578063c9223625146102fe578063e0e03cae14610272578063ea458c0c1461019b5763f2fde38b146100a357600080fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043573ffffffffffffffffffffffffffffffffffffffff8116809103610196576100fb610e81565b33811461016c57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206101d4610bef565b6101dc610c06565b6101e461113a565b67ffffffffffffffff6101ff6101fa8385610f2f565b610d1e565b92166000526005835273ffffffffffffffffffffffffffffffffffffffff604060002091166000528252604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000082541617905567ffffffffffffffff60405191168152f35b346101965760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576102a9610bef565b60243567ffffffffffffffff81168103610196576044359067ffffffffffffffff8211610196576020926102e46102f4933690600401610cba565b9290916102ef61113a565b610d6d565b6040519015158152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610335610bef565b60243567ffffffffffffffff81116101965760209161035b610361923690600401610cba565b9161104a565b67ffffffffffffffff60405191168152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206103616103af610bef565b6103b7610c06565b90610f2f565b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff81116101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610196576040519061043782610b63565b806004013567ffffffffffffffff81116101965761045b9060043691840101610c4a565b825260248101359067ffffffffffffffff82116101965760046104819236920101610c4a565b60208201908152610490610e81565b519060005b8251811015610508578073ffffffffffffffffffffffffffffffffffffffff6104c060019386610ecc565b51166104cb81611196565b6104d7575b5001610495565b60207fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1846104d0565b505160005b81518110156105a55773ffffffffffffffffffffffffffffffffffffffff6105358284610ecc565b511690811561057b577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef60208361056d60019561132c565b50604051908152a10161050d565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b005b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff8111610196573660238201121561019657806004013567ffffffffffffffff8111610196573660248260071b8401011161019657610670610e81565b60005b818110156105a55760008160071b84016024810167ffffffffffffffff61069982610ce8565b1683526004602052604083209273ffffffffffffffffffffffffffffffffffffffff845416158015906107f3575b6107b3575b5060408273ffffffffffffffffffffffffffffffffffffffff6107a667ffffffffffffffff6107907fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c3319966084606460019c9b9a01968661072b89610cfd565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008c5416178b550198858c6107608c610cfd565b920191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055610ce8565b16958261079e865195610c29565b168452610c29565b166020820152a201610673565b60448301358015908115036107ef57156106cc57807fc6117ae20000000000000000000000000000000000000000000000000000000060049252fd5b5080fd5b5073ffffffffffffffffffffffffffffffffffffffff60018501541615156106c7565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760005473ffffffffffffffffffffffffffffffffffffffff811633036108d5577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965767ffffffffffffffff61093f610bef565b6000602060405161094f81610b63565b828152015216600052600460205260408060002073ffffffffffffffffffffffffffffffffffffffff825161098381610b63565b602082600181865416958685520154169101908152835192835251166020820152f35b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576040518060206002549283815201809260026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b818110610a7e5750505081610a25910382610bae565b6040519182916020830190602084525180915260408301919060005b818110610a4f575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101610a41565b8254845260209093019260019283019201610a0f565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610acc81610b63565b601281527f4e6f6e63654d616e6167657220312e362e300000000000000000000000000000602082015260405190602082528181519182602083015260005b838110610b4b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610b0b565b6040810190811067ffffffffffffffff821117610b7f57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b7f57604052565b6004359067ffffffffffffffff8216820361019657565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b9080601f830112156101965781359167ffffffffffffffff8311610b7f578260051b9060405193610c7e6020840186610bae565b845260208085019282010192831161019657602001905b828210610ca25750505090565b60208091610caf84610c29565b815201910190610c95565b9181601f840112156101965782359167ffffffffffffffff8311610196576020838186019501011161019657565b3567ffffffffffffffff811681036101965790565b3573ffffffffffffffffffffffffffffffffffffffff811681036101965790565b67ffffffffffffffff60019116019067ffffffffffffffff8211610d3e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291909267ffffffffffffffff610d886101fa85858561104a565b94168067ffffffffffffffff861603610df8575067ffffffffffffffff9291836020921660005260068252604060002083604051948593843782019081520301902091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600190565b7f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f9450601f8467ffffffffffffffff956080957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09460405198899716875260208701526060604087015281606087015286860137600085828601015201168101030190a1600090565b73ffffffffffffffffffffffffffffffffffffffff600154163303610ea257565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b8051821015610ee05760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90816020910312610196575167ffffffffffffffff811681036101965790565b67ffffffffffffffff1690816000526005602052604060002073ffffffffffffffffffffffffffffffffffffffff821660005260205267ffffffffffffffff60406000205416918215610f8157505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002054169081610fb057505090565b6020919250602473ffffffffffffffffffffffffffffffffffffffff9160405194859384927f856c82470000000000000000000000000000000000000000000000000000000084521660048301525afa90811561103e57600091611012575090565b611034915060203d602011611037575b61102c8183610bae565b810190610f0f565b90565b503d611022565b6040513d6000823e3d90fd5b67ffffffffffffffff90929192169182600052600660205267ffffffffffffffff60406000206020604051809286868337868201908152030190205416928315611095575b50505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff6001604060002001541691821561108f57819293509060209181010312610196573573ffffffffffffffffffffffffffffffffffffffff8116809103610196576020906024604051809481937f856c824700000000000000000000000000000000000000000000000000000000835260048301525afa90811561103e57600091611012575090565b3360005260036020526040600020541561115057565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b8054821015610ee05760005260206000200190600090565b6000818152600360205260409020548015611325577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111610d3e57600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211610d3e578082036112b6575b5050506002548015611287577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161124481600261117e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61130d6112c76112d893600261117e565b90549060031b1c928392600261117e565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600052600360205260406000205538808061120b565b5050600090565b806000526003602052604060002054156000146113865760025468010000000000000000811015610b7f5761136d6112d8826001859401600255600261117e565b9055600254906000526003602052604060002055600190565b5060009056fea164736f6c634300081a000a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c908163181f5a7714610a94575080632451a627146109a6578063294b5630146108ff57806379ba5097146108165780637a75a094146105f95780638da5cb5b146105a757806391a2749a146103bd578063bf18402a14610373578063c9223625146102fe578063e0e03cae14610272578063ea458c0c1461019b5763f2fde38b146100a357600080fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043573ffffffffffffffffffffffffffffffffffffffff8116809103610196576100fb610e81565b33811461016c57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206101d4610bef565b6101dc610c06565b6101e461113a565b67ffffffffffffffff6101ff6101fa8385610f2f565b610d1e565b92166000526005835273ffffffffffffffffffffffffffffffffffffffff604060002091166000528252604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000082541617905567ffffffffffffffff60405191168152f35b346101965760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576102a9610bef565b60243567ffffffffffffffff81168103610196576044359067ffffffffffffffff8211610196576020926102e46102f4933690600401610cba565b9290916102ef61113a565b610d6d565b6040519015158152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610335610bef565b60243567ffffffffffffffff81116101965760209161035b610361923690600401610cba565b9161104a565b67ffffffffffffffff60405191168152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206103616103af610bef565b6103b7610c06565b90610f2f565b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff81116101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610196576040519061043782610b63565b806004013567ffffffffffffffff81116101965761045b9060043691840101610c4a565b825260248101359067ffffffffffffffff82116101965760046104819236920101610c4a565b60208201908152610490610e81565b519060005b8251811015610508578073ffffffffffffffffffffffffffffffffffffffff6104c060019386610ecc565b51166104cb81611196565b6104d7575b5001610495565b60207fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1846104d0565b505160005b81518110156105a55773ffffffffffffffffffffffffffffffffffffffff6105358284610ecc565b511690811561057b577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef60208361056d60019561132c565b50604051908152a10161050d565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b005b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff8111610196573660238201121561019657806004013567ffffffffffffffff8111610196573660248260071b8401011161019657610670610e81565b60005b818110156105a55760008160071b84016024810167ffffffffffffffff61069982610ce8565b1683526004602052604083209273ffffffffffffffffffffffffffffffffffffffff845416158015906107f3575b6107b3575b5060408273ffffffffffffffffffffffffffffffffffffffff6107a667ffffffffffffffff6107907fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c3319966084606460019c9b9a01968661072b89610cfd565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008c5416178b550198858c6107608c610cfd565b920191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055610ce8565b16958261079e865195610c29565b168452610c29565b166020820152a201610673565b60448301358015908115036107ef57156106cc57807fc6117ae20000000000000000000000000000000000000000000000000000000060049252fd5b5080fd5b5073ffffffffffffffffffffffffffffffffffffffff60018501541615156106c7565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760005473ffffffffffffffffffffffffffffffffffffffff811633036108d5577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965767ffffffffffffffff61093f610bef565b6000602060405161094f81610b63565b828152015216600052600460205260408060002073ffffffffffffffffffffffffffffffffffffffff825161098381610b63565b602082600181865416958685520154169101908152835192835251166020820152f35b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576040518060206002549283815201809260026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b818110610a7e5750505081610a25910382610bae565b6040519182916020830190602084525180915260408301919060005b818110610a4f575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101610a41565b8254845260209093019260019283019201610a0f565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610acc81610b63565b601281527f4e6f6e63654d616e6167657220312e362e300000000000000000000000000000602082015260405190602082528181519182602083015260005b838110610b4b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610b0b565b6040810190811067ffffffffffffffff821117610b7f57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b7f57604052565b6004359067ffffffffffffffff8216820361019657565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b9080601f830112156101965781359167ffffffffffffffff8311610b7f578260051b9060405193610c7e6020840186610bae565b845260208085019282010192831161019657602001905b828210610ca25750505090565b60208091610caf84610c29565b815201910190610c95565b9181601f840112156101965782359167ffffffffffffffff8311610196576020838186019501011161019657565b3567ffffffffffffffff811681036101965790565b3573ffffffffffffffffffffffffffffffffffffffff811681036101965790565b67ffffffffffffffff60019116019067ffffffffffffffff8211610d3e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291909267ffffffffffffffff610d886101fa85858561104a565b94168067ffffffffffffffff861603610df8575067ffffffffffffffff9291836020921660005260068252604060002083604051948593843782019081520301902091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600190565b7f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f9450601f8467ffffffffffffffff956080957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09460405198899716875260208701526060604087015281606087015286860137600085828601015201168101030190a1600090565b73ffffffffffffffffffffffffffffffffffffffff600154163303610ea257565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b8051821015610ee05760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90816020910312610196575167ffffffffffffffff811681036101965790565b67ffffffffffffffff1690816000526005602052604060002073ffffffffffffffffffffffffffffffffffffffff821660005260205267ffffffffffffffff60406000205416918215610f8157505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002054169081610fb057505090565b6020919250602473ffffffffffffffffffffffffffffffffffffffff9160405194859384927f856c82470000000000000000000000000000000000000000000000000000000084521660048301525afa90811561103e57600091611012575090565b611034915060203d602011611037575b61102c8183610bae565b810190610f0f565b90565b503d611022565b6040513d6000823e3d90fd5b67ffffffffffffffff90929192169182600052600660205267ffffffffffffffff60406000206020604051809286868337868201908152030190205416928315611095575b50505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff6001604060002001541691821561108f57819293509060209181010312610196573573ffffffffffffffffffffffffffffffffffffffff8116809103610196576020906024604051809481937f856c824700000000000000000000000000000000000000000000000000000000835260048301525afa90811561103e57600091611012575090565b3360005260036020526040600020541561115057565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b8054821015610ee05760005260206000200190600090565b6000818152600360205260409020548015611325577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111610d3e57600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211610d3e578082036112b6575b5050506002548015611287577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161124481600261117e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61130d6112c76112d893600261117e565b90549060031b1c928392600261117e565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600052600360205260406000205538808061120b565b5050600090565b806000526003602052604060002054156000146113865760025468010000000000000000811015610b7f5761136d6112d8826001859401600255600261117e565b9055600254906000526003602052604060002055600190565b5060009056fea164736f6c634300081a000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : authorizedCallers (address[]):
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
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.