Transaction Hash:
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 | ||
---|---|---|---|---|---|
0x0A5ED20B...A96F45490 | 0.069763213137289957 Eth | 0.081144013137289957 Eth | 0.0113808 | ||
0x1a2b924D...611488BD6 | 0 Eth | 0.03473818 Eth | 0.03473818 | ||
0x358A20c5...1EA730c30 | 0.00043676760483887 Eth | 0.00389698075 Eth | 0.00346021314516113 | ||
0x388C818C...7ccB19297
Miner
| (Lido: Execution Layer Rewards Vault) | 35.965882239096980486 Eth | 35.966174508096980486 Eth | 0.000292269 | |
0x3efE7e0a...928fdD012 | 0.01479424 Eth | 0.03161807 Eth | 0.01682383 | ||
0x4135789D...901df0967 | 0.032841579762628117 Eth | 0.060080739762628117 Eth | 0.02723916 | ||
0x49ba3dEb...a57665670 | 0.14336992067170642 Eth | 1.93968623067170642 Eth | 1.79631631 | ||
0x54E818D8...15238C7e7 | 0.000513527325024 Eth | 0.001882237325024 Eth | 0.00136871 | ||
0x558Cdeb1...F9621E756 | 0.005856650886895378 Eth | 0.012116620886895378 Eth | 0.00625997 | ||
0x563BFF50...964D1148d | 0.000142252684959 Eth | 0.051291362684959 Eth | 0.05114911 | ||
0x6b4b7b05...A1dCCaE24 | 0.000483746065614 Eth | 0.00389698075 Eth | 0.003413234684386 | ||
0x758EC44d...f297cE85E | 0.001501495861339828 Eth | 0.0031672345 Eth | 0.001665738638660172 | ||
0x7830c87C...31FA86F43 | (Coinbase: Deposit) |
95.750127126855531576 Eth
Nonce: 1366421
|
95.737155391416952164 Eth
Nonce: 1366422
| 0.012971735438579412 | |
0x7Dd63d2a...E3E724439 | 0.0567862 Eth | 0.11753299 Eth | 0.06074679 | ||
0x836f14f7...6F5cbFfE1 | 0.00620005 Eth | 0.011475 Eth | 0.00527495 | ||
0x90720fB0...13B024A2A | 0.000723181184277134 Eth | 0.002393557 Eth | 0.001670375815722866 | ||
0xa5D29237...1E3bB5cc8 | (BitGo: MultiSig 3) | 1.531525920887404788 Eth | 1.554149470887404788 Eth | 0.02262355 | |
0xA9D1e08C...FB81d3E43 | (Coinbase 10) | 383.469931849419583967 Eth | 381.201360955545314182 Eth | 2.268570893874269785 | |
0xaBB2a0d6...93994b3da | 0.005393887001912479 Eth | 0.006610887001912479 Eth | 0.001217 | ||
0xD07c7DB4...632915bd9 | 0.00137497546231398 Eth | 0.00389698075 Eth | 0.00252200528768602 | ||
0xd202eC2D...D1F6360F7 | 0.000885985504131775 Eth | 0.014960185504131775 Eth | 0.0140742 | ||
0xD4E463DC...Db06ea045 | 0.004021332322334485 Eth | 0.026499352322334485 Eth | 0.02247802 | ||
0xDb529554...964382126 | 0.02096321573313 Eth | 0.11014673573313 Eth | 0.08918352 | ||
0xE64764d6...E4Ad1b4e4 | 0.01065828 Eth | 0.03022417 Eth | 0.01956589 | ||
0xeCd34c51...1F8b1d838 | 0.002123263052712794 Eth | 0.003443863052712794 Eth | 0.0013206 | ||
0xF53B823e...9eFcC53F8 | 0.000469471245019551 Eth | 0.072549331245019551 Eth | 0.07207986 | ||
0xFb120215...12Dccd7CC | 0.000602813447346403 Eth | 0.00260168975 Eth | 0.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.02262355
- 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
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); } }
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); } }