ETH Price: $2,077.00 (-1.12%)

Transaction Decoder

Block:
22196978 at Apr-04-2025 05:14:11 PM +UTC
Transaction Fee:
0.00003383082218797 ETH $0.07
Gas Used:
47,185 Gas / 0.716982562 Gwei

Account State Difference:

  Address   Before After State Difference Code
(beaverbuild)
16.301537775626826106 Eth16.301540234118866096 Eth0.00000245849203999
0xe4468D6f...979A32558
0.0002 Eth
Nonce: 0
0.00016616917781203 Eth
Nonce: 1
0.00003383082218797

Execution Trace

ETH 0.000051094193 Multicaller.66e0daa0( )
  • ETH 0.000051094193 Multicaller.aggregate( targets=[0x49048044D57e1C92A77f79988d21Fa8fAF74E97e], data=[6eBcQgAAAAAAAAAAAAAAAORGjW8J5qTtjbBt9mRa7Il5oyVYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0FHeqYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGGoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==], values=[198000000000000], refundTo=0x0000000000000000000000000000000000000001 )
    • ETH 0.000198 Proxy.e9e05c42( )
      File 1 of 2: Multicaller
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.4;
      /**
       * @title Multicaller
       * @author vectorized.eth
       * @notice Contract that allows for efficient aggregation
       *         of multiple calls in a single transaction.
       */
      contract Multicaller {
          // =============================================================
          //                            ERRORS
          // =============================================================
          /**
           * @dev The lengths of the input arrays are not the same.
           */
          error ArrayLengthsMismatch();
          // =============================================================
          //                    AGGREGATION OPERATIONS
          // =============================================================
          /**
           * @dev Aggregates multiple calls in a single transaction.
           * @param targets  An array of addresses to call.
           * @param data     An array of calldata to forward to the targets.
           * @param values   How much ETH to forward to each target.
           * @param refundTo The address to transfer any remaining ETH in the contract after the calls.
           *                 If `address(0)`, remaining ETH will NOT be refunded.
           *                 If `address(1)`, remaining ETH will be refunded to `msg.sender`.
           *                 If anything else, remaining ETH will be refunded to `refundTo`.
           * @return An array of the returndata from each call.
           */
          function aggregate(
              address[] calldata targets,
              bytes[] calldata data,
              uint256[] calldata values,
              address refundTo
          ) external payable returns (bytes[] memory) {
              assembly {
                  if iszero(and(eq(targets.length, data.length), eq(data.length, values.length))) {
                      // Store the function selector of `ArrayLengthsMismatch()`.
                      mstore(returndatasize(), 0x3b800a46)
                      // Revert with (offset, size).
                      revert(0x1c, 0x04)
                  }
                  let resultsSize := 0x40
                  if data.length {
                      let results := 0x40
                      // Left shift by 5 is equivalent to multiplying by 0x20.
                      data.length := shl(5, data.length)
                      // Copy the offsets from calldata into memory.
                      calldatacopy(results, data.offset, data.length)
                      // Offset into `results`.
                      let resultsOffset := data.length
                      // Pointer to the end of `results`.
                      let end := add(results, data.length)
                      // For deriving the calldata offsets from the `results` pointer.
                      let valuesOffsetDiff := sub(values.offset, results)
                      let targetsOffsetDiff := sub(targets.offset, results)
                      for {} 1 {} {
                          // The offset of the current bytes in the calldata.
                          let o := add(data.offset, mload(results))
                          let memPtr := add(resultsOffset, 0x40)
                          // Copy the current bytes from calldata to the memory.
                          calldatacopy(
                              memPtr,
                              add(o, 0x20), // The offset of the current bytes' bytes.
                              calldataload(o) // The length of the current bytes.
                          )
                          if iszero(
                              call(
                                  gas(), // Remaining gas.
                                  calldataload(add(targetsOffsetDiff, results)), // Address to call.
                                  calldataload(add(valuesOffsetDiff, results)), // ETH to send.
                                  memPtr, // Start of input calldata in memory.
                                  calldataload(o), // Size of input calldata.
                                  0x00, // We will use returndatacopy instead.
                                  0x00 // We will use returndatacopy instead.
                              )
                          ) {
                              // Bubble up the revert if the call reverts.
                              returndatacopy(0x00, 0x00, returndatasize())
                              revert(0x00, returndatasize())
                          }
                          // Append the current `resultsOffset` into `results`.
                          mstore(results, resultsOffset)
                          // Append the returndatasize, and the returndata.
                          mstore(memPtr, returndatasize())
                          returndatacopy(add(memPtr, 0x20), 0x00, returndatasize())
                          // Advance the `resultsOffset` by `returndatasize() + 0x20`,
                          // rounded up to the next multiple of 0x20.
                          resultsOffset := and(add(add(resultsOffset, returndatasize()), 0x3f), not(0x1f))
                          // Advance the `results` pointer.
                          results := add(results, 0x20)
                          if eq(results, end) { break }
                      }
                      resultsSize := add(resultsOffset, 0x40)
                  }
                  if refundTo {
                      // Force transfers all the remaining ETH in the contract to `refundTo`,
                      // with a gas stipend of 100000, which should be enough for most use cases.
                      // If sending via a regular call fails, force sends the ETH by
                      // creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
                      if selfbalance() {
                          // If `refundTo` is `address(1)`, replace it with the `msg.sender`.
                          refundTo := xor(refundTo, mul(eq(refundTo, 1), xor(refundTo, caller())))
                          // Transfer the ETH and check if it succeeded or not.
                          if iszero(
                              call(100000, refundTo, selfbalance(), codesize(), 0x00, codesize(), 0x00)
                          ) {
                              mstore(0x00, refundTo) // Store the address in scratch space.
                              mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                              mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                              // We can directly use `SELFDESTRUCT` in the contract creation.
                              // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758
                              if iszero(create(selfbalance(), 0x0b, 0x16)) {
                                  // Coerce gas estimation to provide enough gas for the `create` above.
                                  revert(codesize(), codesize())
                              }
                          }
                      }
                  }
                  mstore(0x00, 0x20) // Store the memory offset of the `results`.
                  mstore(0x20, targets.length) // Store `targets.length` into `results`.
                  // Direct return.
                  return(0x00, resultsSize)
              }
          }
          /**
           * @dev For receiving ETH.
           *      Does nothing and returns nothing.
           *      Called instead of `fallback()` if the calldatasize is zero.
           */
          receive() external payable {}
          /**
           * @dev Decompresses the calldata and performs a delegatecall
           *      with the decompressed calldata to itself.
           *
           *      Accompanying JavaScript library to compress the calldata:
           *      https://github.com/vectorized/solady/blob/main/js/solady.js
           *      (See: `LibZip.cdCompress`)
           */
          fallback() external payable {
              assembly {
                  // If the calldata starts with the bitwise negation of
                  // `bytes4(keccak256("aggregate(address[],bytes[],uint256[],address)"))`.
                  let s := calldataload(returndatasize())
                  if eq(shr(224, s), 0x66e0daa0) {
                      mstore(returndatasize(), not(s))
                      let o := 4
                      for { let i := o } lt(i, calldatasize()) {} {
                          let c := byte(returndatasize(), calldataload(i))
                          i := add(i, 1)
                          if iszero(c) {
                              let d := byte(returndatasize(), calldataload(i))
                              i := add(i, 1)
                              // Fill with either 0xff or 0x00.
                              mstore(o, not(returndatasize()))
                              if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) }
                              o := add(o, add(and(d, 0x7f), 1))
                              continue
                          }
                          mstore8(o, c)
                          o := add(o, 1)
                      }
                      let success := delegatecall(gas(), address(), 0x00, o, 0x00, 0x00)
                      returndatacopy(0x00, 0x00, returndatasize())
                      if iszero(success) { revert(0x00, returndatasize()) }
                      return(0x00, returndatasize())
                  }
                  revert(returndatasize(), returndatasize())
              }
          }
      }
      

      File 2 of 2: Proxy
      // SPDX-License-Identifier: MIT
      pragma solidity 0.8.15;
      /**
       * @title Proxy
       * @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or
       *         if the caller is address(0), meaning that the call originated from an off-chain
       *         simulation.
       */
      contract Proxy {
          /**
           * @notice The storage slot that holds the address of the implementation.
           *         bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
           */
          bytes32 internal constant IMPLEMENTATION_KEY =
              0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
          /**
           * @notice The storage slot that holds the address of the owner.
           *         bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
           */
          bytes32 internal constant OWNER_KEY =
              0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
          /**
           * @notice An event that is emitted each time the implementation is changed. This event is part
           *         of the EIP-1967 specification.
           *
           * @param implementation The address of the implementation contract
           */
          event Upgraded(address indexed implementation);
          /**
           * @notice An event that is emitted each time the owner is upgraded. This event is part of the
           *         EIP-1967 specification.
           *
           * @param previousAdmin The previous owner of the contract
           * @param newAdmin      The new owner of the contract
           */
          event AdminChanged(address previousAdmin, address newAdmin);
          /**
           * @notice A modifier that reverts if not called by the owner or by address(0) to allow
           *         eth_call to interact with this proxy without needing to use low-level storage
           *         inspection. We assume that nobody is able to trigger calls from address(0) during
           *         normal EVM execution.
           */
          modifier proxyCallIfNotAdmin() {
              if (msg.sender == _getAdmin() || msg.sender == address(0)) {
                  _;
              } else {
                  // This WILL halt the call frame on completion.
                  _doProxyCall();
              }
          }
          /**
           * @notice Sets the initial admin during contract deployment. Admin address is stored at the
           *         EIP-1967 admin storage slot so that accidental storage collision with the
           *         implementation is not possible.
           *
           * @param _admin Address of the initial contract admin. Admin as the ability to access the
           *               transparent proxy interface.
           */
          constructor(address _admin) {
              _changeAdmin(_admin);
          }
          // 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 Set the implementation contract address. The code at the given address will execute
           *         when this contract is called.
           *
           * @param _implementation Address of the implementation contract.
           */
          function upgradeTo(address _implementation) public virtual proxyCallIfNotAdmin {
              _setImplementation(_implementation);
          }
          /**
           * @notice Set the implementation and call a function in a single transaction. Useful to ensure
           *         atomic execution of initialization-based upgrades.
           *
           * @param _implementation Address of the implementation contract.
           * @param _data           Calldata to delegatecall the new implementation with.
           */
          function upgradeToAndCall(address _implementation, bytes calldata _data)
              public
              payable
              virtual
              proxyCallIfNotAdmin
              returns (bytes memory)
          {
              _setImplementation(_implementation);
              (bool success, bytes memory returndata) = _implementation.delegatecall(_data);
              require(success, "Proxy: delegatecall to new implementation contract failed");
              return returndata;
          }
          /**
           * @notice Changes the owner of the proxy contract. Only callable by the owner.
           *
           * @param _admin New owner of the proxy contract.
           */
          function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
              _changeAdmin(_admin);
          }
          /**
           * @notice Gets the owner of the proxy contract.
           *
           * @return Owner address.
           */
          function admin() public virtual proxyCallIfNotAdmin returns (address) {
              return _getAdmin();
          }
          /**
           * @notice Queries the implementation address.
           *
           * @return Implementation address.
           */
          function implementation() public virtual proxyCallIfNotAdmin returns (address) {
              return _getImplementation();
          }
          /**
           * @notice Sets the implementation address.
           *
           * @param _implementation New implementation address.
           */
          function _setImplementation(address _implementation) internal {
              assembly {
                  sstore(IMPLEMENTATION_KEY, _implementation)
              }
              emit Upgraded(_implementation);
          }
          /**
           * @notice Changes the owner of the proxy contract.
           *
           * @param _admin New owner of the proxy contract.
           */
          function _changeAdmin(address _admin) internal {
              address previous = _getAdmin();
              assembly {
                  sstore(OWNER_KEY, _admin)
              }
              emit AdminChanged(previous, _admin);
          }
          /**
           * @notice Performs the proxy call via a delegatecall.
           */
          function _doProxyCall() internal {
              address impl = _getImplementation();
              require(impl != address(0), "Proxy: implementation not initialized");
              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(), impl, 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 impl;
              assembly {
                  impl := sload(IMPLEMENTATION_KEY)
              }
              return impl;
          }
          /**
           * @notice Queries the owner of the proxy contract.
           *
           * @return Owner address.
           */
          function _getAdmin() internal view returns (address) {
              address owner;
              assembly {
                  owner := sload(OWNER_KEY)
              }
              return owner;
          }
      }