ETH Price: $2,425.97 (-0.36%)

Transaction Decoder

Block:
19619229 at Apr-09-2024 04:19:11 PM +UTC
Transaction Fee:
0.012971735438579412 ETH $31.47
Gas Used:
292,269 Gas / 44.382864548 Gwei

Emitted Events:

138 0xa5d29237a8f14ff25ab9683c38e64671e3bb5cc8.0x6e89d517057028190560dd200cf6bf792842861353d1173761dfa362e1c133f0( 0x6e89d517057028190560dd200cf6bf792842861353d1173761dfa362e1c133f0, 000000000000000000000000ba5d59d3c6f4f3a101459ec3de7538482d7e451b, 00000000000000000000000000000000000000000000000000505fffb54eec00, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000000 )
139 Forwarder.ForwarderDeposited( from=[Receiver] 0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43, value=22623550000000000, data=0x )

Account State Difference:

  Address   Before After State Difference Code
0x0A5ED20B...A96F45490 0.069763213137289957 Eth0.081144013137289957 Eth0.0113808
0x1a2b924D...611488BD6 0 Eth0.03473818 Eth0.03473818
0x358A20c5...1EA730c30 0.00043676760483887 Eth0.00389698075 Eth0.00346021314516113
(Lido: Execution Layer Rewards Vault)
35.965882239096980486 Eth35.966174508096980486 Eth0.000292269
0x3efE7e0a...928fdD012 0.01479424 Eth0.03161807 Eth0.01682383
0x4135789D...901df0967 0.032841579762628117 Eth0.060080739762628117 Eth0.02723916
0x49ba3dEb...a57665670 0.14336992067170642 Eth1.93968623067170642 Eth1.79631631
0x54E818D8...15238C7e7 0.000513527325024 Eth0.001882237325024 Eth0.00136871
0x558Cdeb1...F9621E756 0.005856650886895378 Eth0.012116620886895378 Eth0.00625997
0x563BFF50...964D1148d 0.000142252684959 Eth0.051291362684959 Eth0.05114911
0x6b4b7b05...A1dCCaE24 0.000483746065614 Eth0.00389698075 Eth0.003413234684386
0x758EC44d...f297cE85E 0.001501495861339828 Eth0.0031672345 Eth0.001665738638660172
0x7830c87C...31FA86F43
(Coinbase: Deposit)
95.750127126855531576 Eth
Nonce: 1366421
95.737155391416952164 Eth
Nonce: 1366422
0.012971735438579412
0x7Dd63d2a...E3E724439 0.0567862 Eth0.11753299 Eth0.06074679
0x836f14f7...6F5cbFfE1 0.00620005 Eth0.011475 Eth0.00527495
0x90720fB0...13B024A2A 0.000723181184277134 Eth0.002393557 Eth0.001670375815722866
0xa5D29237...1E3bB5cc8
(BitGo: MultiSig 3)
1.531525920887404788 Eth1.554149470887404788 Eth0.02262355
0xA9D1e08C...FB81d3E43
(Coinbase 10)
383.469931849419583967 Eth381.201360955545314182 Eth2.268570893874269785
0xaBB2a0d6...93994b3da 0.005393887001912479 Eth0.006610887001912479 Eth0.001217
0xD07c7DB4...632915bd9 0.00137497546231398 Eth0.00389698075 Eth0.00252200528768602
0xd202eC2D...D1F6360F7 0.000885985504131775 Eth0.014960185504131775 Eth0.0140742
0xD4E463DC...Db06ea045 0.004021332322334485 Eth0.026499352322334485 Eth0.02247802
0xDb529554...964382126 0.02096321573313 Eth0.11014673573313 Eth0.08918352
0xE64764d6...E4Ad1b4e4 0.01065828 Eth0.03022417 Eth0.01956589
0xeCd34c51...1F8b1d838 0.002123263052712794 Eth0.003443863052712794 Eth0.0013206
0xF53B823e...9eFcC53F8 0.000469471245019551 Eth0.072549331245019551 Eth0.07207986
0xFb120215...12Dccd7CC 0.000602813447346403 Eth0.00260168975 Eth0.001998876302653597

Execution Trace

Coinbase 10.1a1da075( )
  • ETH 0.001217 0xabb2a0d686e71601711e73fafbdf6e293994b3da.CALL( )
  • ETH 0.0013206 0xecd34c51e499b33dcbc9504189f6a211f8b1d838.CALL( )
  • ETH 0.00136871 0x54e818d89d0d081bc18f0c56839712515238c7e7.CALL( )
  • ETH 0.001665738638660172 0x758ec44dfb3fce288d466784210f554f297ce85e.CALL( )
  • ETH 0.001670375815722866 0x90720fb0c4bcc0baa9cfc7619261fb913b024a2a.CALL( )
  • ETH 0.001998876302653597 0xfb120215295963ba839b3e180d00c0412dccd7cc.CALL( )
  • ETH 0.00252200528768602 0xd07c7db43052a1ae67a07291bbd8a75632915bd9.CALL( )
  • ETH 0.003413234684386 0x6b4b7b05350389fbe16007ac7a92b61a1dccae24.CALL( )
  • ETH 0.00346021314516113 0x358a20c58197a176b3e1fa07cf422001ea730c30.CALL( )
  • ETH 0.00527495 0x836f14f777dbb506f3e81d91f2772aa6f5cbffe1.CALL( )
  • ETH 0.00625997 0x558cdeb1185c299e75245573ab14f6cf9621e756.CALL( )
  • ETH 0.0113808 0x0a5ed20ba33bc688c943fd0031f3234a96f45490.CALL( )
  • ETH 0.0140742 0xd202ec2d34b5915aff88030d40b0d50d1f6360f7.CALL( )
  • ETH 0.01682383 0x3efe7e0abbcceebe6c1381e08120da5928fdd012.CALL( )
  • ETH 0.01956589 0xe64764d6f83b1f51e1e055f553862cbe4ad1b4e4.CALL( )
  • ETH 0.02247802 0xd4e463dcfdc0e55be1a329aedf46662db06ea045.CALL( )
  • ETH 0.02262355 Forwarder.CALL( )
    • ETH 0.02262355 Forwarder.DELEGATECALL( )
      • ETH 0.02262355 BitGo: MultiSig 3.CALL( )
      • ETH 0.02723916 0x4135789dfef980f6a8c322731b050f1901df0967.CALL( )
      • ETH 0.03473818 0x1a2b924d6b8b4d88bd463f454b42a18611488bd6.CALL( )
      • ETH 0.05114911 0x563bff50f740d999f528c08e69facab964d1148d.CALL( )
      • ETH 0.06074679 0x7dd63d2ae158b6bb5f6413b1fe97e54e3e724439.CALL( )
      • ETH 0.07207986 0xf53b823e0668422df7073b23e471a319efcc53f8.CALL( )
      • ETH 0.08918352 0xdb529554ce4c5b696790fea4ff3d1a3964382126.CALL( )
      • ETH 1.79631631 0x49ba3deb7759041c0b6c4da16ce53a3a57665670.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);
          }
        }