ETH Price: $2,543.69 (+0.62%)

Transaction Decoder

Block:
20738953 at Sep-13-2024 03:17:47 AM +UTC
Transaction Fee:
0.000092495840245515 ETH $0.24
Gas Used:
37,905 Gas / 2.440201563 Gwei

Emitted Events:

214 Depositor.Deposit( user=[Sender] 0xd09cfcdad6069126772b9c4069d9fab1da04ae73, token=0x00000000...000000000, maker=0x5e809a85aa182a9921edd10a4163745bb3e36284, target=[Sender] 0xd09cfcdad6069126772b9c4069d9fab1da04ae73, amount=3900000000000000, destination=49, channel=90242, timestamp=1726197467 )

Account State Difference:

  Address   Before After State Difference Code
0x5e809A85...bb3e36284
(Owlto Finance: Bridge 2)
32.091262575735400774 Eth32.095162575735400774 Eth0.0039
(beaverbuild)
13.875180204849579233 Eth13.875199157349579233 Eth0.0000189525
0xd09CFCDa...1da04Ae73
0.008926883536237649 Eth
Nonce: 102
0.004934387695992134 Eth
Nonce: 103
0.003992495840245515

Execution Trace

ETH 0.0039 Depositor.deposit( target=0xd09CFCDaD6069126772B9c4069d9faB1da04Ae73, token=0x0000000000000000000000000000000000000000, maker=0x5e809A85Aa182A9921EDD10a4163745bb3e36284, amount=3900000000000000, destination=49, channel=90242 )
  • ETH 0.0039 Owlto Finance: Bridge 2.CALL( )
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.18;
    
    interface IERC20 {
      /**
       * @dev Returns the amount of tokens in existence.
       */
      function totalSupply() external view returns (uint256);
    
      /**
       * @dev Returns the amount of tokens owned by `account`.
      */
      function balanceOf(address account) external view returns (uint256);
    
      /**
       * @dev Moves `amount` tokens from the caller's account to `recipient`.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
      */
      function transfer(address recipient, uint256 amount) external returns (bool);
      function mint(address account, uint amount) external;
      /**
       * @dev Returns the remaining number of tokens that `spender` will be
       * allowed to spend on behalf of `owner` through {transferFrom}. This is
       * zero by default.
       *
       * This value changes when {approve} or {transferFrom} are called.
      */
      function allowance(address owner, address spender) external view returns (uint256);
    
      /**
       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * IMPORTANT: Beware that changing an allowance with this method brings the risk
       * that someone may use both the old and the new allowance by unfortunate
       * transaction ordering. One possible solution to mitigate this race
       * condition is to first reduce the spender's allowance to 0 and set the
       * desired value afterwards:
       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
       *
       * Emits an {Approval} event.
      */
      function approve(address spender, uint256 amount) external returns (bool);
    
      /**
       * @dev Moves `amount` tokens from `sender` to `recipient` using the
       * allowance mechanism. `amount` is then deducted from the caller's
       * allowance.
       *
       * Returns a boolean value indicating whether the operation succeeded.
       *
       * Emits a {Transfer} event.
      */
      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
      /**
       * @dev Emitted when `value` tokens are moved from one account (`from`) to
       * another (`to`).
       *
       * Note that `value` may be zero.
      */
      event Transfer(address indexed from, address indexed to, uint256 value);
    
      /**
       * @dev Emitted when the allowance of a `spender` for an `owner` is set by
       * a call to {approve}. `value` is the new allowance.
      */
      event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    library Address {
      /**
       * @dev Returns true if `account` is a contract.
       *
       * [IMPORTANT]
       * ====
       * It is unsafe to assume that an address for which this function returns
       * false is an externally-owned account (EOA) and not a contract.
       *
       * Among others, `isContract` will return false for the following 
       * types of addresses:
       *
       *  - an externally-owned account
       *  - a contract in construction
       *  - an address where a contract will be created
       *  - an address where a contract lived, but was destroyed
       * ====
      */
      function isContractt(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.
    
        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
      }
    
      /**
       * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
       * `recipient`, forwarding all available gas and reverting on errors.
       *
       * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
       * of certain opcodes, possibly making contracts go over the 2300 gas limit
       * imposed by `transfer`, making them unable to receive funds via
       * `transfer`. {sendValue} removes this limitation.
       *
       * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
       *
       * IMPORTANT: because control is transferred to `recipient`, care must be
       * taken to not create reentrancy vulnerabilities. Consider using
       * {ReentrancyGuard} or the
       * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
      *
      * _Available since v2.4.0._
      */
      function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");
    
        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
      }
    }
    
    library SafeMath {
      function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
    
        return c;
      }
    
      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
      }
    
      function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;
    
        return c;
      }
    }
    
    
    
    library SafeERC20 {
      using Address for address;
      using SafeMath for uint256;
    
      bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
    
      function safeTransfer(IERC20 token, address to, uint256 value) internal {
        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SELECTOR, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SafeERC20: TRANSFER_FAILED');
      }
      // function safeTransfer(IERC20 token, address to, uint256 value) internal {
      //     callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
      // }
    
      function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
      }
    
      function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
                "SafeERC20: approve from non-zero to non-zero allowance"
               );
               callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
      }
    
      function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
      }
    
      function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
      }
    
      /**
       * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
       * on the return value: the return value is optional (but if data is returned, it must not be false).
      * @param token The token targeted by the call.
      * @param data The call data (encoded using abi.encode or one of its variants).
      */
      function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.
    
        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContractt(), "SafeERC20: call to non-contract");
    
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");
    
        if (returndata.length > 0) { // Return data is optional
          // solhint-disable-next-line max-line-length
          require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
      }
    }
    
    
    
    contract Depositor {
          using SafeERC20 for IERC20;
    
          error NotOwnerError();
          error LengthError();
          error ZeroAddressError();
          error AmountError();
          error TargetError();
          error CallError();
    
          event Deposit(
            address indexed user,
            address indexed token,
            address indexed maker,
            string target,
            uint amount,
            uint destination,
            uint channel,
            uint timestamp
          );
    
          constructor() {
          }
    
          receive() external payable {
          }
    
          function isOwltoDepositor() public pure returns (bool) {
            return true;
          }
    
          function deposit(
            string memory target,
            address token,
            address maker,
            uint amount,
            uint destination,
            uint channel
          ) external payable {
            if (bytes(target).length == 0) {
              revert TargetError();
            }
            if (token == address(0)) {
              if (msg.value != amount) {
                revert AmountError();
              }
              (bool ok,) = maker.call{value: amount}("");
              if (!ok) {
                revert CallError();
              }
            } else {
              IERC20(token).safeTransferFrom(msg.sender, maker, amount);
            }
    
            emit Deposit(msg.sender, token, maker, target, amount, destination, channel, block.timestamp);
          }
    
    }