ETH Price: $1,981.62 (-3.28%)

Transaction Decoder

Block:
13447378 at Oct-19-2021 09:26:23 AM +UTC
Transaction Fee:
0.002599490354221202 ETH $5.15
Gas Used:
51,974 Gas / 50.015206723 Gwei

Account State Difference:

  Address   Before After State Difference Code
(F2Pool Old)
3,583.084973975863518561 Eth3,583.085084257556839685 Eth0.000110281693321124
0xEe6103Ae...16565A3A6
0.053159363520875229 Eth
Nonce: 4
0.050559873166654027 Eth
Nonce: 5
0.002599490354221202

Execution Trace

TransparentUpgradeableProxy.CALL( )
  • 0x0386871c51bb0dfbd0a10088444c91fd37d12e15.DELEGATECALL( )
    pragma solidity ^0.6.12;
    
    /**
     * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
     * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
     * be specified by overriding the virtual {_implementation} function.
     * 
     * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
     * different contract through the {_delegate} function.
     * 
     * The success and return data of the delegated call will be returned back to the caller of the proxy.
     */
    abstract contract Proxy {
        /**
         * @dev Delegates the current call to `implementation`.
         * 
         * This function does not return to its internall call site, it will return directly to the external caller.
         */
        function _delegate(address implementation) internal {
            // solhint-disable-next-line no-inline-assembly
            assembly {
                // Copy msg.data. We take full control of memory in this inline assembly
                // block because it will not return to Solidity code. We overwrite the
                // Solidity scratch pad at memory position 0.
                calldatacopy(0, 0, calldatasize())
    
                // Call the implementation.
                // out and outsize are 0 because we don't know the size yet.
                let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
    
                // Copy the returned data.
                returndatacopy(0, 0, returndatasize())
    
                switch result
                // delegatecall returns 0 on error.
                case 0 { revert(0, returndatasize()) }
                default { return(0, returndatasize()) }
            }
        }
    
        /**
         * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
         * and {_fallback} should delegate.
         */
        function _implementation() internal virtual view returns (address);
    
        /**
         * @dev Delegates the current call to the address returned by `_implementation()`.
         * 
         * This function does not return to its internall call site, it will return directly to the external caller.
         */
        function _fallback() internal {
            _delegate(_implementation());
        }
    
        /**
         * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
         * function in the contract matches the call data.
         */
        fallback () payable external {
            _delegate(_implementation());
        }
    
        /**
         * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
         * is empty.
         */
        receive () payable external {
            _delegate(_implementation());
        }
    }
    
    /**
     * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
     * implementation address that can be changed. This address is stored in storage in the location specified by
     * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
     * implementation behind the proxy.
     * 
     * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see
     * {TransparentUpgradeableProxy}.
     */
    contract UpgradeableProxy is Proxy {
        /**
         * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
         * 
         * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
         * function call, and allows initializating the storage of the proxy like a Solidity constructor.
         */
        constructor() public payable {
            assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
        }
    
        /**
         * @dev Emitted when the implementation is upgraded.
         */
        event Upgraded(address indexed implementation);
    
        /**
         * @dev Storage slot with the address of the current implementation.
         * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
         * validated in the constructor.
         */
        bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    
        /**
         * @dev Returns the current implementation address.
         */
        function _implementation() internal override view returns (address impl) {
            bytes32 slot = _IMPLEMENTATION_SLOT;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                impl := sload(slot)
            }
        }
    
        /**
         * @dev Upgrades the proxy to a new implementation.
         * 
         * Emits an {Upgraded} event.
         */
        function _upgradeTo(address newImplementation) virtual internal {
            _setImplementation(newImplementation);
            emit Upgraded(newImplementation);
        }
    
        /**
         * @dev Stores a new address in the EIP1967 implementation slot.
         */
        function _setImplementation(address newImplementation) private {
            address implementation = _implementation();
            require(implementation != newImplementation, "Proxy: Attemps update proxy with the same implementation");
    
            bytes32 slot = _IMPLEMENTATION_SLOT;
    
            // solhint-disable-next-line no-inline-assembly
            assembly {
                sstore(slot, newImplementation)
            }
        }
    }
    
    /**
     * @dev This contract implements a proxy that is upgradeable by an admin.
     * 
     * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
     * clashing], which can potentially be used in an attack, this contract uses the
     * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
     * things that go hand in hand:
     * 
     * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
     * that call matches one of the admin functions exposed by the proxy itself.
     * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
     * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
     * "admin cannot fallback to proxy target".
     * 
     * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
     * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
     * to sudden errors when trying to call a function from the proxy implementation.
     * 
     * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
     * you should think of the `ProxyAdmin` instance as the real administrative inerface of your proxy.
     */
    contract TransparentUpgradeableProxy is UpgradeableProxy {
        /**
         * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
         * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.
         */
        constructor(address admin, address implementation) public payable UpgradeableProxy() {
            require(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1), "Wrong admin slot");
            _setAdmin(admin);
            _upgradeTo(implementation);
        }
    
        /**
         * @dev Emitted when the admin account has changed.
         */
        event AdminChanged(address previousAdmin, address newAdmin);
    
        /**
         * @dev Storage slot with the admin of the contract.
         * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
         * validated in the constructor.
         */
        bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    
        /**
         * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
         */
        modifier ifAdmin() {
            if (msg.sender == _admin()) {
                _;
            } else {
                _fallback();
            }
        }
    
        /**
         * @dev Returns the current admin.
         * 
         * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
         * 
         * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
         * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
         * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
         */
        function admin() external ifAdmin returns (address) {
            return _admin();
        }
    
        /**
         * @dev Returns the current implementation.
         * 
         * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
         * 
         * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
         * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
         * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
         */
        function implementation() external ifAdmin returns (address) {
            return _implementation();
        }
    
        /**
         * @dev Changes the admin of the proxy.
         * 
         * Emits an {AdminChanged} event.
         * 
         * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
         */
        function changeAdmin(address newAdmin) external ifAdmin {
            require(newAdmin != _admin(), "Proxy: new admin is the same admin.");
            emit AdminChanged(_admin(), newAdmin);
            _setAdmin(newAdmin);
        }
    
        /**
         * @dev Upgrade the implementation of the proxy.
         * 
         * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
         */
        function upgradeTo(address newImplementation) external ifAdmin {
            _upgradeTo(newImplementation);
        }
    
        /**
         * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
         * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
         * proxied contract.
         * 
         * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
         */
        function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
            _upgradeTo(newImplementation);
            // solhint-disable-next-line avoid-low-level-calls
            (bool success,) = newImplementation.delegatecall(data);
            require(success);
        }
    
        /**
         * @dev Returns the current admin.
         */
        function _admin() internal view returns (address adm) {
            bytes32 slot = _ADMIN_SLOT;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                adm := sload(slot)
            }
        }
    
        /**
         * @dev Stores a new address in the EIP1967 admin slot.
         */
        function _setAdmin(address newAdmin) private {
            bytes32 slot = _ADMIN_SLOT;
            require(newAdmin != address(0), "Proxy: Can't set admin to zero address.");
    
            // solhint-disable-next-line no-inline-assembly
            assembly {
                sstore(slot, newAdmin)
            }
        }
    }