S Price: $0.068314 (+0.44%)
Gas: 55 Gwei

Contract

0x321520f89076836a0e306E4a41BCCd1BFd2189D9

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0.558553401221569426 S

S Value

$0.04 (@ $0.07/S)

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Send611748392026-01-26 7:17:239 hrs ago1769411843IN
0x321520f8...BFd2189D9
9.04983946 S0.012223250
Send605092292026-01-16 11:31:4010 days ago1768563100IN
0x321520f8...BFd2189D9
7.06979229 S0.0132065455
Send591977502025-12-29 20:26:4127 days ago1767040001IN
0x321520f8...BFd2189D9
1.33648705 S0.012391950
Send588816582025-12-25 13:42:2932 days ago1766670149IN
0x321520f8...BFd2189D9
7.99880447 S0.0115971250.0001
Send557583122025-11-19 8:42:3168 days ago1763541751IN
0x321520f8...BFd2189D9
7.69622295 S0.0121243550
Send557491132025-11-19 6:29:2668 days ago1763533766IN
0x321520f8...BFd2189D9
1.03945236 S0.0132569855
Send534885372025-11-04 2:31:1683 days ago1762223476IN
0x321520f8...BFd2189D9
0.88927341 S0.0133360755
Send528345752025-10-31 17:10:2086 days ago1761930620IN
0x321520f8...BFd2189D9
0.76843806 S0.0133360755
Send527896652025-10-31 11:20:4887 days ago1761909648IN
0x321520f8...BFd2189D9
0.78427315 S0.0133360755
Send525957622025-10-30 10:14:4188 days ago1761819281IN
0x321520f8...BFd2189D9
0.71632784 S0.0133346955
Send522705962025-10-28 18:09:4189 days ago1761674981IN
0x321520f8...BFd2189D9
0.74442345 S0.0121237250.0001
Send522678692025-10-28 17:49:4089 days ago1761673780IN
0x321520f8...BFd2189D9
0.99790593 S0.0130706955
Send521882592025-10-28 8:07:4690 days ago1761638866IN
0x321520f8...BFd2189D9
0.66189483 S0.0133333255
Send514348142025-10-21 17:12:1896 days ago1761066738IN
0x321520f8...BFd2189D9
0.7703775 S0.0114982250.0001
Send514347852025-10-21 17:12:0496 days ago1761066724IN
0x321520f8...BFd2189D9
0.66357683 S0.0118824550
Send514322562025-10-21 16:52:0997 days ago1761065529IN
0x321520f8...BFd2189D9
0.573437 S0.0119062150.1
Send513806842025-10-21 6:06:2697 days ago1761026786IN
0x321520f8...BFd2189D9
5.31354006 S0.0121243550
Send508172972025-10-16 6:19:23102 days ago1760595563IN
0x321520f8...BFd2189D9
0.79589914 S0.0132562655
Send500528062025-10-10 20:10:59107 days ago1760127059IN
0x321520f8...BFd2189D9
30.82822909 S0.0121243550
Send500258352025-10-10 16:02:15108 days ago1760112135IN
0x321520f8...BFd2189D9
95.17575475 S0.0121243550
Send494954802025-10-06 7:00:25112 days ago1759734025IN
0x321520f8...BFd2189D9
0.40064631 S0.0122911550
Send494946592025-10-06 6:48:25112 days ago1759733305IN
0x321520f8...BFd2189D9
0.40131661 S0.0122911550
Send488911332025-09-30 19:59:15117 days ago1759262355IN
0x321520f8...BFd2189D9
0.55565836 S0.0141932550.0000125
Send484671442025-09-27 16:24:49121 days ago1758990289IN
0x321520f8...BFd2189D9
7.426847 S0.0121249550
Send479055572025-09-23 13:09:06125 days ago1758632946IN
0x321520f8...BFd2189D9
0.64907115 S0.0133346955
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
611748392026-01-26 7:17:239 hrs ago1769411843
0x321520f8...BFd2189D9
9.04983946 S
605092292026-01-16 11:31:4010 days ago1768563100
0x321520f8...BFd2189D9
7.06979229 S
591977502025-12-29 20:26:4127 days ago1767040001
0x321520f8...BFd2189D9
1.33648705 S
588816582025-12-25 13:42:2932 days ago1766670149
0x321520f8...BFd2189D9
7.99880447 S
557583122025-11-19 8:42:3168 days ago1763541751
0x321520f8...BFd2189D9
7.69622295 S
557491132025-11-19 6:29:2668 days ago1763533766
0x321520f8...BFd2189D9
1.03945236 S
534885372025-11-04 2:31:1683 days ago1762223476
0x321520f8...BFd2189D9
0.88927341 S
528345752025-10-31 17:10:2086 days ago1761930620
0x321520f8...BFd2189D9
0.76843806 S
527896652025-10-31 11:20:4887 days ago1761909648
0x321520f8...BFd2189D9
0.78427315 S
525957622025-10-30 10:14:4188 days ago1761819281
0x321520f8...BFd2189D9
0.71632784 S
522705962025-10-28 18:09:4189 days ago1761674981
0x321520f8...BFd2189D9
0.74442345 S
522678692025-10-28 17:49:4089 days ago1761673780
0x321520f8...BFd2189D9
0.99790593 S
521882592025-10-28 8:07:4690 days ago1761638866
0x321520f8...BFd2189D9
0.66189483 S
514348142025-10-21 17:12:1896 days ago1761066738
0x321520f8...BFd2189D9
0.7703775 S
514347852025-10-21 17:12:0496 days ago1761066724
0x321520f8...BFd2189D9
0.66357683 S
514322562025-10-21 16:52:0997 days ago1761065529
0x321520f8...BFd2189D9
0.573437 S
513806842025-10-21 6:06:2697 days ago1761026786
0x321520f8...BFd2189D9
5.31354006 S
508172972025-10-16 6:19:23102 days ago1760595563
0x321520f8...BFd2189D9
0.79589914 S
500528062025-10-10 20:10:59107 days ago1760127059
0x321520f8...BFd2189D9
30.82822909 S
500258352025-10-10 16:02:15108 days ago1760112135
0x321520f8...BFd2189D9
95.17575475 S
494954802025-10-06 7:00:25112 days ago1759734025
0x321520f8...BFd2189D9
0.40064631 S
494946592025-10-06 6:48:25112 days ago1759733305
0x321520f8...BFd2189D9
0.40131661 S
488911332025-09-30 19:59:15117 days ago1759262355
0x321520f8...BFd2189D9
0.55565836 S
484671442025-09-27 16:24:49121 days ago1758990289
0x321520f8...BFd2189D9
7.426847 S
479055572025-09-23 13:09:06125 days ago1758632946
0x321520f8...BFd2189D9
0.64907115 S
View All Internal Transactions
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BridgeCCIP

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

import { Codec, BridgeSendPayload } from "../../libs/Codec.sol";
import { Common } from "../../libs/Common.sol";
import { Constants } from "../../libs/Constants.sol";

import { Client } from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
import { CCIPReceiver } from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol";
import { IRouterClient } from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import { LinkTokenInterface } from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol";

import { IBlackList } from "../../administrator/interface/IBlackList.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ILockBox } from "../../core/interface/ILockBox.sol";
import { IManager, ManageAssetAndShares } from "../../core/interface/IManager.sol";
import { IRole } from "../../administrator/interface/IRole.sol";
import { IPausable } from "../../administrator/interface/IPausable.sol";

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

event SetLockbox(address indexed caller, address indexed token, address indexed lockbox);
event SetAdministrator(address indexed caller, address indexed administrator);
event SetToken(address indexed caller, uint64 indexed dstId, address indexed token);
event MessageReceived(bytes32 indexed messageId, uint64 indexed sourceChainSelector, address sender, bytes data);
event MessageSent(bytes32 indexed messageId);
event ManagerSet(address indexed caller, address indexed manager);

contract BridgeCCIP is CCIPReceiver, Ownable {
    bool public immutable isL1;
    address public immutable link;
    address public administrator;
    mapping(bytes32 => bool) public processedMessages;
    mapping(address => address) public lockboxes;
    mapping(address => mapping(uint64 => address)) public tokens;
    address public manager;
    mapping(uint64 peerChainId => mapping(address peer => bool allowed)) public allowedPeers;
    enum PayFeesIn {
        Native,
        LINK
    }
    using SafeERC20 for IERC20;

    constructor(address _router, bool _isL1, address _administrator, address _link) CCIPReceiver(_router) Ownable(msg.sender) {
        isL1 = _isL1;
        administrator = _administrator;
        link = _link;
    }

    modifier onlyAdmin() {
        require(IRole(administrator).hasRole(Constants.ADMIN_ROLE, msg.sender), "!admin");
        _;
    }

    modifier notBlacklisted(address user) {
        require(!IBlackList(administrator).isBlackListed(user), "blacklisted");
        _;
    }

    modifier notPaused() {
        require(!IPausable(administrator).isPaused(address(this)), "paused");
        _;
    }

    function setAdministrator(address _administrator) external onlyOwner {
        require(Common.isContract(_administrator), "!address");
        administrator = _administrator;
        emit SetAdministrator(msg.sender, _administrator);
    }

    function setLockbox(address _ytoken, address _lockbox) external onlyAdmin {
        require(Common.isContract(_ytoken), "!token");
        require(Common.isContract(_lockbox), "!lockbox");
        lockboxes[_ytoken] = _lockbox;
        emit SetLockbox(msg.sender, _ytoken, _lockbox);
    }

    function setManager(address _manager) external onlyAdmin {
        require(Common.isContract(_manager), "!manager");
        manager = _manager;
        emit ManagerSet(msg.sender, _manager);
    }

    function setTokens(address _srcToken, uint64[] calldata _dstIds, address[] calldata _tokens) external onlyAdmin {
        require(_srcToken != address(0), "!src token");
        require(_dstIds.length == _tokens.length, "!length");
        for (uint256 i = 0; i < _dstIds.length; ) {
            require(_tokens[i] != address(0), "!token");
            tokens[_srcToken][_dstIds[i]] = _tokens[i];
            emit SetToken(msg.sender, _dstIds[i], _tokens[i]);

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Set allowed peers for a source chain
     * @param _peerChainId The peer chain id
     * @param _peer The peer
     * @param _allowed Whether the peer is allowed
     * @dev To ensure that messages can only be sent to allowed peers and received from allowed peers
     */
    function setAllowedPeers(uint64 _peerChainId, address _peer, bool _allowed) external onlyAdmin {
        allowedPeers[_peerChainId][_peer] = _allowed;
    }

    function quote(uint64 _dstChainId, address _receiver, bytes calldata _payload, Client.GenericExtraArgsV2 memory _extraArgs, PayFeesIn _payFeesIn) public view returns (uint256) {
        // setting allowOutOfOrderExecution to true to ensure that funds are not locked on chains which require it to be true
        _extraArgs.allowOutOfOrderExecution = true;
        // Sends the message to the destination endpoint
        Client.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({
            receiver: abi.encode(_receiver), // ABI-encoded receiver address
            data: abi.encode(_payload), // ABI-encoded string
            tokenAmounts: new Client.EVMTokenAmount[](0), // Empty array indicating no tokens are being sent
            extraArgs: Client._argsToBytes(_extraArgs),
            feeToken: _payFeesIn == PayFeesIn.LINK ? link : address(0) // For msg.value
        });

        // Get the fee required to send the message
        uint256 fees = IRouterClient(i_ccipRouter).getFee(_dstChainId, evm2AnyMessage);

        return fees;
    }

    function send(address _yToken, uint64 _dstChain, address _to, uint256 _amount, address _receiver, Client.GenericExtraArgsV2 memory _extraArgs, PayFeesIn _payFeesIn) external payable notBlacklisted(msg.sender) notBlacklisted(_to) notPaused {
        require(_amount > 0, "!amount");
        require(lockboxes[_yToken] != address(0), "!token !lockbox");
        require(IERC20(_yToken).balanceOf(msg.sender) >= _amount, "!balance");
        require(_to != address(0), "!receiver");
        require(tokens[_yToken][_dstChain] != address(0), "!destination");
        require(allowedPeers[_dstChain][_receiver], "!allowed");
        bytes memory _encodedMessage = abi.encode(_dstChain, _to, tokens[_yToken][_dstChain], _amount, Constants.BRIDGE_SEND_HASH);
        // setting allowOutOfOrderExecution to true to ensure that funds are not locked on chains which require it to be true
        _extraArgs.allowOutOfOrderExecution = true;

        // Sends the message to the destination endpoint
        Client.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({
            receiver: abi.encode(_receiver), // ABI-encoded receiver address
            data: abi.encode(_encodedMessage), // ABI-encoded string
            tokenAmounts: new Client.EVMTokenAmount[](0), // Empty array indicating no tokens are being sent
            extraArgs: Client._argsToBytes(_extraArgs),
            feeToken: _payFeesIn == PayFeesIn.LINK ? link : address(0) // For msg.value
        });

        // Get the fee required to send the message
        uint256 fees = IRouterClient(i_ccipRouter).getFee(_dstChain, evm2AnyMessage);


        // Transfer or burn tokens
        if (isL1) {
            // Lock the tokens in lockbox
            IERC20(_yToken).safeTransferFrom(msg.sender, lockboxes[_yToken], _amount);
            emit ILockBox.Lock(msg.sender, _yToken, msg.sender, _amount);
        } else {
            // Create manageAssetAndShares struct with isMint = false and updateAsset = false
            // as bridging does not need to update asset amount on L2
            ManageAssetAndShares memory manageAssetAndShares = ManageAssetAndShares({ yToken: _yToken, shares: _amount, assetAmount: 0, updateAsset: false, isMint: false, isNewYToken: false });
            // call manageAssetAndShares
            IManager(manager).manageAssetAndShares(msg.sender, manageAssetAndShares);
        }

        bytes32 messageId;
        if (_payFeesIn == PayFeesIn.LINK) {
            // transfer from msg.sender to this contract
            LinkTokenInterface(link).transferFrom(msg.sender,address(this),fees);
            // approve the router to spend the link
            LinkTokenInterface(link).approve(i_ccipRouter, fees);
            messageId = IRouterClient(i_ccipRouter).ccipSend(_dstChain, evm2AnyMessage);
        } else {
            messageId = IRouterClient(i_ccipRouter).ccipSend{value: fees}(_dstChain, evm2AnyMessage);
        }
        emit MessageSent(messageId);
    }

    /// handle a received message
    function _ccipReceive(Client.Any2EVMMessage memory any2EvmMessage) internal override {
        bytes memory message = abi.decode(any2EvmMessage.data, (bytes)); // abi-decoding of the sent text
        BridgeSendPayload memory payload = Codec.decodeBridgeSendPayload(message);
        bytes32 _hash = keccak256(abi.encode(message, any2EvmMessage.messageId));
        require(!processedMessages[_hash], "processed");
        address sender = abi.decode(any2EvmMessage.sender, (address));
        require(allowedPeers[any2EvmMessage.sourceChainSelector][sender], "!allowed");

        processedMessages[_hash] = true;

        require(payload.amount > 0, "!amount");

        if (isL1) {
            require(lockboxes[payload.token] != address(0), "!token !lockbox");
            ILockBox(lockboxes[payload.token]).unlock(payload.token, payload.to, payload.amount);
        } else {
            // Create manageAssetAndShares struct with isMint = true and updateAsset = false
            // as bridging does not need to update asset amount on L2
            ManageAssetAndShares memory manageAssetAndShares = ManageAssetAndShares({ yToken: payload.token, shares: payload.amount, assetAmount: 0, updateAsset: false, isMint: true, isNewYToken: false });
            // call manageAssetAndShares
            IManager(manager).manageAssetAndShares(payload.to, manageAssetAndShares);
        }
    }
}

// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

import { Common } from "./Common.sol";
import { Constants } from "./Constants.sol";

struct BridgeSendPayload {
    uint64 dstId;
    address to;
    address token;
    uint256 amount;
    bytes32 trxnType;
}

error WrongDataLength();
error WrongAddressEncoding();
error WrongData();

library Codec {
    uint256 internal constant DATA_LENGTH = 32 * 5;
    
    /**
     * @notice Decode a bridge send payload from bytes
     * @param _data encoded payload data
     * @return Decoded BridgeSendPayload struct
     */
    function decodeBridgeSendPayload(bytes memory _data) internal view returns (BridgeSendPayload memory) {
        if (_data.length != DATA_LENGTH) {
            revert WrongDataLength();
        }

        (uint64 dstId, address to, address token, uint256 amount, bytes32 trxnType) = abi.decode(_data, (uint64, address, address, uint256, bytes32));

        if (trxnType != Constants.BRIDGE_SEND_HASH) {
            revert WrongData();
        }
        if (dstId == 0) {
            revert WrongData();
        }
        if (to == address(0)) {
            revert WrongAddressEncoding();
        }
        if (token == address(0) || !Common.isContract(token)) {
            revert WrongAddressEncoding();
        }
        if (amount == 0) {
            revert WrongData();
        }

        return BridgeSendPayload(dstId, to, token, amount, trxnType);
    }
}

// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

library Common {
    /**
     * @notice Check if an address is a contract
     * @param _addr address to check
     * @return true if the address is a contract, false otherwise
     */
    function isContract(address _addr) internal view returns (bool) {
        return _addr != address(0) && _addr.code.length != 0;
    }
}

File 4 of 23 : Constants.sol
// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

library Constants {
    // admin role
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");

    // role for minting and redeeming tokens
    bytes32 public constant MINTER_AND_REDEEMER_ROLE = keccak256("MINTER_AND_REDEEMER");

    // role for collateral manager who can transfer collateral
    bytes32 public constant COLLATERAL_MANAGER_ROLE = keccak256("COLLATERAL_MANAGER");

    // role for rewarder who can transfer reward
    bytes32 public constant REWARDER_ROLE = keccak256("REWARDER");

    // role for managing blacklist addresses
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER");

    // role assigned to bridges
    bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE");

    // role for perpetual bond
    bytes32 public constant BOND_ROLE = keccak256("BOND");

    // role for lockbox
    bytes32 public constant LOCKBOX_ROLE = keccak256("LOCKBOX");

    // role for yield
    bytes32 public constant YIELD_ROLE = keccak256("YIELD");

    uint256 constant PINT = 1e18;
    uint256 constant HUNDRED_PERCENT = 100e18;
    uint256 constant ONE_PERCENT = 1e18;
    uint256 constant HUNDRED = 100;

    // Period for vesting strategy rewards
    uint256 constant VESTING_PERIOD = 24 hours;


    // Bridge transaction types
    bytes32 public constant BRIDGE_SEND_HASH = keccak256("BRIDGE_SEND");
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// End consumer library.
library Client {
  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.4;

import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol";

import {Client} from "../libraries/Client.sol";

import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";

/// @title CCIPReceiver - Base contract for CCIP applications that can receive messages.
abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165 {
  address internal immutable i_ccipRouter;

  constructor(
    address router
  ) {
    if (router == address(0)) revert InvalidRouter(address(0));
    i_ccipRouter = router;
  }

  /// @notice IERC165 supports an interfaceId.
  /// @param interfaceId The interfaceId to check.
  /// @return true if the interfaceId is supported.
  /// @dev Should indicate whether the contract implements IAny2EVMMessageReceiver.
  /// e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId
  /// This allows CCIP to check if ccipReceive is available before calling it.
  /// - If this returns false or reverts, only tokens are transferred to the receiver.
  /// - If this returns true, tokens are transferred and ccipReceive is called atomically.
  /// Additionally, if the receiver address does not have code associated with it at the time of
  /// execution (EXTCODESIZE returns 0), only tokens will be transferred.
  function supportsInterface(
    bytes4 interfaceId
  ) public view virtual override returns (bool) {
    return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId;
  }

  /// @inheritdoc IAny2EVMMessageReceiver
  function ccipReceive(
    Client.Any2EVMMessage calldata message
  ) external virtual override onlyRouter {
    _ccipReceive(message);
  }

  /// @notice Override this function in your implementation.
  /// @param message Any2EVMMessage.
  function _ccipReceive(
    Client.Any2EVMMessage memory message
  ) internal virtual;

  /// @notice Return the current router
  /// @return CCIP router address
  function getRouter() public view virtual returns (address) {
    return address(i_ccipRouter);
  }

  error InvalidRouter(address router);

  /// @dev only calls from the set router are accepted.
  modifier onlyRouter() {
    if (msg.sender != getRouter()) revert InvalidRouter(msg.sender);
    _;
  }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {Client} from "../libraries/Client.sol";

interface IRouterClient {
  error UnsupportedDestinationChain(uint64 destChainSelector);
  error InsufficientFeeTokenAmount();
  error InvalidMsgValue();

  /// @notice Checks if the given chain ID is supported for sending/receiving.
  /// @param destChainSelector The chain to check.
  /// @return supported is true if it is supported, false if not.
  function isChainSupported(
    uint64 destChainSelector
  ) external view returns (bool supported);

  /// @param destinationChainSelector The destination chainSelector.
  /// @param message The cross-chain CCIP message including data and/or tokens.
  /// @return fee returns execution fee for the message.
  /// delivery to destination chain, denominated in the feeToken specified in the message.
  /// @dev Reverts with appropriate reason upon invalid message.
  function getFee(
    uint64 destinationChainSelector,
    Client.EVM2AnyMessage memory message
  ) external view returns (uint256 fee);

  /// @notice Request a message to be sent to the destination chain.
  /// @param destinationChainSelector The destination chain ID.
  /// @param message The cross-chain CCIP message including data and/or tokens.
  /// @return messageId The message ID.
  /// @dev Note if msg.value is larger than the required fee (from getFee) we accept.
  /// the overpayment with no refund.
  /// @dev Reverts with appropriate reason upon invalid message.
  function ccipSend(
    uint64 destinationChainSelector,
    Client.EVM2AnyMessage calldata message
  ) external payable returns (bytes32);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// solhint-disable-next-line interface-starts-with-i
interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);

  function approve(address spender, uint256 value) external returns (bool success);

  function balanceOf(address owner) external view returns (uint256 balance);

  function decimals() external view returns (uint8 decimalPlaces);

  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);

  function increaseApproval(address spender, uint256 subtractedValue) external;

  function name() external view returns (string memory tokenName);

  function symbol() external view returns (string memory tokenSymbol);

  function totalSupply() external view returns (uint256 totalTokensIssued);

  function transfer(address to, uint256 value) external returns (bool success);

  function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);

  function transferFrom(address from, address to, uint256 value) external returns (bool success);
}

// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

interface IBlackList {
    //functions
    function blackListUsers(address[] calldata _users) external;
    function removeBlackListUsers(address[] calldata _clearedUsers) external;
    function isBlackListed(address _user) external view returns (bool);

    //events
    event BlackListed(address indexed _sender, address indexed _user);
    event BlackListCleared(address indexed _sender, address indexed _user);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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: GPL-2.0
pragma solidity ^0.8.20;

interface ILockBox {
    // functions
    function unlock(address token, address to, uint256 amount) external;

    // events
    event Sync(address indexed caller, address indexed token, uint256 shares, uint256 sAmount, bool syncType);
    event Unlock(address indexed caller, address indexed token, address indexed to, uint256 amount);
    event Lock(address indexed caller, address indexed token, address indexed from, uint256 amount);
    event ManagerSet(address indexed caller, address indexed manager);
}

// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

/**
 * @notice ManageAssetAndShares is used to manage the asset and shares of the yToken
 * @param yToken The address of the yToken
 * @param shares The number of shares to manage
 * @param assetAmount The amount of asset to manage
 * @param updateAsset Whether to update the asset
 * @param isMint Whether to mint or burn the yToken
 * @param isNewYToken Whether the yToken is new, only utilised in vyToken and vyTokenL2 whenever asset from outside of 
        YieldFi is deposited into the protocol (i.e during deposits and yield distribution)
  */
struct ManageAssetAndShares {
    address yToken;
    uint256 shares;
    uint256 assetAmount;
    bool updateAsset;
    bool isMint;
    bool isNewYToken;
}
interface IManager {
    event Deposit(address indexed caller, address indexed asset, uint256 amount, address indexed receiver, address yToken, uint256 shares, uint256 feeShare, uint256 gasFeeShare);
    event Withdraw(address indexed caller, address indexed asset, uint256 amount, address indexed receiver, address yToken, uint256 shares, uint256 feeShare, uint256 gasFeeShare);
    event Rescue(address indexed caller, address indexed token, address indexed to, uint256 amount);
    event AssetStatus(bool indexed orderType, address indexed yToken, address indexed asset, bool status);
    event OrderRequest(address caller, address indexed yToken, address indexed asset, address indexed receiver, uint256 amount, bool orderType, uint256 exchangeRateInUnderlying, uint256 receiptId, bytes32 referralCode);
    event YieldFeesTransferred(address indexed treasury, address indexed yToken, uint256 shares);
    event AssetAndShareManaged(address indexed caller, address indexed yToken, uint256 shares, uint256 assetAmount, bool updateAsset, bool isMint, bool isNewYToken);
    event TreasurySet(address indexed caller, address indexed treasury);
    event ReceiptSet(address indexed caller, address indexed receipt);
    event CustodyWalletSet(address indexed caller, address indexed wallet, bool status);
    event MinSharesInYTokenSet(address indexed caller, address indexed yToken, uint256 minShares);

    function deposit(address _yToken, address _asset, uint256 _amount, address _receiver, address _callback, bytes calldata _callbackData, bytes32 _referralCode) external;
    function redeem(address caller, address _yToken, address _asset, uint256 _shares, address _receiver, address _callback, bytes calldata _callbackData) external;
    function executeOrder(uint256 _receiptId, uint256 _amount, uint256 _fee, uint256 _gas) external;
    function transferToCustodyWallet(address _token, address _receiver, uint256 _amount) external;
    function treasury() external view returns (address);
    function manageAssetAndShares(address _to, ManageAssetAndShares memory _manageAssetAndShares) external;
    function minSharesInYToken(address _yToken) external view returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

interface IRole {
    //functions
    function grantRoles(bytes32 _role, address[] calldata _accounts) external;
    function revokeRoles(bytes32 _role, address[] calldata _accounts) external;
    function hasRole(bytes32 _role, address _account) external view returns (bool);
    function hasRoles(bytes32[] calldata _role, address[] calldata _accounts) external view returns (bool[] memory);

    //events
    event RoleGranted(bytes32 indexed _role, address indexed _sender, address indexed _account);
    event RoleRevoked(bytes32 indexed _role, address indexed _sender, address indexed _account);
}

// SPDX-License-Identifier: GPL-2.0
pragma solidity ^0.8.20;

interface IPausable {
    function pause() external;
    function unpause() external;
    function pauseSC(address _sc) external;
    function unpauseSC(address _sc) external;
    function isPaused(address _sc) external view returns (bool);

    //events
    event Paused(address indexed _sender);
    event Unpaused(address indexed _sender);
    event Paused(address indexed _sender, address indexed _sc);
    event Unpaused(address indexed _sender, address indexed _sc);
}

// 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.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 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 {
    /**
     * @dev An operation with an ERC-20 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 Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(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.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    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.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    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.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    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 Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            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 silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

File 17 of 23 : IAny2EVMMessageReceiver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Client} from "../libraries/Client.sol";

/// @notice Application contracts that intend to receive messages from  the router should implement this interface.
interface IAny2EVMMessageReceiver {
  /// @notice Called by the Router to deliver a message. If this reverts, any token transfers also revert.
  /// The message will move to a FAILED state and become available for manual execution.
  /// @param message CCIP Message.
  /// @dev Note ensure you check the msg.sender is the OffRampRouter.
  function ccipReceive(
    Client.Any2EVMMessage calldata message
  ) external;
}

// 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);
}

// 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;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

File 21 of 23 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 22 of 23 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

Settings
{
  "remappings": [
    "@layerzerolabs/oft-evm/=lib/devtools/packages/oft-evm/",
    "@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/",
    "@layerzerolabs/lz-evm-protocol-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/protocol/",
    "@layerzerolabs/lz-evm-messagelib-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/messagelib/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin-upgradeable/contracts/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@chainlink/contracts-ccip/=lib/chainlink/contracts/",
    "@chainlink/contracts/=lib/chainlink/contracts/",
    "solidity-bytes-utils/=lib/solidity-bytes-utils/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "chainlink/=lib/chainlink/",
    "devtools/=lib/devtools/packages/toolbox-foundry/src/",
    "ds-test/=lib/layerzero-v2/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "layerzero-v2/=lib/layerzero-v2/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"bool","name":"_isL1","type":"bool"},{"internalType":"address","name":"_administrator","type":"address"},{"internalType":"address","name":"_link","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"InvalidRouter","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"},{"inputs":[],"name":"WrongAddressEncoding","type":"error"},{"inputs":[],"name":"WrongData","type":"error"},{"inputs":[],"name":"WrongDataLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Lock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"ManagerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"messageId","type":"bytes32"}],"name":"MessageSent","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"administrator","type":"address"}],"name":"SetAdministrator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"lockbox","type":"address"}],"name":"SetLockbox","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"uint64","name":"dstId","type":"uint64"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"SetToken","type":"event"},{"inputs":[],"name":"administrator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"peerChainId","type":"uint64"},{"internalType":"address","name":"peer","type":"address"}],"name":"allowedPeers","outputs":[{"internalType":"bool","name":"allowed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"messageId","type":"bytes32"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"destTokenAmounts","type":"tuple[]"}],"internalType":"struct Client.Any2EVMMessage","name":"message","type":"tuple"}],"name":"ccipReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isL1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"link","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockboxes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_dstChainId","type":"uint64"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"components":[{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bool","name":"allowOutOfOrderExecution","type":"bool"}],"internalType":"struct Client.GenericExtraArgsV2","name":"_extraArgs","type":"tuple"},{"internalType":"enum BridgeCCIP.PayFeesIn","name":"_payFeesIn","type":"uint8"}],"name":"quote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_yToken","type":"address"},{"internalType":"uint64","name":"_dstChain","type":"uint64"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"},{"components":[{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bool","name":"allowOutOfOrderExecution","type":"bool"}],"internalType":"struct Client.GenericExtraArgsV2","name":"_extraArgs","type":"tuple"},{"internalType":"enum BridgeCCIP.PayFeesIn","name":"_payFeesIn","type":"uint8"}],"name":"send","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_administrator","type":"address"}],"name":"setAdministrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_peerChainId","type":"uint64"},{"internalType":"address","name":"_peer","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setAllowedPeers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ytoken","type":"address"},{"internalType":"address","name":"_lockbox","type":"address"}],"name":"setLockbox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_srcToken","type":"address"},{"internalType":"uint64[]","name":"_dstIds","type":"uint64[]"},{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"setTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"tokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e03461017a57601f61223438819003918201601f19168301916001600160401b0383118484101761017e5780849260809460405283398101031261017a5761004781610192565b602082015191821515830361017a5761006e606061006760408401610192565b9201610192565b916001600160a01b03811615610167576080523315610154575f8054336001600160a01b0319821681178355604051959290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a360a052600180546001600160a01b0319166001600160a01b039290921691909117905560c05261208d90816101a782396080518181816103a2015281816105b8015281816106dd0152611477015260a051818181610a290152818161112a01526114ce015260c05181818161054e015281816110e30152818161142201526115bb0152f35b631e4fbdf760e01b5f525f60045260245ffd5b6335fdcccd60e21b5f525f60045260245ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361017a5756fe6080806040526004361015610012575f80fd5b5f905f3560e01c90816301ffc9a714611a94575080630b3f78b3146119b75780630e1c2f4e1461114f5780631974932b146111125780631c4695f4146110cd578063477db86e14611070578063481c6a75146110475780636d4e24c314610f1e578063715018a614610ec457806378ab175014610ca257806379e1ccec14610c6157806385572ffb146106aa57806388ba16ab1461067b5780638da5cb5b146106545780639726f9c41461042a578063a16032cc146103d1578063b0f479a11461038c578063d0ebdbe71461025d578063df8089ef146101b6578063f2fde38b146101305763f53d0a8e14610105575f80fd5b3461012d578060031936011261012d576001546040516001600160a01b039091168152602090f35b80fd5b503461012d57602036600319011261012d5761014a611b29565b610152611ffd565b6001600160a01b031680156101a25781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b503461012d57602036600319011261012d576101d0611b29565b6101d8611ffd565b6101e181611fdf565b1561022d57600180546001600160a01b0319166001600160a01b03929092169182179055337f525117b0c654ea4d9950e296eca92b77aa3c6fdeba6217801c6f32a0ed7a09228380a380f35b60405162461bcd60e51b8152602060048201526008602482015267216164647265737360c01b6044820152606490fd5b503461012d57602036600319011261012d57610277611b29565b600154604051632474521560e21b81525f80516020612038833981519152600482015233602482015290602090829060449082906001600160a01b03165afa8015610381576102cd918491610352575b50611c0d565b6102d681611fdf565b1561032257600580546001600160a01b0319166001600160a01b03929092169182179055337fc64707e618a83637fc41ad1e3aa4242bd5fdd353f3d60bc0faf40db0d7d860788380a380f35b60405162461bcd60e51b815260206004820152600860248201526710b6b0b730b3b2b960c11b6044820152606490fd5b610374915060203d60201161037a575b61036c8183611ba4565b810190611bf5565b5f6102c7565b503d610362565b6040513d85823e3d90fd5b503461012d578060031936011261012d576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461012d57604036600319011261012d5760406103ed611ae7565b916001600160401b036103fe611b13565b931681526006602052209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b503461012d5760c036600319011261012d57610444611ae7565b61044c611b13565b906044356001600160401b0381116106505736602382011215610650578060040135906001600160401b03821161064c57366024838301011161064c57604036606319011261064c57604051906104a282611b89565b6064358252608435928315158403610648576020830193845260a435936002851015610644579261053360606105b499989694602494600160209a98526040519860018060a01b03168a8a01528989526104fd60408a611ba4565b806040519687938c8086015282604086015201848401378a838284010152601f801991011681010301601f198101845283611ba4565b6001610546610540611d62565b92611fae565b930361063d577f0000000000000000000000000000000000000000000000000000000000000000915b6040519561057c87611b3f565b865286860152604085015260018060a01b03166060840152608083015260405194859283926320487ded60e01b845260048401611da7565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561063157906105fa575b602090604051908152f35b506020813d602011610629575b8161061460209383611ba4565b8101031261062557602090516105ef565b5f80fd5b3d9150610607565b604051903d90823e3d90fd5b869161056f565b8780fd5b8680fd5b8480fd5b8380fd5b503461012d578060031936011261012d57546040516001600160a01b039091168152602090f35b503461012d57602036600319011261012d5760ff60406020926004358152600284522054166040519015158152f35b503461012d57602036600319011261012d576004356001600160401b038111610c5d5760a06003198236030112610c5d577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610c4a5760405161071781611b3f565b816004013581526024820135906001600160401b0382168203610650576020810191825260448301356001600160401b03811161064c5761075e9060043691860101611f68565b926040820193845260648101356001600160401b038111610be6576107899060043691840101611f68565b90606083019182526084810135906001600160401b038211610648570136602382011215610be65760048101356107bf81611d4b565b916107cd6040519384611ba4565b818352602060048185019360061b8301010190368211610c4657602401915b818310610bfd57505050608083015251918251830192602081818601950312610be6576020810151906001600160401b03821161064857019280603f85011215610be6578560208501519461084086611f4d565b9561084e6040519788611ba4565b808752602087019360408383010111610bf95780604060209301855e8601015285608060405161087d81611b3f565b828152826020820152826040820152826060820152015260a0845103610bea5760a084805181010312610be65751906001600160401b038216809203610be6576108c960408501612023565b936108d660608201612023565b608082015160a083015190966001600160a01b03908116969216947fedc6e67b7f382e06fc55950940693789ec865cf44b786836c295e1a7ff6694858201610bb8578015610bb8578615610bc75785158015610bd6575b610bc7578715610bb85760405160809161094682611b3f565b8152602081019788526040810196875260608101988952015251610992604051809261097e6020830195604087526060840190611d27565b90604083015203601f198101835282611ba4565b51902090818752600260205260ff604088205416610b8757869551602081805181010312610648576001600160401b03906001600160a01b03906109d890602001612023565b1691511686526006602052604086209060018060a01b03165f52602052610a0560ff60405f205416611cf0565b8452600260205260408420600160ff19825416179055610a2783511515611c7c565b7f000000000000000000000000000000000000000000000000000000000000000015610b085780516001600160a01b03908116855260036020526040852054610a7291161515611cb2565b80516001600160a01b0390811685526003602052604085205491519251935193811693928116929116803b1561064c576040516359508f8f60e01b81526001600160a01b039384166004820152939092166024840152604483015282908290818381606481015b03925af18015610afd57610aec57505080f35b81610af691611ba4565b61012d5780f35b6040513d84823e3d90fd5b51915160405191926001600160a01b0316610b2283611b6e565b8252602082015260408101839052606081018390526001608082015260a0810183905260055491516001600160a01b03928316921690823b15610b8257610ad992849283604051809681958294636defd45560e01b845260048401611e74565b505050fd5b60405162461bcd60e51b81526020600482015260096024820152681c1c9bd8d95cdcd95960ba1b6044820152606490fd5b6301b44b5f60e11b8a5260048afd5b63209e29c560e21b8a5260048afd5b50610be086611fdf565b1561092d565b8580fd5b6366289e3960e11b8652600486fd5b8280fd5b604083360312610c465760405190610c1482611b89565b8335906001600160a01b0382168203610c4257826020926040945282860135838201528152019201916107ec565b8a80fd5b8880fd5b6335fdcccd60e21b825233600452602482fd5b5080fd5b503461012d57602036600319011261012d576020906001600160a01b03610c86611b29565b16815260038252604060018060a01b0391205416604051908152f35b503461012d57606036600319011261012d57610cbc611b29565b6024356001600160401b038111610bf957610cdb903690600401611bc5565b90916044356001600160401b03811161064c57610cfc903690600401611bc5565b600154604051632474521560e21b81525f805160206120388339815191526004820152336024820152919492939190602090829060449082906001600160a01b03165afa8015610eb957610d569188916103525750611c0d565b6001600160a01b0316938415610e8757838203610e5857855b828110610d7a578680f35b600190610da36001600160a01b03610d9b610d96848a8a611f01565b611f25565b161515611ecc565b610db1610d96828888611f01565b8789526004602052604089206001600160401b03610dd8610dd3858989611f01565b611f39565b165f5260205260405f2090838060a01b03166bffffffffffffffffffffffff60a01b825416179055610e0e610dd3828686611f01565b6001600160401b03838060a01b03610e2a610d96858b8b611f01565b169116337fffc69ac19640cba1401d95c27b77e155ce08c0a70946fb435fbd7e0bc7b0c65c8b80a401610d6f565b60405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600a60248201526910b9b931903a37b5b2b760b11b6044820152606490fd5b6040513d89823e3d90fd5b503461012d578060031936011261012d57610edd611ffd565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461012d57604036600319011261012d57610f38611b29565b610f40611b13565b600154604051632474521560e21b81525f80516020612038833981519152600482015233602482015291929190602090829060449082906001600160a01b03165afa801561103c57610f989185916103525750611c0d565b610fa9610fa482611fdf565b611ecc565b610fb282611fdf565b1561100c576001600160a01b0390811680845260036020526040842080546001600160a01b03191693909216928317909155337fc2677273938f50fd26297a86f7c15963e77c4ec9141bbf83f2a7f33cfc2ca1638480a480f35b60405162461bcd60e51b8152602060048201526008602482015267042d8dec6d6c4def60c31b6044820152606490fd5b6040513d86823e3d90fd5b503461012d578060031936011261012d576005546040516001600160a01b039091168152602090f35b503461012d57604036600319011261012d576001600160401b036040611094611b29565b9261109d611afd565b9360018060a01b0316815260046020522091165f52602052602060405f2060018060a01b03905416604051908152f35b503461012d578060031936011261012d576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461012d578060031936011261012d5760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b5061010036600319011261062557611165611b29565b9061116e611afd565b6044356001600160a01b0381169390849003610625576084356001600160a01b0381169190606435908390036106255760403660a319011261062557604051916111b783611b89565b60a435835260c435968715158803610625576020840197885260e43591600283101561062557600154604051630723eb0360e51b81523360048201526001600160a01b0390911690602081602481855afa801561182457611220915f9161199e575b5015611c42565b604051630723eb0360e51b81526004810184905290602082602481845afa9081156118245761125b6020926024945f91611981575015611c42565b604051635b14f18360e01b815230600482015292839182905afa908115611824575f91611962575b5061193457611293841515611c7c565b6001600160a01b039081165f818152600360205260409020549099916112bb91161515611cb2565b6040516370a0823160e01b81523360048201526020816024818d5afa80156118245785915f916118ff575b50106118cf57811561189e575f8981526004602090815260408083206001600160401b038b1684529091529020546001600160a01b03161561186a576113f6916001611404926001600160401b038a1692835f52600660205260405f208a5f5260205261135960ff60405f205416611cf0565b8c5f52600460205260405f20845f5260205260405f20838060a01b0390541690604051946020860152604085015260608401528660808401527f1239198480c7d1f903aa6af6bf96c8761379a30bb48797c93d6a1e5800996b7b60a084015260a083526113c760c084611ba4565b52604051966020880152602087526113e0604088611ba4565b6040519283916020808401526040830190611d27565b03601f198101835282611ba4565b6001611417611411611d62565b95611fae565b9214938415611863577f0000000000000000000000000000000000000000000000000000000000000000915b6040519661145088611b3f565b87526020870152604086015260018060a01b03166060850152608084015260018060a01b037f00000000000000000000000000000000000000000000000000000000000000001691604051916320487ded60e01b8352602083806114b8888a60048401611da7565b0381875afa928315611824575f9361182f575b507f00000000000000000000000000000000000000000000000000000000000000001561178f578787526003602090815260408089205490516323b872dd60e01b8184019081523360248301526001600160a01b0390921660448201526064810184905289919061153f81608481016113f6565b5190828c5af1156117845786513d61177b5750873b155b61176757869760405191825233917fd6aba49fa5adb7dbc18ab12d057e77c75e5d4b345cf473c7514afbbd6f5fc62660203392a45b156116f7576040516323b872dd60e01b815233600482015230602482015260448101829052906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906020836064818a865af1908115610eb9576020936044926116dc575b50604051978893849263095ea7b360e01b845287600485015260248401525af19283156116d157611649946020946116b6575b50856040518096819582946396f4e9f960e01b845260048401611da7565b03925af1908115610afd578291611684575b505b7f54791b38f3859327992a1ca0590ad3c0f08feba98d1a4f56ab0dca74d203392a8280a280f35b90506020813d6020116116ae575b8161169f60209383611ba4565b8101031261062557515f61165b565b3d9150611692565b6116cc90853d871161037a5761036c8183611ba4565b61162b565b6040513d87823e3d90fd5b6116f290853d871161037a5761036c8183611ba4565b6115f8565b6040516396f4e9f960e01b815294506020938593849291839161171d9160048401611da7565b03925af1908115610afd578291611735575b5061165d565b90506020813d60201161175f575b8161175060209383611ba4565b8101031261062557515f61172f565b3d9150611743565b635274afe760e01b87526004889052602487fd5b60011415611556565b6040513d88823e3d90fd5b6040519761179c89611b6e565b885260208801525f60408801819052606088018190526080880181905260a08801526005546001600160a01b0316803b1561062557604051636defd45560e01b8152975f9189918290849082906117f7903360048401611e74565b03925af180156118245761180e575b85965061158b565b9450945f61181b91611ba4565b5f938590611806565b6040513d5f823e3d90fd5b9092506020813d60201161185b575b8161184b60209383611ba4565b810103126106255751915f6114cb565b3d915061183e565b5f91611443565b60405162461bcd60e51b815260206004820152600c60248201526b10b232b9ba34b730ba34b7b760a11b6044820152606490fd5b60405162461bcd60e51b815260206004820152600960248201526810b932b1b2b4bb32b960b91b6044820152606490fd5b60405162461bcd60e51b81526020600482015260086024820152672162616c616e636560c01b6044820152606490fd5b9150506020813d60201161192c575b8161191b60209383611ba4565b81010312610625578490515f6112e6565b3d915061190e565b60405162461bcd60e51b81526020600482015260066024820152651c185d5cd95960d21b6044820152606490fd5b61197b915060203d60201161037a5761036c8183611ba4565b5f611283565b6119989150843d861161037a5761036c8183611ba4565b5f611219565b611998915060203d60201161037a5761036c8183611ba4565b34610625576060366003190112610625576119d0611ae7565b6119d8611b13565b6044359182151580930361062557600154604051632474521560e21b81525f8051602061203883398151915260048201523360248201529190602090839060449082906001600160a01b03165afa918215611824576001600160401b0392611a46915f91611a755750611c0d565b165f52600660205260405f209060018060a01b03165f5260205260405f209060ff801983541691161790555f80f35b611a8e915060203d60201161037a5761036c8183611ba4565b866102c7565b34610625576020366003190112610625576004359063ffffffff60e01b8216809203610625576020916385572ffb60e01b8114908115611ad6575b5015158152f35b6301ffc9a760e01b14905083611acf565b600435906001600160401b038216820361062557565b602435906001600160401b038216820361062557565b602435906001600160a01b038216820361062557565b600435906001600160a01b038216820361062557565b60a081019081106001600160401b03821117611b5a57604052565b634e487b7160e01b5f52604160045260245ffd5b60c081019081106001600160401b03821117611b5a57604052565b604081019081106001600160401b03821117611b5a57604052565b90601f801991011681019081106001600160401b03821117611b5a57604052565b9181601f84011215610625578235916001600160401b038311610625576020808501948460051b01011161062557565b90816020910312610625575180151581036106255790565b15611c1457565b60405162461bcd60e51b815260206004820152600660248201526510b0b236b4b760d11b6044820152606490fd5b15611c4957565b60405162461bcd60e51b815260206004820152600b60248201526a189b1858dadb1a5cdd195960aa1b6044820152606490fd5b15611c8357565b60405162461bcd60e51b815260206004820152600760248201526608585b5bdd5b9d60ca1b6044820152606490fd5b15611cb957565b60405162461bcd60e51b815260206004820152600f60248201526e042e8ded6cadc4042d8dec6d6c4def608b1b6044820152606490fd5b15611cf757565b60405162461bcd60e51b815260206004820152600860248201526708585b1b1bddd95960c21b6044820152606490fd5b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160401b038111611b5a5760051b60200190565b60405190611d71602083611ba4565b5f80835282815b828110611d8457505050565b602090604051611d9381611b89565b5f81525f8382015282828501015201611d78565b906001600160401b039093929316815260406020820152611ded611dd7845160a0604085015260e0840190611d27565b6020850151838203603f19016060850152611d27565b90604084015191603f19828203016080830152602080845192838152019301905f5b818110611e49575050506080611e46939460018060a01b0360608201511660a084015201519060c0603f1982850301910152611d27565b90565b825180516001600160a01b031686526020908101518187015260409095019490920191600101611e0f565b90929160a060c09160e0840195600180841b03168452600180831b0381511660208501526020810151604085015260408101516060850152606081015115156080850152608081015115158285015201511515910152565b15611ed357565b60405162461bcd60e51b815260206004820152600660248201526510ba37b5b2b760d11b6044820152606490fd5b9190811015611f115760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036106255790565b356001600160401b03811681036106255790565b6001600160401b038111611b5a57601f01601f191660200190565b81601f8201121561062557803590611f7f82611f4d565b92611f8d6040519485611ba4565b8284526020838301011161062557815f926020809301838601378301015290565b602060405191630181dcf160e41b828401528051602484015201511515604482015260448152611e46606482611ba4565b6001600160a01b03811615159081611ff5575090565b90503b151590565b5f546001600160a01b0316330361201057565b63118cdaa760e01b5f523360045260245ffd5b51906001600160a01b03821682036106255756fedf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42a2646970667358221220e28acc21019ecb81d2e7cedfd13aca78882a28fb870f82637bb7882353f3df9164736f6c634300081a0033000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010472f91f67c49260bdd65f016ea0757bb1fc91e00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f905f3560e01c90816301ffc9a714611a94575080630b3f78b3146119b75780630e1c2f4e1461114f5780631974932b146111125780631c4695f4146110cd578063477db86e14611070578063481c6a75146110475780636d4e24c314610f1e578063715018a614610ec457806378ab175014610ca257806379e1ccec14610c6157806385572ffb146106aa57806388ba16ab1461067b5780638da5cb5b146106545780639726f9c41461042a578063a16032cc146103d1578063b0f479a11461038c578063d0ebdbe71461025d578063df8089ef146101b6578063f2fde38b146101305763f53d0a8e14610105575f80fd5b3461012d578060031936011261012d576001546040516001600160a01b039091168152602090f35b80fd5b503461012d57602036600319011261012d5761014a611b29565b610152611ffd565b6001600160a01b031680156101a25781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b503461012d57602036600319011261012d576101d0611b29565b6101d8611ffd565b6101e181611fdf565b1561022d57600180546001600160a01b0319166001600160a01b03929092169182179055337f525117b0c654ea4d9950e296eca92b77aa3c6fdeba6217801c6f32a0ed7a09228380a380f35b60405162461bcd60e51b8152602060048201526008602482015267216164647265737360c01b6044820152606490fd5b503461012d57602036600319011261012d57610277611b29565b600154604051632474521560e21b81525f80516020612038833981519152600482015233602482015290602090829060449082906001600160a01b03165afa8015610381576102cd918491610352575b50611c0d565b6102d681611fdf565b1561032257600580546001600160a01b0319166001600160a01b03929092169182179055337fc64707e618a83637fc41ad1e3aa4242bd5fdd353f3d60bc0faf40db0d7d860788380a380f35b60405162461bcd60e51b815260206004820152600860248201526710b6b0b730b3b2b960c11b6044820152606490fd5b610374915060203d60201161037a575b61036c8183611ba4565b810190611bf5565b5f6102c7565b503d610362565b6040513d85823e3d90fd5b503461012d578060031936011261012d576040517f000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b8606001600160a01b03168152602090f35b503461012d57604036600319011261012d5760406103ed611ae7565b916001600160401b036103fe611b13565b931681526006602052209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b503461012d5760c036600319011261012d57610444611ae7565b61044c611b13565b906044356001600160401b0381116106505736602382011215610650578060040135906001600160401b03821161064c57366024838301011161064c57604036606319011261064c57604051906104a282611b89565b6064358252608435928315158403610648576020830193845260a435936002851015610644579261053360606105b499989694602494600160209a98526040519860018060a01b03168a8a01528989526104fd60408a611ba4565b806040519687938c8086015282604086015201848401378a838284010152601f801991011681010301601f198101845283611ba4565b6001610546610540611d62565b92611fae565b930361063d577f00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f915b6040519561057c87611b3f565b865286860152604085015260018060a01b03166060840152608083015260405194859283926320487ded60e01b845260048401611da7565b03817f000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b8606001600160a01b03165afa90811561063157906105fa575b602090604051908152f35b506020813d602011610629575b8161061460209383611ba4565b8101031261062557602090516105ef565b5f80fd5b3d9150610607565b604051903d90823e3d90fd5b869161056f565b8780fd5b8680fd5b8480fd5b8380fd5b503461012d578060031936011261012d57546040516001600160a01b039091168152602090f35b503461012d57602036600319011261012d5760ff60406020926004358152600284522054166040519015158152f35b503461012d57602036600319011261012d576004356001600160401b038111610c5d5760a06003198236030112610c5d577f000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b8606001600160a01b03163303610c4a5760405161071781611b3f565b816004013581526024820135906001600160401b0382168203610650576020810191825260448301356001600160401b03811161064c5761075e9060043691860101611f68565b926040820193845260648101356001600160401b038111610be6576107899060043691840101611f68565b90606083019182526084810135906001600160401b038211610648570136602382011215610be65760048101356107bf81611d4b565b916107cd6040519384611ba4565b818352602060048185019360061b8301010190368211610c4657602401915b818310610bfd57505050608083015251918251830192602081818601950312610be6576020810151906001600160401b03821161064857019280603f85011215610be6578560208501519461084086611f4d565b9561084e6040519788611ba4565b808752602087019360408383010111610bf95780604060209301855e8601015285608060405161087d81611b3f565b828152826020820152826040820152826060820152015260a0845103610bea5760a084805181010312610be65751906001600160401b038216809203610be6576108c960408501612023565b936108d660608201612023565b608082015160a083015190966001600160a01b03908116969216947fedc6e67b7f382e06fc55950940693789ec865cf44b786836c295e1a7ff6694858201610bb8578015610bb8578615610bc75785158015610bd6575b610bc7578715610bb85760405160809161094682611b3f565b8152602081019788526040810196875260608101988952015251610992604051809261097e6020830195604087526060840190611d27565b90604083015203601f198101835282611ba4565b51902090818752600260205260ff604088205416610b8757869551602081805181010312610648576001600160401b03906001600160a01b03906109d890602001612023565b1691511686526006602052604086209060018060a01b03165f52602052610a0560ff60405f205416611cf0565b8452600260205260408420600160ff19825416179055610a2783511515611c7c565b7f000000000000000000000000000000000000000000000000000000000000000015610b085780516001600160a01b03908116855260036020526040852054610a7291161515611cb2565b80516001600160a01b0390811685526003602052604085205491519251935193811693928116929116803b1561064c576040516359508f8f60e01b81526001600160a01b039384166004820152939092166024840152604483015282908290818381606481015b03925af18015610afd57610aec57505080f35b81610af691611ba4565b61012d5780f35b6040513d84823e3d90fd5b51915160405191926001600160a01b0316610b2283611b6e565b8252602082015260408101839052606081018390526001608082015260a0810183905260055491516001600160a01b03928316921690823b15610b8257610ad992849283604051809681958294636defd45560e01b845260048401611e74565b505050fd5b60405162461bcd60e51b81526020600482015260096024820152681c1c9bd8d95cdcd95960ba1b6044820152606490fd5b6301b44b5f60e11b8a5260048afd5b63209e29c560e21b8a5260048afd5b50610be086611fdf565b1561092d565b8580fd5b6366289e3960e11b8652600486fd5b8280fd5b604083360312610c465760405190610c1482611b89565b8335906001600160a01b0382168203610c4257826020926040945282860135838201528152019201916107ec565b8a80fd5b8880fd5b6335fdcccd60e21b825233600452602482fd5b5080fd5b503461012d57602036600319011261012d576020906001600160a01b03610c86611b29565b16815260038252604060018060a01b0391205416604051908152f35b503461012d57606036600319011261012d57610cbc611b29565b6024356001600160401b038111610bf957610cdb903690600401611bc5565b90916044356001600160401b03811161064c57610cfc903690600401611bc5565b600154604051632474521560e21b81525f805160206120388339815191526004820152336024820152919492939190602090829060449082906001600160a01b03165afa8015610eb957610d569188916103525750611c0d565b6001600160a01b0316938415610e8757838203610e5857855b828110610d7a578680f35b600190610da36001600160a01b03610d9b610d96848a8a611f01565b611f25565b161515611ecc565b610db1610d96828888611f01565b8789526004602052604089206001600160401b03610dd8610dd3858989611f01565b611f39565b165f5260205260405f2090838060a01b03166bffffffffffffffffffffffff60a01b825416179055610e0e610dd3828686611f01565b6001600160401b03838060a01b03610e2a610d96858b8b611f01565b169116337fffc69ac19640cba1401d95c27b77e155ce08c0a70946fb435fbd7e0bc7b0c65c8b80a401610d6f565b60405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600a60248201526910b9b931903a37b5b2b760b11b6044820152606490fd5b6040513d89823e3d90fd5b503461012d578060031936011261012d57610edd611ffd565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461012d57604036600319011261012d57610f38611b29565b610f40611b13565b600154604051632474521560e21b81525f80516020612038833981519152600482015233602482015291929190602090829060449082906001600160a01b03165afa801561103c57610f989185916103525750611c0d565b610fa9610fa482611fdf565b611ecc565b610fb282611fdf565b1561100c576001600160a01b0390811680845260036020526040842080546001600160a01b03191693909216928317909155337fc2677273938f50fd26297a86f7c15963e77c4ec9141bbf83f2a7f33cfc2ca1638480a480f35b60405162461bcd60e51b8152602060048201526008602482015267042d8dec6d6c4def60c31b6044820152606490fd5b6040513d86823e3d90fd5b503461012d578060031936011261012d576005546040516001600160a01b039091168152602090f35b503461012d57604036600319011261012d576001600160401b036040611094611b29565b9261109d611afd565b9360018060a01b0316815260046020522091165f52602052602060405f2060018060a01b03905416604051908152f35b503461012d578060031936011261012d576040517f00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f6001600160a01b03168152602090f35b503461012d578060031936011261012d5760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b5061010036600319011261062557611165611b29565b9061116e611afd565b6044356001600160a01b0381169390849003610625576084356001600160a01b0381169190606435908390036106255760403660a319011261062557604051916111b783611b89565b60a435835260c435968715158803610625576020840197885260e43591600283101561062557600154604051630723eb0360e51b81523360048201526001600160a01b0390911690602081602481855afa801561182457611220915f9161199e575b5015611c42565b604051630723eb0360e51b81526004810184905290602082602481845afa9081156118245761125b6020926024945f91611981575015611c42565b604051635b14f18360e01b815230600482015292839182905afa908115611824575f91611962575b5061193457611293841515611c7c565b6001600160a01b039081165f818152600360205260409020549099916112bb91161515611cb2565b6040516370a0823160e01b81523360048201526020816024818d5afa80156118245785915f916118ff575b50106118cf57811561189e575f8981526004602090815260408083206001600160401b038b1684529091529020546001600160a01b03161561186a576113f6916001611404926001600160401b038a1692835f52600660205260405f208a5f5260205261135960ff60405f205416611cf0565b8c5f52600460205260405f20845f5260205260405f20838060a01b0390541690604051946020860152604085015260608401528660808401527f1239198480c7d1f903aa6af6bf96c8761379a30bb48797c93d6a1e5800996b7b60a084015260a083526113c760c084611ba4565b52604051966020880152602087526113e0604088611ba4565b6040519283916020808401526040830190611d27565b03601f198101835282611ba4565b6001611417611411611d62565b95611fae565b9214938415611863577f00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f915b6040519661145088611b3f565b87526020870152604086015260018060a01b03166060850152608084015260018060a01b037f000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b8601691604051916320487ded60e01b8352602083806114b8888a60048401611da7565b0381875afa928315611824575f9361182f575b507f00000000000000000000000000000000000000000000000000000000000000001561178f578787526003602090815260408089205490516323b872dd60e01b8184019081523360248301526001600160a01b0390921660448201526064810184905289919061153f81608481016113f6565b5190828c5af1156117845786513d61177b5750873b155b61176757869760405191825233917fd6aba49fa5adb7dbc18ab12d057e77c75e5d4b345cf473c7514afbbd6f5fc62660203392a45b156116f7576040516323b872dd60e01b815233600482015230602482015260448101829052906001600160a01b037f00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f16906020836064818a865af1908115610eb9576020936044926116dc575b50604051978893849263095ea7b360e01b845287600485015260248401525af19283156116d157611649946020946116b6575b50856040518096819582946396f4e9f960e01b845260048401611da7565b03925af1908115610afd578291611684575b505b7f54791b38f3859327992a1ca0590ad3c0f08feba98d1a4f56ab0dca74d203392a8280a280f35b90506020813d6020116116ae575b8161169f60209383611ba4565b8101031261062557515f61165b565b3d9150611692565b6116cc90853d871161037a5761036c8183611ba4565b61162b565b6040513d87823e3d90fd5b6116f290853d871161037a5761036c8183611ba4565b6115f8565b6040516396f4e9f960e01b815294506020938593849291839161171d9160048401611da7565b03925af1908115610afd578291611735575b5061165d565b90506020813d60201161175f575b8161175060209383611ba4565b8101031261062557515f61172f565b3d9150611743565b635274afe760e01b87526004889052602487fd5b60011415611556565b6040513d88823e3d90fd5b6040519761179c89611b6e565b885260208801525f60408801819052606088018190526080880181905260a08801526005546001600160a01b0316803b1561062557604051636defd45560e01b8152975f9189918290849082906117f7903360048401611e74565b03925af180156118245761180e575b85965061158b565b9450945f61181b91611ba4565b5f938590611806565b6040513d5f823e3d90fd5b9092506020813d60201161185b575b8161184b60209383611ba4565b810103126106255751915f6114cb565b3d915061183e565b5f91611443565b60405162461bcd60e51b815260206004820152600c60248201526b10b232b9ba34b730ba34b7b760a11b6044820152606490fd5b60405162461bcd60e51b815260206004820152600960248201526810b932b1b2b4bb32b960b91b6044820152606490fd5b60405162461bcd60e51b81526020600482015260086024820152672162616c616e636560c01b6044820152606490fd5b9150506020813d60201161192c575b8161191b60209383611ba4565b81010312610625578490515f6112e6565b3d915061190e565b60405162461bcd60e51b81526020600482015260066024820152651c185d5cd95960d21b6044820152606490fd5b61197b915060203d60201161037a5761036c8183611ba4565b5f611283565b6119989150843d861161037a5761036c8183611ba4565b5f611219565b611998915060203d60201161037a5761036c8183611ba4565b34610625576060366003190112610625576119d0611ae7565b6119d8611b13565b6044359182151580930361062557600154604051632474521560e21b81525f8051602061203883398151915260048201523360248201529190602090839060449082906001600160a01b03165afa918215611824576001600160401b0392611a46915f91611a755750611c0d565b165f52600660205260405f209060018060a01b03165f5260205260405f209060ff801983541691161790555f80f35b611a8e915060203d60201161037a5761036c8183611ba4565b866102c7565b34610625576020366003190112610625576004359063ffffffff60e01b8216809203610625576020916385572ffb60e01b8114908115611ad6575b5015158152f35b6301ffc9a760e01b14905083611acf565b600435906001600160401b038216820361062557565b602435906001600160401b038216820361062557565b602435906001600160a01b038216820361062557565b600435906001600160a01b038216820361062557565b60a081019081106001600160401b03821117611b5a57604052565b634e487b7160e01b5f52604160045260245ffd5b60c081019081106001600160401b03821117611b5a57604052565b604081019081106001600160401b03821117611b5a57604052565b90601f801991011681019081106001600160401b03821117611b5a57604052565b9181601f84011215610625578235916001600160401b038311610625576020808501948460051b01011161062557565b90816020910312610625575180151581036106255790565b15611c1457565b60405162461bcd60e51b815260206004820152600660248201526510b0b236b4b760d11b6044820152606490fd5b15611c4957565b60405162461bcd60e51b815260206004820152600b60248201526a189b1858dadb1a5cdd195960aa1b6044820152606490fd5b15611c8357565b60405162461bcd60e51b815260206004820152600760248201526608585b5bdd5b9d60ca1b6044820152606490fd5b15611cb957565b60405162461bcd60e51b815260206004820152600f60248201526e042e8ded6cadc4042d8dec6d6c4def608b1b6044820152606490fd5b15611cf757565b60405162461bcd60e51b815260206004820152600860248201526708585b1b1bddd95960c21b6044820152606490fd5b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6001600160401b038111611b5a5760051b60200190565b60405190611d71602083611ba4565b5f80835282815b828110611d8457505050565b602090604051611d9381611b89565b5f81525f8382015282828501015201611d78565b906001600160401b039093929316815260406020820152611ded611dd7845160a0604085015260e0840190611d27565b6020850151838203603f19016060850152611d27565b90604084015191603f19828203016080830152602080845192838152019301905f5b818110611e49575050506080611e46939460018060a01b0360608201511660a084015201519060c0603f1982850301910152611d27565b90565b825180516001600160a01b031686526020908101518187015260409095019490920191600101611e0f565b90929160a060c09160e0840195600180841b03168452600180831b0381511660208501526020810151604085015260408101516060850152606081015115156080850152608081015115158285015201511515910152565b15611ed357565b60405162461bcd60e51b815260206004820152600660248201526510ba37b5b2b760d11b6044820152606490fd5b9190811015611f115760051b0190565b634e487b7160e01b5f52603260045260245ffd5b356001600160a01b03811681036106255790565b356001600160401b03811681036106255790565b6001600160401b038111611b5a57601f01601f191660200190565b81601f8201121561062557803590611f7f82611f4d565b92611f8d6040519485611ba4565b8284526020838301011161062557815f926020809301838601378301015290565b602060405191630181dcf160e41b828401528051602484015201511515604482015260448152611e46606482611ba4565b6001600160a01b03811615159081611ff5575090565b90503b151590565b5f546001600160a01b0316330361201057565b63118cdaa760e01b5f523360045260245ffd5b51906001600160a01b03821682036106255756fedf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42a2646970667358221220e28acc21019ecb81d2e7cedfd13aca78882a28fb870f82637bb7882353f3df9164736f6c634300081a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010472f91f67c49260bdd65f016ea0757bb1fc91e00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f

-----Decoded View---------------
Arg [0] : _router (address): 0xB4e1Ff7882474BB93042be9AD5E1fA387949B860
Arg [1] : _isL1 (bool): False
Arg [2] : _administrator (address): 0x10472f91f67C49260BDD65F016ea0757bb1Fc91e
Arg [3] : _link (address): 0x71052BAe71C25C78E37fD12E5ff1101A71d9018F

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000b4e1ff7882474bb93042be9ad5e1fa387949b860
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 00000000000000000000000010472f91f67c49260bdd65f016ea0757bb1fc91e
Arg [3] : 00000000000000000000000071052bae71c25c78e37fd12e5ff1101a71d9018f


Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.