Source Code
Overview
SOPH Balance
0 SOPH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
L2SharedBridge
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.3
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import {IL1ERC20Bridge} from "./interfaces/IL1ERC20Bridge.sol"; import {IL2SharedBridge} from "./interfaces/IL2SharedBridge.sol"; import {IL2Messenger} from "./interfaces/IL2Messenger.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface MintableToken { function mint(address _to, uint256 _amount) external; function burn(uint256 _amount) external; } /// @author Sophon /// @notice Forked from ML L1SharedBridge contract /// @custom:security-contact [email protected] /// @notice The "default" bridge implementation for the ERC20 tokens. Note, that it does not /// support any custom token logic, i.e. rebase tokens' functionality is not supported. contract L2SharedBridge is IL2SharedBridge, Initializable { using SafeERC20 for IERC20; uint160 constant SYSTEM_CONTRACTS_OFFSET = 0x8000; // 2^15 /// @dev The address of the L1 shared bridge counterpart. address public override l1SharedBridge; /// @dev Contract is expected to be used as proxy implementation. /// @dev Disable the initialization to prevent Parity hack. /// @dev The address of the USDC token on L1. address public immutable L1_USDC_TOKEN; /// @dev The address of the USDC token on L2. address public immutable L2_USDC_TOKEN; constructor(address _l1UsdcToken, address _l2UsdcToken) { L1_USDC_TOKEN = _l1UsdcToken; L2_USDC_TOKEN = _l2UsdcToken; _disableInitializers(); } /// @notice Initializes the bridge contract for later use. Expected to be used in the proxy. /// @param _l1SharedBridge The address of the L1 Bridge contract. /// _l1Bridge The address of the legacy L1 Bridge contract. function initialize(address _l1SharedBridge) external reinitializer(1) { require(_l1SharedBridge != address(0), "bf"); l1SharedBridge = _l1SharedBridge; } /// @notice Finalize the deposit and mint funds /// @param _l1Sender The account address that initiated the deposit on L1 /// @param _l2Receiver The account address that would receive minted ether /// _l1Token The address of the token that was locked on the L1 /// @param _amount Total amount of tokens deposited from L1 /// _data [UNUSED] The additional data that user can pass with the deposit function finalizeDeposit(address _l1Sender, address _l2Receiver, address, uint256 _amount, bytes calldata) external override { // Only the L1 bridge counterpart can initiate and finalize the deposit. require(undoL1ToL2Alias(msg.sender) == l1SharedBridge, "mq"); MintableToken(L2_USDC_TOKEN).mint(_l2Receiver, _amount); emit FinalizeDeposit(_l1Sender, _l2Receiver, L2_USDC_TOKEN, _amount); } /// @notice Initiates a withdrawal by burning funds on the contract and sending the message to L1 /// where tokens would be unlocked /// @param _l1Receiver The account address that should receive funds on L1 /// _l2Token The L2 token address which is withdrawn /// @param _amount The total amount of tokens to be withdrawn function withdraw(address _l1Receiver, address, uint256 _amount) external override { require(_amount > 0, "Amount cannot be zero"); // transfer from msg.sender to here and then burn IERC20(L2_USDC_TOKEN).safeTransferFrom(msg.sender, address(this), _amount); MintableToken(L2_USDC_TOKEN).burn(_amount); // encode the message for l2ToL1log sent with withdraw initialization bytes memory message = abi.encodePacked(IL1ERC20Bridge.finalizeWithdrawal.selector, _l1Receiver, L1_USDC_TOKEN, _amount); IL2Messenger(address(SYSTEM_CONTRACTS_OFFSET + 0x08)).sendToL1(message); emit WithdrawalInitiated(msg.sender, _l1Receiver, L2_USDC_TOKEN, _amount); } function l1TokenAddress(address) external view returns (address) { return L1_USDC_TOKEN; } function l2TokenAddress(address) public view override returns (address) { return L2_USDC_TOKEN; } /*////////////////////////////////////////////////////////////// UTILS //////////////////////////////////////////////////////////////*/ /// @notice Utility function that converts the msg.sender viewed on L2 to the /// address that submitted a tx to the inbox on L1 /// @param l2Address L2 address as viewed in msg.sender /// @return l1Address the address in the L1 that triggered the tx to L2 function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { uint160 offset = uint160(0x1111000000000000000000000000000000001111); unchecked { l1Address = address(uint160(l2Address) - offset); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol) pragma solidity ^0.8.0; import "./IBeacon.sol"; import "../Proxy.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. * * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't * conflict with the storage layout of the implementation behind the proxy. * * _Available since v3.4._ */ contract BeaconProxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the proxy with `beacon`. * * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity * constructor. * * Requirements: * * - `beacon` must be a contract with the interface {IBeacon}. */ constructor(address beacon, bytes memory data) payable { _upgradeBeaconToAndCall(beacon, data, false); } /** * @dev Returns the current beacon address. */ function _beacon() internal view virtual returns (address) { return _getBeacon(); } /** * @dev Returns the current implementation address of the associated beacon. */ function _implementation() internal view virtual override returns (address) { return IBeacon(_getBeacon()).implementation(); } /** * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}. * * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. * * Requirements: * * - `beacon` must be a contract. * - The implementation returned by `beacon` must be a contract. */ function _setBeacon(address beacon, bytes memory data) internal virtual { _upgradeBeaconToAndCall(beacon, data, false); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol) pragma solidity ^0.8.0; import "./IBeacon.sol"; import "../../access/Ownable.sol"; import "../../utils/Address.sol"; /** * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their * implementation contract, which is where they will delegate all function calls. * * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon. */ contract UpgradeableBeacon is IBeacon, Ownable { address private _implementation; /** * @dev Emitted when the implementation returned by the beacon is changed. */ event Upgraded(address indexed implementation); /** * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the * beacon. */ constructor(address implementation_) { _setImplementation(implementation_); } /** * @dev Returns the current implementation address. */ function implementation() public view virtual override returns (address) { return _implementation; } /** * @dev Upgrades the beacon to a new implementation. * * Emits an {Upgraded} event. * * Requirements: * * - msg.sender must be the owner of the contract. * - `newImplementation` must be a contract. */ function upgradeTo(address newImplementation) public virtual onlyOwner { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Sets the implementation contract address for this beacon * * Requirements: * * - `newImplementation` must be a contract. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract"); _implementation = newImplementation; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @author Matter Labs // note we use the IL1ERC20Bridge only to send L1<>L2 messages, // and we use this interface so that when the switch happened the old messages could be processed interface IL1ERC20Bridge { function finalizeWithdrawal( uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes calldata _message, bytes32[] calldata _merkleProof ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @author Matter Labs interface IL2SharedBridge { event FinalizeDeposit( address indexed l1Sender, address indexed l2Receiver, address indexed l2Token, uint256 amount ); event WithdrawalInitiated( address indexed l2Sender, address indexed l1Receiver, address indexed l2Token, uint256 amount ); function finalizeDeposit( address _l1Sender, address _l2Receiver, address _l1Token, uint256 _amount, bytes calldata _data ) external; function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external; function l1TokenAddress(address _l2Token) external view returns (address); function l2TokenAddress(address _l1Token) external view returns (address); function l1SharedBridge() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /** * @author Matter Labs * @custom:security-contact [email protected] * @notice Smart contract for sending arbitrary length messages to L1 * @dev by default ZkSync can send fixed-length messages on L1. * A fixed length message has 4 parameters `senderAddress`, `isService`, `key`, `value`, * the first one is taken from the context, the other three are chosen by the sender. * @dev To send a variable-length message we use this trick: * - This system contract accepts an arbitrary length message and sends a fixed length message with * parameters `senderAddress == this`, `isService == true`, `key == msg.sender`, `value == keccak256(message)`. * - The contract on L1 accepts all sent messages and if the message came from this system contract * it requires that the preimage of `value` be provided. */ interface IL2Messenger { /// @notice Sends an arbitrary length message to L1. /// @param _message The variable length message to be sent to L1. /// @return Returns the keccak256 hashed value of the message. function sendToL1(bytes memory _message) external returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev 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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../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. * * By default, the owner account will be the one that deploys the contract. 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; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @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 { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _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 v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
{ "viaIR": false, "remappings": [ "@era-contracts/=node_modules/era-contracts/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", "forge-std/=lib/forge-std/src/" ], "evmVersion": "cancun", "outputSelection": { "*": { "*": [ "abi" ] } }, "optimizer": { "enabled": true, "mode": "3", "fallback_to_optimizing_for_size": false, "disable_system_request_memoization": true }, "metadata": {}, "libraries": {}, "detectMissingLibraries": false, "enableEraVMExtensions": false, "forceEVMLA": false }
[{"inputs":[{"internalType":"address","name":"_l1UsdcToken","type":"address"},{"internalType":"address","name":"_l2UsdcToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Sender","type":"address"},{"indexed":true,"internalType":"address","name":"l2Receiver","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FinalizeDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l2Sender","type":"address"},{"indexed":true,"internalType":"address","name":"l1Receiver","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalInitiated","type":"event"},{"inputs":[],"name":"L1_USDC_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L2_USDC_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Sender","type":"address"},{"internalType":"address","name":"_l2Receiver","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"finalizeDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_l1SharedBridge","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1SharedBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"l1TokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"l2TokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_l1Receiver","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
9c4d535b00000000000000000000000000000000000000000000000000000000000000000100012bf6fa7aefbe0501d2b56ee474766e8878e010c2d6455c251e0e1e5b2400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000bf4fdf7bf4014ea78c0a07259fbc4315cb10d94e00000000000000000000000027553b610304b6ab77855a963f8208443d773e60
Deployed Bytecode
0x0002000000000002000a00000000000200000000030100190000006003300270000000ed03300197000100000031035500000001002001900000001a0000c13d0000008004000039000000400040043f000000040030008c000001510000413d000000000201043b000000e002200270000000f80020009c000000680000213d000000fe0020009c000000890000213d000001010020009c000000ba0000613d000001020020009c000001510000c13d0000000001000416000000000001004b000000b20000613d000001510000013d0000000002000416000000000002004b000001510000c13d0000001f02300039000000ee02200197000000c002200039000000400020043f0000001f0430018f000000ef05300198000000c0025000390000002b0000613d000000c006000039000000000701034f000000007807043c0000000006860436000000000026004b000000270000c13d000000000004004b000000380000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000400030008c000001510000413d000000c00100043d000000f00010009c000001510000213d000000e00200043d000000f00020009c000001510000213d000000800010043f000000a00020043f000000000300041a0000ff0000300190000001610000c13d000000ff0430018f000000ff0040008c0000005e0000613d000000ff013001bf000000000010041b000000ff01000039000000400200043d0000000000120435000000ed0020009c000000ed0200804100000040012002100000000002000414000000ed0020009c000000ed02008041000000c002200210000000000112019f000000f5011001c70000800d020000390000000103000039000000f60400004103ae03a40000040f0000000100200190000001510000613d000000a00200043d000000800100043d0000014000000443000001600010044300000020010000390000018000100443000001a000200443000001000010044300000002010000390000012000100443000000f701000041000003af0001042e000000f90020009c000000a50000213d000000fc0020009c000000be0000613d000000fd0020009c000001510000c13d000000640030008c000001510000413d0000000002000416000000000002004b000001510000c13d0000000402100370000000000302043b000000f00030009c000001510000213d0000002402100370000000000202043b000000f00020009c000001510000213d0000004401100370000000000101043b000000000001004b000001810000c13d000000f301000041000000800010043f0000002001000039000000840010043f0000001501000039000000a40010043f0000011701000041000000c40010043f0000011801000041000003b000010430000000ff0020009c000001420000613d000001000020009c000001510000c13d000000240030008c000001510000413d0000000002000416000000000002004b000001510000c13d0000000401100370000000000101043b000000f00010009c000001510000213d000000000200041a0000ffff00200190000001750000c13d000000000001004b000001ab0000c13d000000f301000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f0000012601000041000000c40010043f0000011801000041000003b000010430000000fa0020009c000001480000613d000000fb0020009c000001510000c13d000000240030008c000001510000413d0000000002000416000000000002004b000001510000c13d0000000401100370000000000101043b000000f00010009c000001510000213d0000000001000412000800000001001d000700200000003d000080050100003900000044030000390000000004000415000000080440008a0000015a0000013d0000000001000416000000000001004b000001510000c13d000001530000013d000000a40030008c000001510000413d0000000002000416000000000002004b000001510000c13d0000000402100370000000000502043b000000f00050009c000001510000213d0000002402100370000000000602043b000000f00060009c000001510000213d0000004402100370000000000202043b000000f00020009c000001510000213d0000006402100370000000000702043b0000008402100370000000000202043b000001090020009c000001510000213d0000002304200039000000000034004b000001510000813d0000000404200039000000000141034f000000000101043b000001090010009c000001510000213d00000000011200190000002401100039000000000031004b000001510000213d000500000007001d000600000006001d000400000005001d000000000100041a00000010011002700000000002000411000001190220009a000000000112013f000000f000100198000001d50000c13d0000010301000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000000ed0010009c000000ed01008041000000c00110021000000104011001c7000080050200003903ae03a90000040f00000001002001900000033f0000613d000000000101043b0000010a020000410000000000200443000000f001100197000300000001001d00000004001004430000000001000414000000ed0010009c000000ed01008041000000c0011002100000010b011001c7000080020200003903ae03a90000040f00000001002001900000033f0000613d000000000101043b000000000001004b00000006020000290000000503000029000001510000613d000000400400043d000000240140003900000000003104350000011b010000410000000000140435000200000004001d0000000401400039000000000021043500000000010004140000000302000029000000040020008c0000012b0000613d0000000202000029000000ed0020009c000000ed020080410000004002200210000000ed0010009c000000ed01008041000000c001100210000000000121019f0000011c011001c7000000030200002903ae03a40000040f00000000030100190000006003300270000000ed0030019d00010000000103550000000100200190000003400000613d00000002010000290000011d0010009c000001a50000813d0000000202000029000000400020043f00000005010000290000000000120435000000ed0020009c000000ed0200804100000040012002100000000002000414000000ed0020009c000000ed02008041000000c002200210000000000112019f000000f5011001c70000800d0200003900000004030000390000011e04000041000000040500002900000006060000290000000307000029000001ba0000013d0000000001000416000000000001004b000001510000c13d000000000100041a00000010011002700000015d0000013d000000240030008c000001510000413d0000000002000416000000000002004b000001510000c13d0000000401100370000000000101043b000000f00010009c000001530000a13d0000000001000019000003b0000104300000000001000412000a00000001001d000900000000003d0000800501000039000000440300003900000000040004150000000a0440008a0000000504400210000001030200004103ae038b0000040f000000f001100197000000800010043f0000012701000041000003af0001042e000000400100043d0000006402100039000000f10300004100000000003204350000004402100039000000f2030000410000000000320435000000240210003900000027030000390000000000320435000000f3020000410000000000210435000000040210003900000020030000390000000000320435000000ed0010009c000000ed010080410000004001100210000000f4011001c7000003b000010430000000f301000041000000800010043f0000002001000039000000840010043f0000002e01000039000000a40010043f0000012001000041000000c40010043f0000012101000041000000e40010043f0000012201000041000003b000010430000500000004001d000600000001001d000400000003001d0000010301000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000000ed0010009c000000ed01008041000000c00110021000000104011001c7000080050200003903ae03a90000040f00000001002001900000033f0000613d000000000301043b000000400600043d00000064016000390000000604000029000000000041043500000044016000390000000004000410000000000041043500000020016000390000010504000041000000000041043500000064040000390000000000460435000000240460003900000000050004110000000000540435000001060060009c000001bf0000a13d0000011f01000041000000000010043f0000004101000039000000040010043f0000011001000041000003b000010430000001230220019700000010011002100000012401100197000000000121019f00000001011001bf000000000010041b0000000103000039000000800030043f0000000001000414000000ed0010009c000000ed01008041000000c00110021000000125011001c70000800d02000039000000f60400004103ae03a40000040f0000000100200190000001510000613d0000000001000019000003af0001042e000001070060009c000001a50000213d000000a005600039000000e004600039000000000054004b000001a50000413d000000f002300197000000400040043f0000002003000039000200000005001d0000000000350435000000c0036000390000010804000041000000000043043500000000030604330000000004000414000000040020008c000300000002001d000001df0000c13d00000001020000390000000001000031000001f00000013d000000f301000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f0000011a01000041000000c40010043f0000011801000041000003b000010430000000ed0010009c000000ed010080410000004001100210000000ed0030009c000000ed030080410000006003300210000000000113019f000000ed0040009c000000ed04008041000000c003400210000000000131019f03ae03a40000040f000000010220018f00010000000103550000006001100270000000ed0010019d000000ed01100197000000000001004b0000020c0000c13d00000060090000390000000001090433000000000002004b000002380000c13d000000000001004b0000025c0000c13d000000400300043d000600000003001d000000f30100004100000000001304350000000401300039000000200200003900000000002104350000002402300039000000020100002903ae03780000040f00000006020000290000000001210049000000ed0010009c000000ed01008041000000ed0020009c000000ed0200804100000060011002100000004002200210000000000121019f000003b000010430000001090010009c000001a50000213d0000001f0410003900000128044001970000003f044000390000012804400197000000400500043d00000000044500190000000009050019000000000054004b00000000050000390000000105004039000001090040009c000001a50000213d0000000100500190000001a50000c13d000000400040043f000000000519043600000128031001980000001f0410018f000500000005001d000000000135001900000001050003670000022a0000613d000000000605034f0000000507000029000000006806043c0000000007870436000000000017004b000002260000c13d000000000004004b000001f30000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000001f30000013d000200000009001d000000000001004b000002690000c13d0000010a010000410000000000100443000000030100002900000004001004430000000001000414000000ed0010009c000000ed01008041000000c0011002100000010b011001c7000080020200003903ae03a90000040f00000001002001900000033f0000613d000000000101043b000000000001004b000002650000c13d000000400100043d00000044021000390000011503000041000000000032043500000024021000390000001d030000390000000000320435000000f3020000410000000000210435000000040210003900000020030000390000000000320435000000ed0010009c000000ed01008041000000400110021000000116011001c7000003b0000104300000000502000029000000ed0020009c000000ed020080410000004002200210000000ed0010009c000000ed010080410000006001100210000000000121019f000003b00001043000000002010000290000000001010433000000000001004b000002800000613d0000010c0010009c0000000502000029000001510000213d000000200010008c000001510000413d0000000001020433000000000001004b0000000002000039000000010200c039000000000021004b000001510000c13d000000000001004b000002800000c13d000000400100043d00000064021000390000010d03000041000000000032043500000044021000390000010e03000041000000000032043500000024021000390000002a030000390000016a0000013d0000010a010000410000000000100443000000030100002900000004001004430000000001000414000000ed0010009c000000ed01008041000000c0011002100000010b011001c7000080020200003903ae03a90000040f00000001002001900000033f0000613d000000000101043b000000000001004b000001510000613d000000400200043d0000010f010000410000000001120436000200000001001d000500000002001d00000004012000390000000602000029000000000021043500000000010004140000000302000029000000040020008c000002ad0000613d0000000502000029000000ed0020009c000000ed020080410000004002200210000000ed0010009c000000ed01008041000000c001100210000000000121019f00000110011001c7000000030200002903ae03a40000040f00000000030100190000006003300270000000ed0030019d000100000001035500000001002001900000035f0000613d0000000501000029000001090010009c000001a50000213d0000000503000029000000400030043f0000011101000041000000020200002900000000001204350000000401000029000000600110021000000024023000390000000000120435000001030100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000000ed0010009c000000ed01008041000000c00110021000000104011001c7000080050200003903ae03a90000040f00000001002001900000033f0000613d000000000101043b00000060011002100000000503000029000000380230003900000000001204350000004c01300039000000060200002900000000002104350000004c010000390000000000130435000001120030009c000001a50000213d00000005030000290000008002300039000000400020043f0000011301000041000100000002001d0000000000120435000000840130003900000020020000390000000000210435000000a40230003900000000010304330000000000120435000000c402300039000000000001004b0000000206000029000002eb0000613d000000000300001900000000042300190000000005630019000000000505043300000000005404350000002003300039000000000013004b000002e40000413d0000001f031000390000012803300197000000000121001900000000000104350000004401300039000000ed0010009c000000ed0100804100000060011002100000000102000029000000ed0020009c000000ed020080410000004002200210000000000121019f0000000002000414000000ed0020009c000000ed02008041000000c002200210000000000112019f000080080200003903ae03a40000040f00000000030100190000006003300270000000ed03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000001057000290000030f0000613d000000000801034f0000000109000029000000008a08043c0000000009a90436000000000059004b0000030b0000c13d000000000006004b0000031c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000100000001035500000001002001900000036c0000613d0000001f01400039000000600210018f0000000101200029000000000021004b00000000020000390000000102004039000001090010009c000001a50000213d0000000100200190000001a50000c13d000000400010043f000000200030008c0000000403000029000001510000413d00000006020000290000000000210435000000ed0010009c000000ed0100804100000040011002100000000002000414000000ed0020009c000000ed02008041000000c002200210000000000121019f000000f5011001c7000000f0063001970000800d02000039000000040300003900000114040000410000000005000411000001400000013d000000000001042f000000ed033001970000001f0530018f000000ef06300198000000400200043d00000000046200190000034c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000003480000c13d000000000005004b000003590000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000000ed0020009c000000ed020080410000004002200210000000000112019f000003b000010430000000ed033001970000001f0530018f000000ef06300198000000400200043d00000000046200190000034c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000003670000c13d0000034c0000013d0000001f0530018f000000ef06300198000000400200043d00000000046200190000034c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000003730000c13d0000034c0000013d00000000430104340000000001320436000000000003004b000003840000613d000000000200001900000000052100190000000006240019000000000606043300000000006504350000002002200039000000000032004b0000037d0000413d000000000231001900000000000204350000001f0230003900000128022001970000000001210019000000000001042d000000000001042f00000000050100190000000000200443000000040100003900000005024002700000000002020031000000000121043a0000002004400039000000000031004b0000038e0000413d000000ed0030009c000000ed0300804100000060013002100000000002000414000000ed0020009c000000ed02008041000000c002200210000000000112019f00000129011001c7000000000205001903ae03a90000040f0000000100200190000003a30000613d000000000101043b000000000001042d000000000001042f000003a7002104210000000102000039000000000001042d0000000002000019000000000001042d000003ac002104230000000102000039000000000001042d0000000002000019000000000001042d000003ae00000432000003af0001042e000003b00001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff616c697a696e6700000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320696e69746908c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249800000002000000000000000000000000000000c000000100000000000000000000000000000000000000000000000000000000000000000000000000cfe7af7b00000000000000000000000000000000000000000000000000000000f54266a100000000000000000000000000000000000000000000000000000000f54266a200000000000000000000000000000000000000000000000000000000f5f1516800000000000000000000000000000000000000000000000000000000cfe7af7c00000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000b852ad3500000000000000000000000000000000000000000000000000000000b852ad3600000000000000000000000000000000000000000000000000000000c4d66de8000000000000000000000000000000000000000000000000000000005615ef5d00000000000000000000000000000000000000000000000000000000a6e54b77310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e020000020000000000000000000000000000004400000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f000000000000000000000000000000000000000000000000ffffffffffffff1f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564000000000000000000000000000000000000000000000000ffffffffffffffff1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f742073756363656564000000000000000000000000000000000000000000005361666545524332303a204552433230206f7065726174696f6e20646964206e42966c6800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000011a2ccc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f62f84b24000000000000000000000000000000000000000000000000000000002fc3848834aac8e883a2d2a17a7514dc4f2d3dd268089df9b9f5d918259ef3b0416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000000000000000000000000000000000000000000064000000000000000000000000416d6f756e742063616e6e6f74206265207a65726f00000000000000000000000000000000000000000000000000000000000064000000800000000000000000ffffffffffffffffffffffff11110000000000000000000000000000000011116d7100000000000000000000000000000000000000000000000000000000000040c10f190000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000000000000010000000000000000b84fba9af218da60d299dc177abd5805e7ac541d2673cbee7808c10017874f634e487b7100000000000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000ffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000020000000000000000000000000000000000002000000080000000000000000062660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe002000002000000000000000000000000000000000000000000000000000000001e4b08557703ecedd2d9e0deae7dcee3d66553fda968e302d025eb7fb17c34be
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bf4fdf7bf4014ea78c0a07259fbc4315cb10d94e00000000000000000000000027553b610304b6ab77855a963f8208443d773e60
-----Decoded View---------------
Arg [0] : _l1UsdcToken (address): 0xBF4FdF7BF4014EA78C0A07259FBc4315Cb10d94E
Arg [1] : _l2UsdcToken (address): 0x27553b610304b6AB77855a963f8208443D773E60
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000bf4fdf7bf4014ea78c0a07259fbc4315cb10d94e
Arg [1] : 00000000000000000000000027553b610304b6ab77855a963f8208443d773e60
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.