ETH Price: $2,074.50 (-2.53%)

Transaction Decoder

Block:
16869301 at Mar-20-2023 01:52:11 PM +UTC
Transaction Fee:
0.01399955311313988 ETH $29.04
Gas Used:
560,505 Gas / 24.976678376 Gwei

Emitted Events:

119 0x7a5ce41c3511e4838f5dcefcf5533950ee1a8315.0x6e89d517057028190560dd200cf6bf792842861353d1173761dfa362e1c133f0( 0x6e89d517057028190560dd200cf6bf792842861353d1173761dfa362e1c133f0, 000000000000000000000000d0a7a69950f30de89906e79a713b97e9668433a6, 0000000000000000000000000000000000000000000000000186fb97ba37ac00, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000000 )
120 Forwarder.ForwarderDeposited( from=[Receiver] 0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43, value=110051870000000000, data=0x )

Account State Difference:

  Address   Before After State Difference Code
0x075F63f0...1357f6dE4 0.000345235968176511 Eth0.00167145125 Eth0.001326215281823489
0x14Ad241B...d9e798502 0.000145352359062143 Eth0.001706033 Eth0.001560680640937857
0x158B74D3...Ac24f27c7 0.000418916209391063 Eth0.001706033 Eth0.001287116790608937
0x16fb2850...f4Ca8494d 0.000331998736066038 Eth0.001706033 Eth0.001374034263933962
0x1fBE6A01...4b87c4f02 0 Eth0.05341972 Eth0.05341972
0x22d60D8C...0E7126f18 0.02102539 Eth0.04132561 Eth0.02030022
0x25734B96...cA99d657b 0.000229167256479 Eth0.009304427256479 Eth0.00907526
0x2c2E4C79...74d89D339 0.005458202672470252 Eth0.144994772672470252 Eth0.13953657
0x31a81780...8DcC6f30c 0.000857525701222347 Eth0.013553655701222347 Eth0.01269613
0x40BBbcFD...21521E7fe
(BingX Dep: 0x40BBbcFDfC6932600D9258fE6ff422821521E7fe)
0.062617296025753148 Eth0.070723156025753148 Eth0.00810586
0x464F939e...D605D9B2E 0.000374497220903207 Eth0.00167145125 Eth0.001296954029096793
0x46F2874a...6eF6f60D9 0.000308379185935621 Eth0.001706033 Eth0.001397653814064379
0x55eb6C70...99f14379C 0.16215529 Eth0.19595747 Eth0.03380218
0x5a10825F...B9c793dC2 0.000388449434450055 Eth0.00167188625 Eth0.001283436815549945
0x62b1eF13...b52F93e1c 0.000382334089710181 Eth0.001706033 Eth0.001323698910289819
0x6351B685...2CBfdf59C 0.000515996410539526 Eth0.057927176410539526 Eth0.05741118
0x647c1861...ae4167AAa 0.002701566886400068 Eth0.015152366886400068 Eth0.0124508
0x688B1495...B260f7838 0.01038681241759347 Eth0.01517146241759347 Eth0.00478465
0x692B8E87...95ef66d97 0.000106705858731583 Eth0.001706033 Eth0.001599327141268417
0x6a72d034...AC6C6CF24 0.006667748922319196 Eth0.011210838922319196 Eth0.00454309
0x6aDe09f6...62925C56C 0.00129627 Eth0.00695936 Eth0.00566309
0x6e928DCA...06f8FB5B8 0.000366877567963083 Eth0.001706033 Eth0.001339155432036917
0x70A8bE72...270f8be51 0.00026802402077449 Eth0.001706033 Eth0.00143800897922551
0x72F405ed...8271b4726 0.000364692171351451 Eth0.00167145125 Eth0.001306759078648549
0x73cEF42E...264197E8C 0 Eth0.01459923 Eth0.01459923
0x74047B07...e139357B9 0.002399725925838294 Eth0.152399725925838294 Eth0.15
0x7830c87C...31FA86F43
(Coinbase: Deposit)
20.153755963144451713 Eth
Nonce: 648020
20.139756410031311833 Eth
Nonce: 648021
0.01399955311313988
0x78AFC1D5...4D1b1e0a2 0.000436041067963083 Eth0.001706033 Eth0.001269991932036917
0x7a5ce41c...0eE1A8315 40.471579325790579012 Eth40.581631195790579012 Eth0.11005187
0x7Ef6E570...364B12602 0.003270729776726653 Eth0.023629839776726653 Eth0.02035911
0x85da7467...84D1b8dCE 0.006267034803084252 Eth0.012341594803084252 Eth0.00607456
0x867731e6...92D14909c 0.000278530991104551 Eth0.00167188625 Eth0.001393355258895449
0x8951A715...3D2005307 0.00041436722234356 Eth0.001706033 Eth0.00129166577765644
0x9954f7c2...917d3f108 0.000356168836317 Eth0.00188402125 Eth0.001527852413683
0x9b5AdEba...24A0FfF54 0.015464346642909796 Eth0.108457576642909796 Eth0.09299323
0xa138e6Dd...35E2bE582 0.000439503042692502 Eth0.001706033 Eth0.001266529957307498
0xa2D5572C...3547A78eF 0.000089027419467342 Eth0.026095757419467342 Eth0.02600673
0xa94D6AEC...2fc072d4a 0.000402441785965517 Eth0.00167188625 Eth0.001269444464034483
0xA9D1e08C...FB81d3E43
(Coinbase 10)
2,174.331659163498009147 Eth2,173.37262283030847138 Eth0.959036333189537767
0xB04D264A...4d09F3cf9 0.026836992956962528 Eth0.047765692956962528 Eth0.0209287
0xb7483F2e...dea7c1414 0.002949397539035904 Eth0.029335227539035904 Eth0.02638583
0xb79AD82A...9B1E7823E 0.14494686 Eth0.18197971 Eth0.03703285
0xb831579E...8E87eD605 0.0005004943 Eth0.0133327543 Eth0.01283226
0xd9545604...f884aF739 0.03011447 Eth0.06047711 Eth0.03036264
0xd9993E61...e94FcdCA0 0.000360223239859527 Eth0.00167145125 Eth0.001311228010140473
0xd9eD50a2...7F8c8DC81 0.000447715806366692 Eth0.001706033 Eth0.001258317193633308
(Flashbots: Builder)
1.173765338562209121 Eth1.174325843562209121 Eth0.000560505
0xe0B62209...7C18857B4 0.000328417221192017 Eth0.00167188625 Eth0.001343469028807983
0xE4761536...1058adF5c 0.03862283 Eth0.05410867 Eth0.01548584
0xeb930447...5E789E560 0.000350387364418715 Eth0.001705589 Eth0.001355201635581285
0xF0Bd783C...c300629a0 0.000225335546703442 Eth0.00167188625 Eth0.001446550703296558
0xFe79F3E2...ed9e6c928 0.000189851084575658 Eth0.00167188625 Eth0.001482035165424342
0xfF15C2b3...36a7FF063 0.000285835778444543 Eth0.00167188625 Eth0.001386050471555457

Execution Trace

Coinbase 10.1a1da075( )
  • ETH 0.001258317193633308 0xd9ed50a2b7401cf4cc2e06b7a85fa297f8c8dc81.CALL( )
  • ETH 0.001266529957307498 0xa138e6dd962a9086fa855c6e2b7b5aa35e2be582.CALL( )
  • ETH 0.001269444464034483 0xa94d6aec1f08625dfb8c0ede88a871f2fc072d4a.CALL( )
  • ETH 0.001269991932036917 0x78afc1d58eb5a6a6ed7ac7ea95c44f34d1b1e0a2.CALL( )
  • ETH 0.001283436815549945 0x5a10825f70cbb14d5ab73a16e0ff69db9c793dc2.CALL( )
  • ETH 0.001287116790608937 0x158b74d3435e2ba28eda51fa27a572dac24f27c7.CALL( )
  • ETH 0.00129166577765644 0x8951a7158d5f7f417a77128be241aa43d2005307.CALL( )
  • ETH 0.001296954029096793 0x464f939e7dbf927873f6c0e03bc0576d605d9b2e.CALL( )
  • ETH 0.001306759078648549 0x72f405ed763b277048b129abb7fdc058271b4726.CALL( )
  • ETH 0.001311228010140473 0xd9993e61edc96f9610d171d1ed27d31e94fcdca0.CALL( )
  • ETH 0.001323698910289819 0x62b1ef138eb00ef14b880ef89a28517b52f93e1c.CALL( )
  • ETH 0.001326215281823489 0x075f63f07d0539409a8c6b13f0f28d51357f6de4.CALL( )
  • ETH 0.001339155432036917 0x6e928dcace4cbe0cf84f92013d6fc4806f8fb5b8.CALL( )
  • ETH 0.001343469028807983 0xe0b6220980af7ea3ffcd5d83c2fff457c18857b4.CALL( )
  • ETH 0.001355201635581285 0xeb9304472a3c23ef98ebc925d5376615e789e560.CALL( )
  • ETH 0.001374034263933962 0x16fb28504df51116a0db4af5132671ef4ca8494d.CALL( )
  • ETH 0.001386050471555457 0xff15c2b36d45b5e34937023ec96a19136a7ff063.CALL( )
  • ETH 0.001393355258895449 0x867731e64400f14584f75e5d216fc5d92d14909c.CALL( )
  • ETH 0.001397653814064379 0x46f2874a1dfc02ba97efd194e51bfeb6ef6f60d9.CALL( )
  • ETH 0.00143800897922551 0x70a8be7296e318c84ddaaa0854a8de9270f8be51.CALL( )
  • ETH 0.001446550703296558 0xf0bd783c667b9d03e680fcc552501bec300629a0.CALL( )
  • ETH 0.001482035165424342 0xfe79f3e21467a0a1082b1c15d13a9f7ed9e6c928.CALL( )
  • ETH 0.001527852413683 0x9954f7c26e0288892e6bae9ef9373ae917d3f108.CALL( )
  • ETH 0.001560680640937857 0x14ad241ba1937a43a904ccf0a4ffd54d9e798502.CALL( )
  • ETH 0.001599327141268417 0x692b8e8708e1ee0692da34068c84d2795ef66d97.CALL( )
  • ETH 0.00454309 0x6a72d03494cf3cde0d1b84d9614cc5bac6c6cf24.CALL( )
  • ETH 0.00478465 0x688b1495959a57aa34280544ba31c59b260f7838.CALL( )
  • ETH 0.00566309 0x6ade09f629073c0af7032f8c3f1168662925c56c.CALL( )
  • ETH 0.00607456 0x85da746704d27bf483303746f9e31ac84d1b8dce.CALL( )
  • ETH 0.00810586 BingX Dep: 0x40BBbcFDfC6932600D9258fE6ff422821521E7fe.CALL( )
  • ETH 0.00907526 0x25734b968d7f5c1e027e48cdc6c070bca99d657b.CALL( )
  • ETH 0.0124508 0x647c1861345d52f84ca1659f51d0485ae4167aaa.CALL( )
  • ETH 0.01269613 0x31a817802ee183eb8b13167ffe24bd28dcc6f30c.CALL( )
  • ETH 0.01283226 0xb831579e837824432d5d19ac10456728e87ed605.CALL( )
  • ETH 0.01459923 0x73cef42eb480fa806af8077b27de323264197e8c.CALL( )
  • ETH 0.01548584 0xe4761536144b9f4b46dda79834c88a91058adf5c.CALL( )
  • ETH 0.02030022 0x22d60d8ca42b6d82cec33a4ed68f5950e7126f18.CALL( )
  • ETH 0.02035911 0x7ef6e570ae8e977adcb4646b2d0befa364b12602.CALL( )
  • ETH 0.0209287 0xb04d264a001b00c9e1791edb9944c274d09f3cf9.CALL( )
  • ETH 0.02600673 0xa2d5572cf61c98ac0b8b542059356bb3547a78ef.CALL( )
  • ETH 0.02638583 0xb7483f2e0d2c0b00c401a875e260b38dea7c1414.CALL( )
  • ETH 0.03036264 0xd954560419a88223fff2ccde6efbae9f884af739.CALL( )
  • ETH 0.03380218 0x55eb6c70eb1a87ffa3c3a2f4d5385d399f14379c.CALL( )
  • ETH 0.03703285 0xb79ad82adf2985fe5d79271e948a8a29b1e7823e.CALL( )
  • ETH 0.05341972 0x1fbe6a01183b39a8fcbcb358dd310264b87c4f02.CALL( )
  • ETH 0.05741118 0x6351b68517bd899b44d0ee8301d14302cbfdf59c.CALL( )
  • ETH 0.09299323 0x9b5adebad48cf33869ddc6a463839ba24a0fff54.CALL( )
  • ETH 0.11005187 Forwarder.CALL( )
    • ETH 0.11005187 Forwarder.DELEGATECALL( )
      • ETH 0.11005187 0x7a5ce41c3511e4838f5dcefcf5533950ee1a8315.CALL( )
      • ETH 0.13953657 0x2c2e4c7993a11130f34a7eebe00364374d89d339.CALL( )
      • ETH 0.15 0x74047b072d81b563a096c6d4d5ac2fae139357b9.CALL( )
        File 1 of 2: Forwarder
        pragma solidity 0.7.5;
        
        /*
            The MIT License (MIT)
            Copyright (c) 2018 Murray Software, LLC.
            Permission is hereby granted, free of charge, to any person obtaining
            a copy of this software and associated documentation files (the
            "Software"), to deal in the Software without restriction, including
            without limitation the rights to use, copy, modify, merge, publish,
            distribute, sublicense, and/or sell copies of the Software, and to
            permit persons to whom the Software is furnished to do so, subject to
            the following conditions:
            The above copyright notice and this permission notice shall be included
            in all copies or substantial portions of the Software.
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
            OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
            IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
            CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
            TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
            SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        */
        //solhint-disable max-line-length
        //solhint-disable no-inline-assembly
        
        contract CloneFactory {
          function createClone(address target, bytes32 salt)
            internal
            returns (address payable result)
          {
            bytes20 targetBytes = bytes20(target);
            assembly {
              // load the next free memory slot as a place to store the clone contract data
              let clone := mload(0x40)
        
              // The bytecode block below is responsible for contract initialization
              // during deployment, it is worth noting the proxied contract constructor will not be called during
              // the cloning procedure and that is why an initialization function needs to be called after the
              // clone is created
              mstore(
                clone,
                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
              )
        
              // This stores the address location of the implementation contract
              // so that the proxy knows where to delegate call logic to
              mstore(add(clone, 0x14), targetBytes)
        
              // The bytecode block is the actual code that is deployed for each clone created.
              // It forwards all calls to the already deployed implementation via a delegatecall
              mstore(
                add(clone, 0x28),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
              )
        
              // deploy the contract using the CREATE2 opcode
              // this deploys the minimal proxy defined above, which will proxy all
              // calls to use the logic defined in the implementation contract `target`
              result := create2(0, clone, 0x37, salt)
            }
          }
        
          function isClone(address target, address query)
            internal
            view
            returns (bool result)
          {
            bytes20 targetBytes = bytes20(target);
            assembly {
              // load the next free memory slot as a place to store the comparison clone
              let clone := mload(0x40)
        
              // The next three lines store the expected bytecode for a miniml proxy
              // that targets `target` as its implementation contract
              mstore(
                clone,
                0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000
              )
              mstore(add(clone, 0xa), targetBytes)
              mstore(
                add(clone, 0x1e),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
              )
        
              // the next two lines store the bytecode of the contract that we are checking in memory
              let other := add(clone, 0x40)
              extcodecopy(query, other, 0, 0x2d)
        
              // Check if the expected bytecode equals the actual bytecode and return the result
              result := and(
                eq(mload(clone), mload(other)),
                eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))
              )
            }
          }
        }
        
        
        /**
         * Contract that exposes the needed erc20 token functions
         */
        
        abstract contract ERC20Interface {
          // Send _value amount of tokens to address _to
          function transfer(address _to, uint256 _value)
            public
            virtual
            returns (bool success);
        
          // Get the account balance of another account with address _owner
          function balanceOf(address _owner)
            public
            virtual
            view
            returns (uint256 balance);
        }
        
        // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
        library TransferHelper {
            function safeApprove(
                address token,
                address to,
                uint256 value
            ) internal {
                // bytes4(keccak256(bytes('approve(address,uint256)')));
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
                require(
                    success && (data.length == 0 || abi.decode(data, (bool))),
                    'TransferHelper::safeApprove: approve failed'
                );
            }
        
            function safeTransfer(
                address token,
                address to,
                uint256 value
            ) internal {
                // bytes4(keccak256(bytes('transfer(address,uint256)')));
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
                require(
                    success && (data.length == 0 || abi.decode(data, (bool))),
                    'TransferHelper::safeTransfer: transfer failed'
                );
            }
        
            function safeTransferFrom(
                address token,
                address from,
                address to,
                uint256 value
            ) internal {
                // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
                require(
                    success && (data.length == 0 || abi.decode(data, (bool))),
                    'TransferHelper::transferFrom: transferFrom failed'
                );
            }
        
            function safeTransferETH(address to, uint256 value) internal {
                (bool success, ) = to.call{value: value}(new bytes(0));
                require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
            }
        }
        
        
        /**
         * Contract that will forward any incoming Ether to the creator of the contract
         *
         */
        contract Forwarder {
          // Address to which any funds sent to this contract will be forwarded
          address public parentAddress;
          event ForwarderDeposited(address from, uint256 value, bytes data);
        
          /**
           * Initialize the contract, and sets the destination address to that of the creator
           */
          function init(address _parentAddress) external onlyUninitialized {
            parentAddress = _parentAddress;
            uint256 value = address(this).balance;
        
            if (value == 0) {
              return;
            }
        
            (bool success, ) = parentAddress.call{ value: value }('');
            require(success, 'Flush failed');
            // NOTE: since we are forwarding on initialization,
            // we don't have the context of the original sender.
            // We still emit an event about the forwarding but set
            // the sender to the forwarder itself
            emit ForwarderDeposited(address(this), value, msg.data);
          }
        
          /**
           * Modifier that will execute internal code block only if the sender is the parent address
           */
          modifier onlyParent {
            require(msg.sender == parentAddress, 'Only Parent');
            _;
          }
        
          /**
           * Modifier that will execute internal code block only if the contract has not been initialized yet
           */
          modifier onlyUninitialized {
            require(parentAddress == address(0x0), 'Already initialized');
            _;
          }
        
          /**
           * Default function; Gets called when data is sent but does not match any other function
           */
          fallback() external payable {
            flush();
          }
        
          /**
           * Default function; Gets called when Ether is deposited with no data, and forwards it to the parent address
           */
          receive() external payable {
            flush();
          }
        
          /**
           * Execute a token transfer of the full balance from the forwarder token to the parent address
           * @param tokenContractAddress the address of the erc20 token contract
           */
          function flushTokens(address tokenContractAddress) external onlyParent {
            ERC20Interface instance = ERC20Interface(tokenContractAddress);
            address forwarderAddress = address(this);
            uint256 forwarderBalance = instance.balanceOf(forwarderAddress);
            if (forwarderBalance == 0) {
              return;
            }
        
            TransferHelper.safeTransfer(
              tokenContractAddress,
              parentAddress,
              forwarderBalance
            );
          }
        
          /**
           * Flush the entire balance of the contract to the parent address.
           */
          function flush() public {
            uint256 value = address(this).balance;
        
            if (value == 0) {
              return;
            }
        
            (bool success, ) = parentAddress.call{ value: value }('');
            require(success, 'Flush failed');
            emit ForwarderDeposited(msg.sender, value, msg.data);
          }
        }
        
        contract ForwarderFactory is CloneFactory {
          address public implementationAddress;
        
          event ForwarderCreated(address newForwarderAddress, address parentAddress);
        
          constructor(address _implementationAddress) {
            implementationAddress = _implementationAddress;
          }
        
          function createForwarder(address parent, bytes32 salt) external {
            // include the signers in the salt so any contract deployed to a given address must have the same signers
            bytes32 finalSalt = keccak256(abi.encodePacked(parent, salt));
        
            address payable clone = createClone(implementationAddress, finalSalt);
            Forwarder(clone).init(parent);
            emit ForwarderCreated(clone, parent);
          }
        }

        File 2 of 2: Forwarder
        pragma solidity 0.7.5;
        
        /*
            The MIT License (MIT)
            Copyright (c) 2018 Murray Software, LLC.
            Permission is hereby granted, free of charge, to any person obtaining
            a copy of this software and associated documentation files (the
            "Software"), to deal in the Software without restriction, including
            without limitation the rights to use, copy, modify, merge, publish,
            distribute, sublicense, and/or sell copies of the Software, and to
            permit persons to whom the Software is furnished to do so, subject to
            the following conditions:
            The above copyright notice and this permission notice shall be included
            in all copies or substantial portions of the Software.
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
            OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
            IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
            CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
            TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
            SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        */
        //solhint-disable max-line-length
        //solhint-disable no-inline-assembly
        
        contract CloneFactory {
          function createClone(address target, bytes32 salt)
            internal
            returns (address payable result)
          {
            bytes20 targetBytes = bytes20(target);
            assembly {
              // load the next free memory slot as a place to store the clone contract data
              let clone := mload(0x40)
        
              // The bytecode block below is responsible for contract initialization
              // during deployment, it is worth noting the proxied contract constructor will not be called during
              // the cloning procedure and that is why an initialization function needs to be called after the
              // clone is created
              mstore(
                clone,
                0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
              )
        
              // This stores the address location of the implementation contract
              // so that the proxy knows where to delegate call logic to
              mstore(add(clone, 0x14), targetBytes)
        
              // The bytecode block is the actual code that is deployed for each clone created.
              // It forwards all calls to the already deployed implementation via a delegatecall
              mstore(
                add(clone, 0x28),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
              )
        
              // deploy the contract using the CREATE2 opcode
              // this deploys the minimal proxy defined above, which will proxy all
              // calls to use the logic defined in the implementation contract `target`
              result := create2(0, clone, 0x37, salt)
            }
          }
        
          function isClone(address target, address query)
            internal
            view
            returns (bool result)
          {
            bytes20 targetBytes = bytes20(target);
            assembly {
              // load the next free memory slot as a place to store the comparison clone
              let clone := mload(0x40)
        
              // The next three lines store the expected bytecode for a miniml proxy
              // that targets `target` as its implementation contract
              mstore(
                clone,
                0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000
              )
              mstore(add(clone, 0xa), targetBytes)
              mstore(
                add(clone, 0x1e),
                0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
              )
        
              // the next two lines store the bytecode of the contract that we are checking in memory
              let other := add(clone, 0x40)
              extcodecopy(query, other, 0, 0x2d)
        
              // Check if the expected bytecode equals the actual bytecode and return the result
              result := and(
                eq(mload(clone), mload(other)),
                eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))
              )
            }
          }
        }
        
        
        /**
         * Contract that exposes the needed erc20 token functions
         */
        
        abstract contract ERC20Interface {
          // Send _value amount of tokens to address _to
          function transfer(address _to, uint256 _value)
            public
            virtual
            returns (bool success);
        
          // Get the account balance of another account with address _owner
          function balanceOf(address _owner)
            public
            virtual
            view
            returns (uint256 balance);
        }
        
        // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
        library TransferHelper {
            function safeApprove(
                address token,
                address to,
                uint256 value
            ) internal {
                // bytes4(keccak256(bytes('approve(address,uint256)')));
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
                require(
                    success && (data.length == 0 || abi.decode(data, (bool))),
                    'TransferHelper::safeApprove: approve failed'
                );
            }
        
            function safeTransfer(
                address token,
                address to,
                uint256 value
            ) internal {
                // bytes4(keccak256(bytes('transfer(address,uint256)')));
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
                require(
                    success && (data.length == 0 || abi.decode(data, (bool))),
                    'TransferHelper::safeTransfer: transfer failed'
                );
            }
        
            function safeTransferFrom(
                address token,
                address from,
                address to,
                uint256 value
            ) internal {
                // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
                (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
                require(
                    success && (data.length == 0 || abi.decode(data, (bool))),
                    'TransferHelper::transferFrom: transferFrom failed'
                );
            }
        
            function safeTransferETH(address to, uint256 value) internal {
                (bool success, ) = to.call{value: value}(new bytes(0));
                require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
            }
        }
        
        
        /**
         * Contract that will forward any incoming Ether to the creator of the contract
         *
         */
        contract Forwarder {
          // Address to which any funds sent to this contract will be forwarded
          address public parentAddress;
          event ForwarderDeposited(address from, uint256 value, bytes data);
        
          /**
           * Initialize the contract, and sets the destination address to that of the creator
           */
          function init(address _parentAddress) external onlyUninitialized {
            parentAddress = _parentAddress;
            uint256 value = address(this).balance;
        
            if (value == 0) {
              return;
            }
        
            (bool success, ) = parentAddress.call{ value: value }('');
            require(success, 'Flush failed');
            // NOTE: since we are forwarding on initialization,
            // we don't have the context of the original sender.
            // We still emit an event about the forwarding but set
            // the sender to the forwarder itself
            emit ForwarderDeposited(address(this), value, msg.data);
          }
        
          /**
           * Modifier that will execute internal code block only if the sender is the parent address
           */
          modifier onlyParent {
            require(msg.sender == parentAddress, 'Only Parent');
            _;
          }
        
          /**
           * Modifier that will execute internal code block only if the contract has not been initialized yet
           */
          modifier onlyUninitialized {
            require(parentAddress == address(0x0), 'Already initialized');
            _;
          }
        
          /**
           * Default function; Gets called when data is sent but does not match any other function
           */
          fallback() external payable {
            flush();
          }
        
          /**
           * Default function; Gets called when Ether is deposited with no data, and forwards it to the parent address
           */
          receive() external payable {
            flush();
          }
        
          /**
           * Execute a token transfer of the full balance from the forwarder token to the parent address
           * @param tokenContractAddress the address of the erc20 token contract
           */
          function flushTokens(address tokenContractAddress) external onlyParent {
            ERC20Interface instance = ERC20Interface(tokenContractAddress);
            address forwarderAddress = address(this);
            uint256 forwarderBalance = instance.balanceOf(forwarderAddress);
            if (forwarderBalance == 0) {
              return;
            }
        
            TransferHelper.safeTransfer(
              tokenContractAddress,
              parentAddress,
              forwarderBalance
            );
          }
        
          /**
           * Flush the entire balance of the contract to the parent address.
           */
          function flush() public {
            uint256 value = address(this).balance;
        
            if (value == 0) {
              return;
            }
        
            (bool success, ) = parentAddress.call{ value: value }('');
            require(success, 'Flush failed');
            emit ForwarderDeposited(msg.sender, value, msg.data);
          }
        }
        
        contract ForwarderFactory is CloneFactory {
          address public implementationAddress;
        
          event ForwarderCreated(address newForwarderAddress, address parentAddress);
        
          constructor(address _implementationAddress) {
            implementationAddress = _implementationAddress;
          }
        
          function createForwarder(address parent, bytes32 salt) external {
            // include the signers in the salt so any contract deployed to a given address must have the same signers
            bytes32 finalSalt = keccak256(abi.encodePacked(parent, salt));
        
            address payable clone = createClone(implementationAddress, finalSalt);
            Forwarder(clone).init(parent);
            emit ForwarderCreated(clone, parent);
          }
        }