ETH Price: $2,526.44 (+0.40%)

Transaction Decoder

Block:
19861572 at May-13-2024 02:04:23 PM +UTC
Transaction Fee:
0.009980390631954288 ETH $25.21
Gas Used:
609,154 Gas / 16.384018872 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x2b3F2015...024F30420
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 5565295238860406290745115627146948458364692159430472364222897915572798496379163594789282723910690546833997201996251825190931485216442666189769364195074095234979653831058916743493280037938959256662066436942286414303031654090897497187241181475187834420195739618605744310153884719770841643960723490696988369020372824740587341840412894613024680644431023523428622975474537457864988812475454406201234869729740196724549621334340659981217093995869966210309674698127772143265689583140252914299038919577068169000518606693832864146726303548898304694710524400094968186707952820741161914326081736815459135670623976703328278977353501215648382762815401747295960470323771047961473322340854976551511200006299392660609662060266405766925099268866327974469706541981566248186568961557545380279158318640333903491717484776104009588976912327258210189568777103761027944068346848755436550588801123952732790115255838017378022076755310214601598626641149953216454101662065336384579527131517646221893324999349280495124441309859071096634301329144175663096708864015770353258221740797293414083901407204128203921989759987062542755750171239620695573329637867524232562276459392806013122858710593677587429908897803495320309735629107117767026499458675815989955319197868293200970047729081591147335131278182352370104758120600730954081371256377428822411350979820588678468858015111716416279889633065468242720535829982901665738141568220415235563866638006638499456228833135348151231244447612381895679163124301298522215911117602558004997500220579392700720215031172967179709129374436554529075914754021423996192360261906268353341808196507618825519809113193929916020640796793164451926201197326440714334147542499895719987576148428966765232711178993163290605802535438724221812841139958023309998658139356572662215120021467495020556751254767221747013757539670431914914216998061398604811747421916849884945517601741473592913285115898380541003154243686951423342932605832464952195601014636791833288846206206864639922362518733706302908101256789585660211531828403297322032906493887802756375613023906867521664807677303325413789612266375951751348591598184947492553030585749296488605897484219180442056438982522713562569382687734328767647977874718824078259263086547509868592069743111567502065067062499153192870575151294879983955824506914462582738295480852699927564943724493823460858329292686445126883560343812497145678502971103495287907322201980368777383107020699265142186984015533724433996890355587197988965521430322248087199079203513919181778262219810709382831269299044245445752135798880057498805748326386390144648866027799890417046282644214227411521161655730829302785025327098406451185338414971658084864455982126415500651130583328196832800109371402916192194741205523340735408306607358216084238216170600828387391689979133470676542091222335111773680283051016122266767911372100613030178116735482397625912106429989557131916840436325864717019050402904475810653442847042674312924758175337210673236251626036440124688895436354339055394251581873809925308611882315821953043850652178605438633013762643032033543079086716543916213138377872262381022698781783138306997644000401036253554988226038550284117310614374382658451943482481288635023694207084780289149953021519075664188045610165798401835378274521189415737575952791728276688412664769332468507325383806105583940314934101569826574052533360677884482266127172873925284654588880754581196271562751211338123048453365405680925382285842876125151628170132228536231021319024911243367013967456906603487866732665265543691265189519165466921091770320074211140299146824200771579533899351429867682806568730535884977721230968620864336182826468936215085655662729833901642802005337040895586452616851595954660495808646032038016139249849436693781521061869339650254414131413383665239220228212366324564535250551520688767035104227512679613824625152045502428371685729267772194220403107276079358006457662886391324939819894769770176579575542170936745472093280824039636883398766326546890416477962326732389813449212698893655158571370562283165943038957952873001421373516729225864008698460599658640354831996684134366562085731806300441196309419782508066140995574652063701601847063827223997479466027486723206450991730204145795045587140220278476804141452906505634581385853916267028477933236521627564253371630313452455631306999538382603414954316631573824845836270797664189075613066851157052638959013123587377272622949006766344248734813783798356947587826563684804409028118273190089813212794930728553033872549797791166814067964069760635709737930055360656063370152053806438790611840125010113621802132004460474804514207750768596133010585761450955673007405394943570347125723357420913860293165685721289748082532236172606043140806939166437006062688860918199334502535457435942030722741186324400046110684526492937528056729956112366074339763197322159093189462211839820387631439291273129900921822148184425262812072308241887881572994617509323703283480227551479845003151056701874624108106709054415065989340926070827379162010439470123038769627737520390777341660439615288161014937387235159573655613261935756100194974516005596027546617624733492609102965207363737612948528366403551896021869052128497332483441264857575792218967198910473989952221272155764013063367462473288493238901009941326362404092180368597392784418858556957582843452777613920190076266920597273097824852110150301938122618312105447233866403889067201227642738869657102228051713737300891693860985368542517231155564676903826219094806710257216398954700347974551840512119056286730105759501904742610480511446555457390611904941971704540318566969150789525363448967784772440766244931046007329504249810849860530147705121602822488110103604498363158124863954748508152653069085075742772688954744482376197743121368543539924657893066069654503950090136209402612443456340977951768001960412415493077746510188518527066401021314202580507636760460926296687885338261179139518299590560399042815860919645376058550959170283726670564854985252640438247771367664678134772423118558265354
(beaverbuild)
21.749160420973860908 Eth21.749181771680846334 Eth0.000021350706985426
0xD23d1DAF...5d89DC914
1.942546963838482328 Eth
Nonce: 6
1.93256657320652804 Eth
Nonce: 7
0.009980390631954288

Execution Trace

L1ChugSplashProxy.60806040( )
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/**
 * @title IL1ChugSplashDeployer
 */
interface IL1ChugSplashDeployer {
    function isUpgrading() external view returns (bool);
}
/**
 * @custom:legacy
 * @title L1ChugSplashProxy
 * @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added
 *         functions `setCode` and `setStorage` for changing the code or storage of the contract.
 *
 *         Note for future developers: do NOT make anything in this contract 'public' unless you
 *         know what you're doing. Anything public can potentially have a function signature that
 *         conflicts with a signature attached to the implementation contract. Public functions
 *         SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good
 *         reason not to have that modifier. And there almost certainly is not a good reason to not
 *         have that modifier. Beware!
 */
contract L1ChugSplashProxy {
    /**
     * @notice "Magic" prefix. When prepended to some arbitrary bytecode and used to create a
     *         contract, the appended bytecode will be deployed as given.
     */
    bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;
    /**
     * @notice bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
     */
    bytes32 internal constant IMPLEMENTATION_KEY =
        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    /**
     * @notice bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
     */
    bytes32 internal constant OWNER_KEY =
        0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    /**
     * @notice Blocks a function from being called when the parent signals that the system should
     *         be paused via an isUpgrading function.
     */
    modifier onlyWhenNotPaused() {
        address owner = _getOwner();
        // We do a low-level call because there's no guarantee that the owner actually *is* an
        // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and
        // it turns out that it isn't the right type of contract.
        (bool success, bytes memory returndata) = owner.staticcall(
            abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)
        );
        // If the call was unsuccessful then we assume that there's no "isUpgrading" method and we
        // can just continue as normal. We also expect that the return value is exactly 32 bytes
        // long. If this isn't the case then we can safely ignore the result.
        if (success && returndata.length == 32) {
            // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the
            // case that the isUpgrading function returned something other than 0 or 1. But we only
            // really care about the case where this value is 0 (= false).
            uint256 ret = abi.decode(returndata, (uint256));
            require(ret == 0, "L1ChugSplashProxy: system is currently being upgraded");
        }
        _;
    }
    /**
     * @notice Makes a proxy call instead of triggering the given function when the caller is
     *         either the owner or the zero address. Caller can only ever be the zero address if
     *         this function is being called off-chain via eth_call, which is totally fine and can
     *         be convenient for client-side tooling. Avoids situations where the proxy and
     *         implementation share a sighash and the proxy function ends up being called instead
     *         of the implementation one.
     *
     *         Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If
     *         there's a way for someone to send a transaction with msg.sender == address(0) in any
     *         real context then we have much bigger problems. Primary reason to include this
     *         additional allowed sender is because the owner address can be changed dynamically
     *         and we do not want clients to have to keep track of the current owner in order to
     *         make an eth_call that doesn't trigger the proxied contract.
     */
    // slither-disable-next-line incorrect-modifier
    modifier proxyCallIfNotOwner() {
        if (msg.sender == _getOwner() || msg.sender == address(0)) {
            _;
        } else {
            // This WILL halt the call frame on completion.
            _doProxyCall();
        }
    }
    /**
     * @param _owner Address of the initial contract owner.
     */
    constructor(address _owner) {
        _setOwner(_owner);
    }
    // slither-disable-next-line locked-ether
    receive() external payable {
        // Proxy call by default.
        _doProxyCall();
    }
    // slither-disable-next-line locked-ether
    fallback() external payable {
        // Proxy call by default.
        _doProxyCall();
    }
    /**
     * @notice Sets the code that should be running behind this proxy.
     *
     *         Note: This scheme is a bit different from the standard proxy scheme where one would
     *         typically deploy the code separately and then set the implementation address. We're
     *         doing it this way because it gives us a lot more freedom on the client side. Can
     *         only be triggered by the contract owner.
     *
     * @param _code New contract code to run inside this contract.
     */
    function setCode(bytes memory _code) external proxyCallIfNotOwner {
        // Get the code hash of the current implementation.
        address implementation = _getImplementation();
        // If the code hash matches the new implementation then we return early.
        if (keccak256(_code) == _getAccountCodeHash(implementation)) {
            return;
        }
        // Create the deploycode by appending the magic prefix.
        bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);
        // Deploy the code and set the new implementation address.
        address newImplementation;
        assembly {
            newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))
        }
        // Check that the code was actually deployed correctly. I'm not sure if you can ever
        // actually fail this check. Should only happen if the contract creation from above runs
        // out of gas but this parent execution thread does NOT run out of gas. Seems like we
        // should be doing this check anyway though.
        require(
            _getAccountCodeHash(newImplementation) == keccak256(_code),
            "L1ChugSplashProxy: code was not correctly deployed"
        );
        _setImplementation(newImplementation);
    }
    /**
     * @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to
     *         perform upgrades in a more transparent way. Only callable by the owner.
     *
     * @param _key   Storage key to modify.
     * @param _value New value for the storage key.
     */
    function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner {
        assembly {
            sstore(_key, _value)
        }
    }
    /**
     * @notice Changes the owner of the proxy contract. Only callable by the owner.
     *
     * @param _owner New owner of the proxy contract.
     */
    function setOwner(address _owner) external proxyCallIfNotOwner {
        _setOwner(_owner);
    }
    /**
     * @notice Queries the owner of the proxy contract. Can only be called by the owner OR by
     *         making an eth_call and setting the "from" address to address(0).
     *
     * @return Owner address.
     */
    function getOwner() external proxyCallIfNotOwner returns (address) {
        return _getOwner();
    }
    /**
     * @notice Queries the implementation address. Can only be called by the owner OR by making an
     *         eth_call and setting the "from" address to address(0).
     *
     * @return Implementation address.
     */
    function getImplementation() external proxyCallIfNotOwner returns (address) {
        return _getImplementation();
    }
    /**
     * @notice Sets the implementation address.
     *
     * @param _implementation New implementation address.
     */
    function _setImplementation(address _implementation) internal {
        assembly {
            sstore(IMPLEMENTATION_KEY, _implementation)
        }
    }
    /**
     * @notice Changes the owner of the proxy contract.
     *
     * @param _owner New owner of the proxy contract.
     */
    function _setOwner(address _owner) internal {
        assembly {
            sstore(OWNER_KEY, _owner)
        }
    }
    /**
     * @notice Performs the proxy call via a delegatecall.
     */
    function _doProxyCall() internal onlyWhenNotPaused {
        address implementation = _getImplementation();
        require(implementation != address(0), "L1ChugSplashProxy: implementation is not set yet");
        assembly {
            // Copy calldata into memory at 0x0....calldatasize.
            calldatacopy(0x0, 0x0, calldatasize())
            // Perform the delegatecall, make sure to pass all available gas.
            let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)
            // Copy returndata into memory at 0x0....returndatasize. Note that this *will*
            // overwrite the calldata that we just copied into memory but that doesn't really
            // matter because we'll be returning in a second anyway.
            returndatacopy(0x0, 0x0, returndatasize())
            // Success == 0 means a revert. We'll revert too and pass the data up.
            if iszero(success) {
                revert(0x0, returndatasize())
            }
            // Otherwise we'll just return and pass the data up.
            return(0x0, returndatasize())
        }
    }
    /**
     * @notice Queries the implementation address.
     *
     * @return Implementation address.
     */
    function _getImplementation() internal view returns (address) {
        address implementation;
        assembly {
            implementation := sload(IMPLEMENTATION_KEY)
        }
        return implementation;
    }
    /**
     * @notice Queries the owner of the proxy contract.
     *
     * @return Owner address.
     */
    function _getOwner() internal view returns (address) {
        address owner;
        assembly {
            owner := sload(OWNER_KEY)
        }
        return owner;
    }
    /**
     * @notice Gets the code hash for a given account.
     *
     * @param _account Address of the account to get a code hash for.
     *
     * @return Code hash for the account.
     */
    function _getAccountCodeHash(address _account) internal view returns (bytes32) {
        bytes32 codeHash;
        assembly {
            codeHash := extcodehash(_account)
        }
        return codeHash;
    }
}