ETH Price: $1,861.33 (-0.62%)

Transaction Decoder

Block:
21671364 at Jan-21-2025 07:26:47 AM +UTC
Transaction Fee:
0.009855069383584531 ETH $18.34
Gas Used:
1,279,613 Gas / 7.701601487 Gwei

Emitted Events:

347 DelayedWETH.OwnershipTransferred( previousOwner=0x00000000...000000000, newOwner=[Receiver] 0x4e59b44847b379578588920ca78fbf26c0b4956c )
348 DelayedWETH.OwnershipTransferred( previousOwner=[Receiver] 0x4e59b44847b379578588920ca78fbf26c0b4956c, newOwner=0x00000000...000000000 )
349 DelayedWETH.Initialized( version=1 )

Account State Difference:

  Address   Before After State Difference Code
(Titan Builder)
12.213980659525644541 Eth12.214067033403144541 Eth0.0000863738775
0x4e59b448...6c0B4956C
0x837eB124...4051de395
1.772325994237859454 Eth
Nonce: 31
1.762470924854274923 Eth
Nonce: 32
0.009855069383584531
0xdAF8E8cd...74A13a8EB
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 2796812686927739268784578969009201301298326925142676220219647988754715358759501042707684454977940588437997794202063575241687682674997765268273891337679479112317991192365493457552176508198340753517795831638084563597051640022290745819462520553398978398907508745441084853237921983636029331495518631803671149422250245231438151355962689217130717345640203691148242876989945254949117799912166282190358349560715467376612276928781658731758034939003365418522455649178368540593491488533050836073857557744616245094382310824439174717885683722357733912115486068357522637602959789818811326470130285724332272041836000957316879602264160184432132487310612443150517390069663383238246900263093603592129595503065080219009942233509386770914509611231262255791537488921678149047707911139290464974548027227276005391380246478415162065496867205893497720004752460471369939770879972071333614610099553734543180020338573516515587524170903471166812856666559647558496703824716273561363174806927327313496578367789880807152012213819068504133829004728660130614986231118347705604727380835805712673230859140672131448036168604769081129067386271062808977654556330957200561908555110608994321603073240140783282110428352076129114166991130273524306089119365404801676123900463187299713703100976119952344327143357440197032408986338119043647402610710386669438146304261224739795517942812378305885546316808548736528391829788394873546552557329452631340065189219627050038564488210971993825392164685268348307763656810006525775702103820634592898333606423961686237639571537007260541159208775998125184592852439430003679307674119779445031807153725595075780119399668439758880813222895805489670609798231697834352486791512878730309875171035981198544717039120979842487774397636332170803833946508812941334715319882642280058634888640303448607339027741938747999133091470015590531910859696969670292380263249434008810354459771077653788595701324562113075821545216074906721750291812210126832131543522714997109675196845151210523794685634507896331179104885019418475176628951311560351061127166434915596320927277190536938791105706511477473979890473591523008450359809413991944902901478010777346671014445529907965384155223487673403708231388556911913978601730511368392386013107792553065693911659615104010548372995160937240763527159821926410086543454047403817421387710134428930329447956669312755545500672936957492078066260633371607594095030308325438841982397943769534640205010868025767522379866950270440393601528206047376482240246617690546663773142019534685493667531843448876833992535469402477241366147498635047627095200789105197292181033277931166184638452542687201233209164835692264061084561527099395537703467920033275087417295530273727768809940692406739701069560728241417365652618848609542923625101928258981574416794477431771600440365107819800059906492730210650762927424780717641441746497482858300766041458005980733591086669052553811852180660805802721320395348040491156721893171203125623681714407946656803515426728696253605627174396387831256557159572597052878772147909611374652470011621196992002454139854236518029591773234804672217849621164222852400924652195471176273070955951099119097924050489580235784940870635265596181441940620128709432291806593001115520839125435690422201129880946315495233670947426866333258123949659978431329630650685515297232723134971280867296728059818537887688358266736457062643198614329227081578080627751118248553557248794713216172006128092393209569890214832296023656985820640721982264433093578757216948962614873465689767527488562273734219006574495598462962999335313185761079503563575280917346818786956905503756560832932139954196661922286280897827083254115291555126924182949820871070411518188314857404996522207823670987886897047805818021477127436384540218358271313396888398679122452001099828472977867224773369416001720084494479723428063835500860989139481839659853665463728314141426966516109829372402710331494791536076524587838332665690555255412882617771631760451508861176880063468665479264932123030376655259731409854085833679299597591665449902417549209589594424640214241742956065626128648821710528808443714739274181879470951178702839868275669590341977262304841424517194187645817419079479816532476924508451799737915647908809806283987084342124067208635104968944016929235782749074970415004284279738126291329723492419293222557252915497080499222790014698373440887802645063232048818680486988839280876167497720478390406546043166263018558862095948527612219702141147110038192327835573774101347523383838105786067331948637366855320850632212424623500797132284272298123807556966602043394654927615135855263827070990961169904816969737115271954483596035284521734610390965948745076516078413423037583620738316381014084210674020323766028867451167791694655345105833941506700349037236974210760808214551678917872708734813654013061021714622341155828832827688282155020926568417667829045548096197088807149800333120816278316337979245177542985606963686823269660260586937145058817377496019105625643231501546626304251813166591252548890680715909797822151868285126903328971951134230131684372531610846966773866421331239185602342791594551162493844508205852553368329006451242311431392378647377175051220949690521949638509181333425889409065872358229427782830385979044961837943512984502603075168306247513559048773310446066980443633640188557421919407521066368891669258313393584922301918933314422585461943832192909908264018417166600077998979853593558355627607774934630754685790992082991604791702061155772106014617699902461080502045711941996254219343586519637482447788288440480215474300161087347990963666545368431096476560224151684817520028789323495258792829855352488869151323081926285931773175329146823703357044770031143640501931850715551335892669784247472235286699553988080628068059322240668954270075589925337106379981250933158881914635075621794058956566710324952326504249867843087888174511248053872157973721895624214420131697281369837730152343646108472639771346145902187080578607168203564899854073679458605329299062189417439979685545478709675603694045142892410188876300415893651222798206886527177424883936229139620683483486519059716102377769097229713552028274816027826209586364924488301344682971412380436638135738189208589986276101020574357821891314204039589410393572058180605248356402638837023961721817280301043125342440996882094240204938994469831647104175453494089848247453787019547084284607086511421661080125976001278020908185510544322018655114308766899468686435788133781851937441678881928570020663730528805266011302987861252884839111492980870733245395232600694637508653120310508466833706636975906052242588023831634367885207152579211664770632912142936127481812113790677509148487312434955452181507283352534071954819404760244946664882662961136272640948969141282806221586547178774242583158050808430624600442634048146406112776702596592405071760702250531634020955090920511165375484723144001328472700790771739246292279167118223297672373302483735850058192692264710389525071240004299389152378601155980596862088589292659954141505387997213456821337995521405673006142127874214145434799344862324223020007855597249056214635552001151399950861013549950799536207643611528908216402694896113273854039397599630735062908314847928064696676284232410223497090524502881920139401951180440318644703162585804164525833414150338521650634506799157132118313533809399732817125813707790333994388514590567669574078526424543051985217611193883462754156105716511656575968456514897454540413263308349584954603680994671458391616205605545187785553469627080034493227811255819185213096650611366418938345668032278076945206854651456977391159630905408951985692358207903160533470020584335698449130532246096877033078667728629855997099973143659040058268257325385394240310087843084660282393424219502147014172790281182641204778972154918988884971476416077985613502559908927977073120540897472238373930981856181909929964802841074269921432706965641219985015357833960462882337238594807605328013014557414703307519135600842155646430912731785071771843360263516958546369371856537729068840714806429997489481649816724261828734762674492774775414607037289952299445550040054455741790804579349907629384834656009659454297896797420277541317747890922991125956273319424605464665014006260866440185750903397910808001422720359395051348805554945380073690188841713001036832791568044643340406606290382588818735765448591642110226326807936838781796606670186516296356688079158418498341690846211633614629077199946082537100439593882592588730458222980682175254130934403611268319769711966032295771032025840848362108990046588683295426673477012397982482389813847283316338563067629931968820484706739898790831854274235028666361718670384873524281910310653322642896629152351104715663727492159981343272272450161211844964824561084730769723131124461676519233207162663140381341842954863498263241105365813176500303776007079910377966181409020822293410631054018197346656851401444403528212884850496906498956749594734373290014065419743271233885730836007184408779440973211743966107482969113705961081985798240154066201234516303175438804586157635574630734409126995308513797839922195987501203763837813651489024745878278518273555275421185366291969027193662777024646508634880046759124950215115104369465625543005231288101992415011754784542181814152018525523364962278364403228781638680452239295045159882997508046582447020090646474019664822117516425183231322222563128707665675786821084917925618235043900941978999163735092552127703178178092397363437935112826477767043711654988902119575459774913192629186455882918903180167614871903786840598973348485477119238846255617290344948560521709636295262430919425315020661606113372426094031286149242582260577760841892651703561207083802619978688235879160187622313985096417661549474003992244693552590975270641823117713793577386831509341595337130400922520569291726935971434989252798661812331457183465643874299213475174424212472550935842278499918891443883670816941698126265512730352205057642178589012969597912057447304022865774711472457964048944258355256635276481495068441902239638421555434656076399122481415923618443374671730401720880379550546288160759237804325173247452178400160973757561727821359393555480086403469484904232430854341305350026860418935077450127254589806364634266430068940585952812780834723029823051313675737900032811143558965005637185268448718293752768836455426174191255375294055565223926559619740187192812686313770344903089621844261866104144866316739614204576693417719801105016825178951196820393640850744481220545168020610810504367405077621451971087636670004422337793311151039534647784563594796578726621318107660346700374381268768383896325807766610618595323438631565356283514945424448475177384135067286793210438770105888055129858348857221933140182776857893611724322319321091577056347380774764925467649780757942106664482443449855556061810729462078333043003165433934546944564128384767240097012267792193969834104595500369217408372630084102483293385173424354123231963763184766176894858282264589904928580800817502391066663399652490684988941007613182358987460068091286302497155034562149755309643593336554704097995294117892487666122386262470651511479497731588660649085332562900169863499501748061155081239989286874976794602398667881662246664747238554386015344524666963069480030535007026436314558892745983949030623569561548661859347823179525928697784523317377918962743684331511116242189310263124750758529885671493552566802697419177783386133895147125037220638945952909952429094477012850356962691121393212774838258882382114229134684869606838511707621960058159606712258988396655256017909012103296804225763551844515876880566787109501606512586372671553439976627392831313321502598831813416090534206582995464764037756185122315712973804647113355984404616656950186274882038688954433749920143049620474597996684276993739196420397297826174301818672322571671382790315556472585395134473969125564899350402534108149179088898796656865049551748462728001842209139962969875187082397369225697666814740380915082559311586242491894416925959046871121237994465947685651151522551141182229990285236353064772213419633774106455787080882147089544830721774175686903599759866116056229091420553500742424310427176519597719008096566672352171847421425823157798688094370859765986832031698965190964360976231208705164234649121627901942071529713540599574224133107408849585254527564305386772325065741351077657447622430539412330095567630615860121318013560358823604118358636439302224876252093524200400148312979016944989829301768296220714889686752220396360925983994422701944020610287593357266492687000500045566328273142680064223204104787253977187688814895383604533304818569838357375956090871587537953355241618979796193202689783446040571331009287621595848515853588907987103705006994116488421697573752023592913580400002279498865602907441859586592585940346019906226532804579087572197343399796169266172372528313937680231102626560591998448446477397207458038292938836750720867716291845760506526171704578822019234054897520436395015080919176701957910314502453499577988087716908800033556214087840763348380168608514919029799695634582013988064721694660922055670024885481583254724986433881799634491395698044385762518896622880346826280834180694503114334930022705624436440023652071897697921198752159898981189006491378193226641283229577051978272772529679250228439072297737418139134405433188165633547625752900168873061226735682632819867658

Execution Trace

Deterministic Deployer .704de1ba( )
  • DelayedWETH.60a06040( )
    // SPDX-License-Identifier: MIT
    pragma solidity 0.8.15;
    import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
    import { ISemver } from "src/universal/ISemver.sol";
    import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol";
    import { IWETH } from "src/dispute/interfaces/IWETH.sol";
    import { WETH98 } from "src/dispute/weth/WETH98.sol";
    import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
    /// @title DelayedWETH
    /// @notice DelayedWETH is an extension to WETH9 that allows for delayed withdrawals. Accounts must trigger an unlock
    ///         function before they can withdraw WETH. Accounts must trigger unlock by specifying a sub-account and an
    ///         amount of WETH to unlock. Accounts can trigger the unlock function at any time, but must wait a delay
    ///         period before they can withdraw after the unlock function is triggered. DelayedWETH is designed to be used
    ///         by the DisputeGame contracts where unlock will only be triggered after a dispute is resolved. DelayedWETH
    ///         is meant to sit behind a proxy contract and has an owner address that can pull WETH from any account and
    ///         can recover ETH from the contract itself. Variable and function naming vaguely follows the vibe of WETH9.
    ///         Not the prettiest contract in the world, but it gets the job done.
    contract DelayedWETH is OwnableUpgradeable, WETH98, IDelayedWETH, ISemver {
        /// @notice Semantic version.
        /// @custom:semver 1.0.0
        string public constant version = "1.0.0";
        /// @inheritdoc IDelayedWETH
        mapping(address => mapping(address => WithdrawalRequest)) public withdrawals;
        /// @notice Withdrawal delay in seconds.
        uint256 internal immutable DELAY_SECONDS;
        /// @notice Address of the SuperchainConfig contract.
        SuperchainConfig public config;
        /// @param _delay The delay for withdrawals in seconds.
        constructor(uint256 _delay) {
            DELAY_SECONDS = _delay;
            initialize({ _owner: address(0), _config: SuperchainConfig(address(0)) });
        }
        /// @notice Initializes the contract.
        /// @param _owner The address of the owner.
        /// @param _config Address of the SuperchainConfig contract.
        function initialize(address _owner, SuperchainConfig _config) public initializer {
            __Ownable_init();
            _transferOwnership(_owner);
            config = _config;
        }
        /// @inheritdoc IDelayedWETH
        function delay() external view returns (uint256) {
            return DELAY_SECONDS;
        }
        /// @inheritdoc IDelayedWETH
        function unlock(address _guy, uint256 _wad) external {
            // Note that the unlock function can be called by any address, but the actual unlocking capability still only
            // gives the msg.sender the ability to withdraw from the account. As long as the unlock and withdraw functions
            // are called with the proper recipient addresses, this will be safe. Could be made safer by having external
            // accounts execute withdrawals themselves but that would have added extra complexity and made DelayedWETH a
            // leaky abstraction, so we chose this instead.
            WithdrawalRequest storage wd = withdrawals[msg.sender][_guy];
            wd.timestamp = block.timestamp;
            wd.amount += _wad;
        }
        /// @inheritdoc IWETH
        function withdraw(uint256 _wad) public override(WETH98, IWETH) {
            withdraw(msg.sender, _wad);
        }
        /// @inheritdoc IDelayedWETH
        function withdraw(address _guy, uint256 _wad) public {
            require(!config.paused(), "DelayedWETH: contract is paused");
            WithdrawalRequest storage wd = withdrawals[msg.sender][_guy];
            require(wd.amount >= _wad, "DelayedWETH: insufficient unlocked withdrawal");
            require(wd.timestamp > 0, "DelayedWETH: withdrawal not unlocked");
            require(wd.timestamp + DELAY_SECONDS <= block.timestamp, "DelayedWETH: withdrawal delay not met");
            wd.amount -= _wad;
            super.withdraw(_wad);
        }
        /// @inheritdoc IDelayedWETH
        function recover(uint256 _wad) external {
            require(msg.sender == owner(), "DelayedWETH: not owner");
            uint256 amount = _wad < address(this).balance ? _wad : address(this).balance;
            payable(msg.sender).transfer(amount);
        }
        /// @inheritdoc IDelayedWETH
        function hold(address _guy, uint256 _wad) external {
            require(msg.sender == owner(), "DelayedWETH: not owner");
            allowance[_guy][msg.sender] = _wad;
            emit Approval(_guy, msg.sender, _wad);
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
    pragma solidity ^0.8.0;
    import "../utils/ContextUpgradeable.sol";
    import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {
        address private _owner;
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        function __Ownable_init() internal onlyInitializing {
            __Ownable_init_unchained();
        }
        function __Ownable_init_unchained() internal onlyInitializing {
            _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 anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing 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);
        }
        /**
         * @dev This empty reserved space is put in place to allow future versions to add new
         * variables without shifting down storage in the inheritance chain.
         * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
         */
        uint256[49] private __gap;
    }
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    /// @title ISemver
    /// @notice ISemver is a simple contract for ensuring that contracts are
    ///         versioned using semantic versioning.
    interface ISemver {
        /// @notice Getter for the semantic version of the contract. This is not
        ///         meant to be used onchain but instead meant to be used by offchain
        ///         tooling.
        /// @return Semver contract version as a string.
        function version() external view returns (string memory);
    }
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    import { IWETH } from "src/dispute/interfaces/IWETH.sol";
    /// @title IDelayedWETH
    /// @notice Interface for the DelayedWETH contract.
    interface IDelayedWETH is IWETH {
        /// @notice Represents a withdrawal request.
        struct WithdrawalRequest {
            uint256 amount;
            uint256 timestamp;
        }
        /// @notice Emitted when an unwrap is started.
        /// @param src The address that started the unwrap.
        /// @param wad The amount of WETH that was unwrapped.
        event Unwrap(address indexed src, uint256 wad);
        /// @notice Returns the withdrawal delay in seconds.
        /// @return The withdrawal delay in seconds.
        function delay() external view returns (uint256);
        /// @notice Returns a withdrawal request for the given address.
        /// @param _owner The address to query the withdrawal request of.
        /// @param _guy Sub-account to query the withdrawal request of.
        /// @return The withdrawal request for the given address-subaccount pair.
        function withdrawals(address _owner, address _guy) external view returns (uint256, uint256);
        /// @notice Unlocks withdrawals for the sender's account, after a time delay.
        /// @param _guy Sub-account to unlock.
        /// @param _wad The amount of WETH to unlock.
        function unlock(address _guy, uint256 _wad) external;
        /// @notice Extension to withdrawal, must provide a sub-account to withdraw from.
        /// @param _guy Sub-account to withdraw from.
        /// @param _wad The amount of WETH to withdraw.
        function withdraw(address _guy, uint256 _wad) external;
        /// @notice Allows the owner to recover from error cases by pulling ETH out of the contract.
        /// @param _wad The amount of WETH to recover.
        function recover(uint256 _wad) external;
        /// @notice Allows the owner to recover from error cases by pulling ETH from a specific owner.
        /// @param _guy The address to recover the WETH from.
        /// @param _wad The amount of WETH to recover.
        function hold(address _guy, uint256 _wad) external;
    }
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    /// @title IWETH
    /// @notice Interface for WETH9.
    interface IWETH {
        /// @notice Emitted when an approval is made.
        /// @param src The address that approved the transfer.
        /// @param guy The address that was approved to transfer.
        /// @param wad The amount that was approved to transfer.
        event Approval(address indexed src, address indexed guy, uint256 wad);
        /// @notice Emitted when a transfer is made.
        /// @param src The address that transferred the WETH.
        /// @param dst The address that received the WETH.
        /// @param wad The amount of WETH that was transferred.
        event Transfer(address indexed src, address indexed dst, uint256 wad);
        /// @notice Emitted when a deposit is made.
        /// @param dst The address that deposited the WETH.
        /// @param wad The amount of WETH that was deposited.
        event Deposit(address indexed dst, uint256 wad);
        /// @notice Emitted when a withdrawal is made.
        /// @param src The address that withdrew the WETH.
        /// @param wad The amount of WETH that was withdrawn.
        event Withdrawal(address indexed src, uint256 wad);
        /// @notice Returns the name of the token.
        /// @return The name of the token.
        function name() external view returns (string memory);
        /// @notice Returns the symbol of the token.
        /// @return The symbol of the token.
        function symbol() external view returns (string memory);
        /// @notice Returns the number of decimals the token uses.
        /// @return The number of decimals the token uses.
        function decimals() external pure returns (uint8);
        /// @notice Returns the balance of the given address.
        /// @param owner The address to query the balance of.
        /// @return The balance of the given address.
        function balanceOf(address owner) external view returns (uint256);
        /// @notice Returns the amount of WETH that the spender can transfer on behalf of the owner.
        /// @param owner The address that owns the WETH.
        /// @param spender The address that is approved to transfer the WETH.
        /// @return The amount of WETH that the spender can transfer on behalf of the owner.
        function allowance(address owner, address spender) external view returns (uint256);
        /// @notice Allows WETH to be deposited by sending ether to the contract.
        function deposit() external payable;
        /// @notice Withdraws an amount of ETH.
        /// @param wad The amount of ETH to withdraw.
        function withdraw(uint256 wad) external;
        /// @notice Returns the total supply of WETH.
        /// @return The total supply of WETH.
        function totalSupply() external view returns (uint256);
        /// @notice Approves the given address to transfer the WETH on behalf of the caller.
        /// @param guy The address that is approved to transfer the WETH.
        /// @param wad The amount that is approved to transfer.
        /// @return True if the approval was successful.
        function approve(address guy, uint256 wad) external returns (bool);
        /// @notice Transfers the given amount of WETH to the given address.
        /// @param dst The address to transfer the WETH to.
        /// @param wad The amount of WETH to transfer.
        /// @return True if the transfer was successful.
        function transfer(address dst, uint256 wad) external returns (bool);
        /// @notice Transfers the given amount of WETH from the given address to the given address.
        /// @param src The address to transfer the WETH from.
        /// @param dst The address to transfer the WETH to.
        /// @param wad The amount of WETH to transfer.
        /// @return True if the transfer was successful.
        function transferFrom(address src, address dst, uint256 wad) external returns (bool);
    }
    // SPDX-License-Identifier: GPL-3.0
    // Copyright (C) 2015, 2016, 2017 Dapphub
    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    // You should have received a copy of the GNU General Public License
    // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    // Based on WETH9 by Dapphub.
    // Modified by OP Labs.
    pragma solidity 0.8.15;
    import { IWETH } from "src/dispute/interfaces/IWETH.sol";
    /// @title WETH98
    /// @notice WETH98 is a version of WETH9 upgraded for Solidity 0.8.x.
    contract WETH98 is IWETH {
        uint8 public constant decimals = 18;
        mapping(address => uint256) public balanceOf;
        mapping(address => mapping(address => uint256)) public allowance;
        /// @notice Pipes to deposit.
        receive() external payable {
            deposit();
        }
        /// @notice Pipes to deposit.
        fallback() external payable {
            deposit();
        }
        /// @inheritdoc IWETH
        function name() external view virtual override returns (string memory) {
            return "Wrapped Ether";
        }
        /// @inheritdoc IWETH
        function symbol() external view virtual override returns (string memory) {
            return "WETH";
        }
        /// @inheritdoc IWETH
        function deposit() public payable {
            balanceOf[msg.sender] += msg.value;
            emit Deposit(msg.sender, msg.value);
        }
        /// @inheritdoc IWETH
        function withdraw(uint256 wad) public virtual {
            require(balanceOf[msg.sender] >= wad);
            balanceOf[msg.sender] -= wad;
            payable(msg.sender).transfer(wad);
            emit Withdrawal(msg.sender, wad);
        }
        /// @inheritdoc IWETH
        function totalSupply() external view returns (uint256) {
            return address(this).balance;
        }
        /// @inheritdoc IWETH
        function approve(address guy, uint256 wad) external returns (bool) {
            allowance[msg.sender][guy] = wad;
            emit Approval(msg.sender, guy, wad);
            return true;
        }
        /// @inheritdoc IWETH
        function transfer(address dst, uint256 wad) external returns (bool) {
            return transferFrom(msg.sender, dst, wad);
        }
        /// @inheritdoc IWETH
        function transferFrom(address src, address dst, uint256 wad) public returns (bool) {
            require(balanceOf[src] >= wad);
            if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {
                require(allowance[src][msg.sender] >= wad);
                allowance[src][msg.sender] -= wad;
            }
            balanceOf[src] -= wad;
            balanceOf[dst] += wad;
            emit Transfer(src, dst, wad);
            return true;
        }
    }
    // SPDX-License-Identifier: MIT
    pragma solidity 0.8.15;
    import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
    import { ISemver } from "src/universal/ISemver.sol";
    import { Storage } from "src/libraries/Storage.sol";
    /// @custom:audit none This contracts is not yet audited.
    /// @title SuperchainConfig
    /// @notice The SuperchainConfig contract is used to manage configuration of global superchain values.
    contract SuperchainConfig is Initializable, ISemver {
        /// @notice Enum representing different types of updates.
        /// @custom:value GUARDIAN            Represents an update to the guardian.
        enum UpdateType {
            GUARDIAN
        }
        /// @notice Whether or not the Superchain is paused.
        bytes32 public constant PAUSED_SLOT = bytes32(uint256(keccak256("superchainConfig.paused")) - 1);
        /// @notice The address of the guardian, which can pause withdrawals from the System.
        ///         It can only be modified by an upgrade.
        bytes32 public constant GUARDIAN_SLOT = bytes32(uint256(keccak256("superchainConfig.guardian")) - 1);
        /// @notice Emitted when the pause is triggered.
        /// @param identifier A string helping to identify provenance of the pause transaction.
        event Paused(string identifier);
        /// @notice Emitted when the pause is lifted.
        event Unpaused();
        /// @notice Emitted when configuration is updated.
        /// @param updateType Type of update.
        /// @param data       Encoded update data.
        event ConfigUpdate(UpdateType indexed updateType, bytes data);
        /// @notice Semantic version.
        /// @custom:semver 1.1.0
        string public constant version = "1.1.0";
        /// @notice Constructs the SuperchainConfig contract.
        constructor() {
            initialize({ _guardian: address(0), _paused: false });
        }
        /// @notice Initializer.
        /// @param _guardian    Address of the guardian, can pause the OptimismPortal.
        /// @param _paused      Initial paused status.
        function initialize(address _guardian, bool _paused) public initializer {
            _setGuardian(_guardian);
            if (_paused) {
                _pause("Initializer paused");
            }
        }
        /// @notice Getter for the guardian address.
        function guardian() public view returns (address guardian_) {
            guardian_ = Storage.getAddress(GUARDIAN_SLOT);
        }
        /// @notice Getter for the current paused status.
        function paused() public view returns (bool paused_) {
            paused_ = Storage.getBool(PAUSED_SLOT);
        }
        /// @notice Pauses withdrawals.
        /// @param _identifier (Optional) A string to identify provenance of the pause transaction.
        function pause(string memory _identifier) external {
            require(msg.sender == guardian(), "SuperchainConfig: only guardian can pause");
            _pause(_identifier);
        }
        /// @notice Pauses withdrawals.
        /// @param _identifier (Optional) A string to identify provenance of the pause transaction.
        function _pause(string memory _identifier) internal {
            Storage.setBool(PAUSED_SLOT, true);
            emit Paused(_identifier);
        }
        /// @notice Unpauses withdrawals.
        function unpause() external {
            require(msg.sender == guardian(), "SuperchainConfig: only guardian can unpause");
            Storage.setBool(PAUSED_SLOT, false);
            emit Unpaused();
        }
        /// @notice Sets the guardian address. This is only callable during initialization, so an upgrade
        ///         will be required to change the guardian.
        /// @param _guardian The new guardian address.
        function _setGuardian(address _guardian) internal {
            Storage.setAddress(GUARDIAN_SLOT, _guardian);
            emit ConfigUpdate(UpdateType.GUARDIAN, abi.encode(_guardian));
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
    pragma solidity ^0.8.0;
    import "../proxy/utils/Initializable.sol";
    /**
     * @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 ContextUpgradeable is Initializable {
        function __Context_init() internal onlyInitializing {
        }
        function __Context_init_unchained() internal onlyInitializing {
        }
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
        /**
         * @dev This empty reserved space is put in place to allow future versions to add new
         * variables without shifting down storage in the inheritance chain.
         * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
         */
        uint256[50] private __gap;
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
    pragma solidity ^0.8.2;
    import "../../utils/AddressUpgradeable.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]
     * ```
     * 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. Equivalent to `reinitializer(1)`.
         */
        modifier initializer() {
            bool isTopLevelCall = !_initializing;
            require(
                (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.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.
         *
         * `initializer` is equivalent to `reinitializer(1)`, so 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.
         *
         * 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.
         */
        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.
         */
        function _disableInitializers() internal virtual {
            require(!_initializing, "Initializable: contract is initializing");
            if (_initialized < type(uint8).max) {
                _initialized = type(uint8).max;
                emit Initialized(type(uint8).max);
            }
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.7.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]
     * ```
     * 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. Equivalent to `reinitializer(1)`.
         */
        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.
         *
         * `initializer` is equivalent to `reinitializer(1)`, so 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.
         *
         * 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.
         */
        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.
         */
        function _disableInitializers() internal virtual {
            require(!_initializing, "Initializable: contract is initializing");
            if (_initialized < type(uint8).max) {
                _initialized = type(uint8).max;
                emit Initialized(type(uint8).max);
            }
        }
    }
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    /// @title Storage
    /// @notice Storage handles reading and writing to arbitary storage locations
    library Storage {
        /// @notice Returns an address stored in an arbitrary storage slot.
        ///         These storage slots decouple the storage layout from
        ///         solc's automation.
        /// @param _slot The storage slot to retrieve the address from.
        function getAddress(bytes32 _slot) internal view returns (address addr_) {
            assembly {
                addr_ := sload(_slot)
            }
        }
        /// @notice Stores an address in an arbitrary storage slot, `_slot`.
        /// @param _slot The storage slot to store the address in.
        /// @param _address The protocol version to store
        /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses
        ///      in arbitrary storage slots.
        function setAddress(bytes32 _slot, address _address) internal {
            assembly {
                sstore(_slot, _address)
            }
        }
        /// @notice Returns a uint256 stored in an arbitrary storage slot.
        ///         These storage slots decouple the storage layout from
        ///         solc's automation.
        /// @param _slot The storage slot to retrieve the address from.
        function getUint(bytes32 _slot) internal view returns (uint256 value_) {
            assembly {
                value_ := sload(_slot)
            }
        }
        /// @notice Stores a value in an arbitrary storage slot, `_slot`.
        /// @param _slot The storage slot to store the address in.
        /// @param _value The protocol version to store
        /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values
        ///      in arbitrary storage slots.
        function setUint(bytes32 _slot, uint256 _value) internal {
            assembly {
                sstore(_slot, _value)
            }
        }
        /// @notice Returns a bytes32 stored in an arbitrary storage slot.
        ///         These storage slots decouple the storage layout from
        ///         solc's automation.
        /// @param _slot The storage slot to retrieve the address from.
        function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) {
            assembly {
                value_ := sload(_slot)
            }
        }
        /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`.
        /// @param _slot The storage slot to store the address in.
        /// @param _value The bytes32 value to store.
        /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values
        ///      in arbitrary storage slots.
        function setBytes32(bytes32 _slot, bytes32 _value) internal {
            assembly {
                sstore(_slot, _value)
            }
        }
        /// @notice Stores a bool value in an arbitrary storage slot, `_slot`.
        /// @param _slot The storage slot to store the bool in.
        /// @param _value The bool value to store
        /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values
        ///      in arbitrary storage slots.
        function setBool(bytes32 _slot, bool _value) internal {
            assembly {
                sstore(_slot, _value)
            }
        }
        /// @notice Returns a bool stored in an arbitrary storage slot.
        /// @param _slot The storage slot to retrieve the bool from.
        function getBool(bytes32 _slot) internal view returns (bool value_) {
            assembly {
                value_ := sload(_slot)
            }
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
    pragma solidity ^0.8.1;
    /**
     * @dev Collection of functions related to the address type
     */
    library AddressUpgradeable {
        /**
         * @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
         * ====
         *
         * [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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, "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");
            require(isContract(target), "Address: call to non-contract");
            (bool success, bytes memory returndata) = target.call{value: value}(data);
            return verifyCallResult(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) {
            require(isContract(target), "Address: static call to non-contract");
            (bool success, bytes memory returndata) = target.staticcall(data);
            return verifyCallResult(success, returndata, errorMessage);
        }
        /**
         * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
         * revert reason 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 {
                // 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 (last updated v4.7.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
         * ====
         *
         * [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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, "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");
            require(isContract(target), "Address: call to non-contract");
            (bool success, bytes memory returndata) = target.call{value: value}(data);
            return verifyCallResult(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) {
            require(isContract(target), "Address: static call to non-contract");
            (bool success, bytes memory returndata) = target.staticcall(data);
            return verifyCallResult(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) {
            require(isContract(target), "Address: delegate call to non-contract");
            (bool success, bytes memory returndata) = target.delegatecall(data);
            return verifyCallResult(success, returndata, errorMessage);
        }
        /**
         * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
         * revert reason 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 {
                // 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);
                }
            }
        }
    }