Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xa4F6400fd2Bd1C3C1cA1DeFad79EB3b5269f9299
Balance 0 ETH
Nonce 1
Code Size 5115 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

5115 bytes
0x608060405260043610610108575f3560e01c8063967c0ccd11610092578063da25b72511610062578063da25b725146102df578063dc8b985014610312578063efc21e3f14610331578063f2fde38b14610345578063f9c10fa914610364575f80fd5b8063967c0ccd1461025b578063b5d2a1e91461026e578063c6328a461461028d578063cdf65f34146102c0575f80fd5b806358c2689b116100d857806358c2689b146101c45780635c975abb146101e35780635cbab4e1146102135780638456cb59146102285780638da5cb5b1461023c575f80fd5b8063091d2788146101135780631dac56d31461013c5780632c9465c6146101635780633f4ba83a146101ae575f80fd5b3661010f57005b5f80fd5b34801561011e575f80fd5b506101296203d09081565b6040519081526020015b60405180910390f35b348015610147575f80fd5b50610150600281565b60405161ffff9091168152602001610133565b34801561016e575f80fd5b506101967f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc881565b6040516001600160a01b039091168152602001610133565b3480156101b9575f80fd5b506101c2610378565b005b3480156101cf575f80fd5b506101966101de3660046110f1565b6103e4565b3480156101ee575f80fd5b5060035461020390600160a01b900460ff1681565b6040519015158152602001610133565b34801561021e575f80fd5b5061012960025481565b348015610233575f80fd5b506101c261046b565b348015610247575f80fd5b50600354610196906001600160a01b031681565b6101c261026936600461112b565b6104d4565b348015610279575f80fd5b506101c261028836600461116f565b610dcb565b348015610298575f80fd5b506101967f0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa58581565b3480156102cb575f80fd5b50600154610196906001600160a01b031681565b3480156102ea575f80fd5b506101967f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d89491181565b34801561031d575f80fd5b506101c261032c366004611186565b610e36565b34801561033c575f80fd5b50610150601e81565b348015610350575f80fd5b506101c261035f366004611186565b610eca565b34801561036f575f80fd5b50610129610f8b565b6003546001600160a01b031633146103ab5760405162461bcd60e51b81526004016103a2906111b3565b60405180910390fd5b6003805460ff60a01b1916905560405133907f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa905f90a2565b5f80826040516020016103f791906111f8565b60408051601f1981840301815282825280516020918201206001546002546001600160f81b03198487015260609190911b6bffffffffffffffffffffffff19166021860152603585019190915260558085019190915282518085039091018152607590930190915281519101209392505050565b6003546001600160a01b031633146104955760405162461bcd60e51b81526004016103a2906111b3565b6003805460ff60a01b1916600160a01b17905560405133907f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258905f90a2565b6104dc61102c565b600354600160a01b900460ff16156105285760405162461bcd60e51b815260206004820152600f60248201526e10dbdb9d1c9858dd081c185d5cd959608a1b60448201526064016103a2565b5f821161056c5760405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b60448201526064016103a2565b5f8151116105b35760405162461bcd60e51b8152602060048201526014602482015273456d70747920747769747465722068616e646c6560601b60448201526064016103a2565b5f6105bd826103e4565b90505f6105c8610f8b565b90508034101561060d5760405162461bcd60e51b815260206004820152601060248201526f496e73756666696369656e742066656560801b60448201526064016103a2565b6040516370a0823160e01b81523060048201525f907f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc86001600160a01b0316906370a0823190602401602060405180830381865afa158015610671573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610695919061121e565b6040516323b872dd60e01b8152336004820152306024820152604481018790529091507f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc86001600160a01b0316906323b872dd906064016020604051808303815f875af1158015610708573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072c9190611235565b61076a5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064016103a2565b6040516370a0823160e01b81523060048201525f907f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc86001600160a01b0316906370a0823190602401602060405180830381865afa1580156107ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107f2919061121e565b90505f6107ff8383611254565b9050868110156108515760405162461bcd60e51b815260206004820152601860248201527f5472616e7366657220616d6f756e74206d69736d61746368000000000000000060448201526064016103a2565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa58581166004830152602482018990527f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc8169063095ea7b3906044016020604051808303815f875af11580156108dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109019190611235565b61093f5760405162461bcd60e51b815260206004820152600f60248201526e105c1c1c9bdd985b0819985a5b1959608a1b60448201526064016103a2565b60405162f5287b60e41b81526001600160a01b037f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc88116600483015260248201899052601e604483015286811660648301525f6084830181905260a48301819052917f0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa58590911690630f5287b09060c4016020604051808303815f875af11580156109eb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0f9190611279565b6040516370a0823160e01b81523060048201529091505f906001600160a01b037f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc816906370a0823190602401602060405180830381865afa158015610a76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9a919061121e565b9050610aa68985611254565b811115610af55760405162461bcd60e51b815260206004820152601d60248201527f42726964676520646964206e6f74207265636569766520746f6b656e7300000060448201526064016103a2565b84811015610b455760405162461bcd60e51b815260206004820152601b60248201527f556e65787065637465642062616c616e6365206465637265617365000000000060448201526064016103a2565b60405163095ea7b360e01b81526001600160a01b037f0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585811660048301525f60248301527f0000000000000000000000000f7dc5d02cc1e1f5ee47854d534d332a1081ccc8169063095ea7b3906044016020604051808303815f875af1158015610bd0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf49190611235565b505f3389898c86604051602001610c0f9594939291906112cb565b60408051601f19818403018152908290526001546312d729bd60e21b83529092505f916001600160a01b037f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911811692634b5ca6f4928c92610c8692601e92911690889088906203d090906002903390600401611312565b60206040518083038185885af1158015610ca2573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190610cc79190611279565b9050886001600160a01b0316336001600160a01b03167f760345242447126ab56a8a34e3e51a46ea62b99ac50ce7f3aa0ebe6258bab5f98c8e8886604051610d12949392919061136a565b60405180910390a35f610d258934611254565b90508015610db4576040515f90339083908381818185875af1925050503d805f8114610d6c576040519150601f19603f3d011682016040523d82523d5f602084013e610d71565b606091505b5050905080610db25760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b60448201526064016103a2565b505b50505050505050505050610dc760015f55565b5050565b6003546001600160a01b03163314610df55760405162461bcd60e51b81526004016103a2906111b3565b80610e315760405162461bcd60e51b815260206004820152600c60248201526b092dcecc2d8d2c840d0c2e6d60a31b60448201526064016103a2565b600255565b6003546001600160a01b03163314610e605760405162461bcd60e51b81526004016103a2906111b3565b6001600160a01b038116610ea85760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420666163746f727960881b60448201526064016103a2565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b03163314610ef45760405162461bcd60e51b81526004016103a2906111b3565b6001600160a01b038116610f3a5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016103a2565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60405163c23ee3c360e01b8152601e60048201525f602482018190526203d09060448301529081906001600160a01b037f00000000000000000000000027428dd2d3dd32a4d7f7c497eaaa23130d894911169063c23ee3c3906064016040805180830381865afa158015611001573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102591906113a3565b5092915050565b60025f540361104e57604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112611077575f80fd5b813567ffffffffffffffff8082111561109257611092611054565b604051601f8301601f19908116603f011681019082821181831017156110ba576110ba611054565b816040528381528660208588010111156110d2575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f60208284031215611101575f80fd5b813567ffffffffffffffff811115611117575f80fd5b61112384828501611068565b949350505050565b5f806040838503121561113c575f80fd5b82359150602083013567ffffffffffffffff811115611159575f80fd5b61116585828601611068565b9150509250929050565b5f6020828403121561117f575f80fd5b5035919050565b5f60208284031215611196575f80fd5b81356001600160a01b03811681146111ac575f80fd5b9392505050565b6020808252600990820152682737ba1037bbb732b960b91b604082015260600190565b5f5b838110156111f05781810151838201526020016111d8565b50505f910152565b5f82516112098184602087016111d6565b625f763360e81b920191825250600301919050565b5f6020828403121561122e575f80fd5b5051919050565b5f60208284031215611245575f80fd5b815180151581146111ac575f80fd5b8181038181111561127357634e487b7160e01b5f52601160045260245ffd5b92915050565b5f60208284031215611289575f80fd5b815167ffffffffffffffff811681146111ac575f80fd5b5f81518084526112b78160208601602086016111d6565b601f01601f19169290920160200192915050565b5f60018060a01b03808816835260a060208401526112ec60a08401886112a0565b9516604083015250606081019290925267ffffffffffffffff1660809091015292915050565b5f61ffff808a16835260018060a01b03808a16602085015260e0604085015261133e60e085018a6112a0565b925087606085015286608085015281861660a085015280851660c0850152505098975050505050505050565b608081525f61137c60808301876112a0565b60208301959095525067ffffffffffffffff92831660408201529116606090910152919050565b5f80604083850312156113b4575f80fd5b50508051602090910151909290915056fea2646970667358221220c75b5358fd0e3ca07381012f7539f38c8de9b8ea0fc988723418e48323e198d164736f6c63430008140033

Verified Source Code Full Match

Compiler: v0.8.20+commit.a1b79de6 EVM: shanghai Optimization: Yes (200 runs)
DepositBridge.sol 234 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "../interfaces/IWormholeRelayer.sol";
import "../interfaces/ITokenBridge.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

/**
 * @title DepositBridge
 * @notice Bridge ZEUS from Ethereum to Base in 1 TX with Wormhole Auto-Relay
 * @dev Uses separate TokenBridge.transferTokens() + WormholeRelayer.sendPayloadToEvm()
 *      because transferTokensWithPayload() doesn't support automatic relay
 */
contract DepositBridge is ReentrancyGuard {
    IERC20 public immutable zeusToken;
    ITokenBridge public immutable tokenBridge;
    IWormholeRelayer public immutable wormholeRelayer;

    uint16 public constant BASE_CHAIN_ID = 30;  // Wormhole chain ID for Base
    uint16 public constant ETHEREUM_CHAIN_ID = 2;  // Wormhole chain ID for Ethereum
    uint256 public constant GAS_LIMIT = 250_000;  // Gas for receiving on Base

    address public walletFactoryOnBase;  // WalletFactory contract address on Base
    bytes32 public userWalletBytecodeHash;  // Hash of UserWallet bytecode for CREATE2 computation
    address public owner;

    bool public paused = false;

    event DepositInitiated(
        address indexed user,
        string twitterHandle,
        address indexed recipientWallet,
        uint256 amount,
        uint64 tokenSequence,
        uint64 messageSequence
    );
    event Paused(address indexed by);
    event Unpaused(address indexed by);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor(
        address _zeusToken,
        address _wormholeRelayer,
        address _tokenBridge,
        address _walletFactoryOnBase,
        bytes32 _userWalletBytecodeHash
    ) {
        require(_zeusToken != address(0), "Invalid token");
        require(_wormholeRelayer != address(0), "Invalid relayer");
        require(_tokenBridge != address(0), "Invalid bridge");
        require(_walletFactoryOnBase != address(0), "Invalid factory");
        require(_userWalletBytecodeHash != bytes32(0), "Invalid bytecode hash");

        zeusToken = IERC20(_zeusToken);
        wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
        tokenBridge = ITokenBridge(_tokenBridge);
        walletFactoryOnBase = _walletFactoryOnBase;
        userWalletBytecodeHash = _userWalletBytecodeHash;
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    modifier whenNotPaused() {
        require(!paused, "Contract paused");
        _;
    }

    /**
     * @notice Emergency pause
     */
    function pause() external onlyOwner {
        paused = true;
        emit Paused(msg.sender);
    }

    function unpause() external onlyOwner {
        paused = false;
        emit Unpaused(msg.sender);
    }

    /**
     * @notice Compute deterministic UserWallet address on Base (same as WalletFactory.computeAddress)
     * @param twitterHandle Twitter handle (without @)
     * @return Predicted UserWallet address on Base
     */
    function computeUserWalletAddress(string memory twitterHandle)
        public
        view
        returns (address)
    {
        // V3: Add "_v3" suffix to match WalletFactory V3 on Base
        bytes32 salt = keccak256(abi.encodePacked(twitterHandle, "_v3"));

        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes1(0xff),
                walletFactoryOnBase,
                salt,
                userWalletBytecodeHash
            )
        );

        return address(uint160(uint256(hash)));
    }

    /**
     * @notice Quote cost for bridge (only WormholeRelayer fee, TokenBridge is free)
     */
    function quoteCrossChainDeposit() public view returns (uint256 cost) {
        (uint256 deliveryCost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
            BASE_CHAIN_ID,
            0,
            GAS_LIMIT
        );
        return deliveryCost;
    }

    /**
     * @notice Deposit and bridge to Base in 1 TX
     * @param amount Amount of ZEUS tokens
     * @param twitterHandle Twitter handle of recipient (without @)
     * @dev Computes UserWallet address deterministically and sends tokens directly
     *      UserWallet doesn't need to be deployed yet - tokens will arrive when it's deployed
     */
    function depositAndBridge(
        uint256 amount,
        string memory twitterHandle
    ) external payable nonReentrant whenNotPaused {
        require(amount > 0, "Amount must be > 0");
        require(bytes(twitterHandle).length > 0, "Empty twitter handle");

        // Compute deterministic UserWallet address (may not be deployed yet)
        address recipientWallet = computeUserWalletAddress(twitterHandle);

        uint256 cost = quoteCrossChainDeposit();
        require(msg.value >= cost, "Insufficient fee");

        // Transfer ZEUS from user
        uint256 balanceBefore = zeusToken.balanceOf(address(this));
        require(zeusToken.transferFrom(msg.sender, address(this), amount), "Transfer failed");

        // Verify actual amount received (handles fee-on-transfer tokens)
        uint256 balanceAfter = zeusToken.balanceOf(address(this));
        uint256 actualAmount = balanceAfter - balanceBefore;
        require(actualAmount >= amount, "Transfer amount mismatch");

        // 1. Send tokens via TokenBridge directly to UserWallet on Base
        // Note: Wallet doesn't need to be deployed yet - tokens will arrive when it's deployed
        require(zeusToken.approve(address(tokenBridge), amount), "Approval failed");

        uint64 tokenSequence = tokenBridge.transferTokens(
            address(zeusToken),
            amount,
            BASE_CHAIN_ID,
            bytes32(uint256(uint160(recipientWallet))),  // Send to computed UserWallet address
            0,  // arbiter fee
            0   // nonce
        );

        // Security: Verify tokens were actually transferred to bridge
        // Use range checks instead of strict equality to handle edge cases
        uint256 balanceAfterBridge = zeusToken.balanceOf(address(this));
        require(balanceAfterBridge <= balanceAfter - amount, "Bridge did not receive tokens");
        require(balanceAfterBridge >= balanceBefore, "Unexpected balance decrease");

        // Security: Reset approval to 0 (defense in depth)
        zeusToken.approve(address(tokenBridge), 0);

        // 2. Send message via WormholeRelayer (with automatic relay)
        // Note: We send twitterHandle instead of just address for better tracking
        bytes memory payload = abi.encode(
            msg.sender,        // original sender on Ethereum
            twitterHandle,     // twitter handle of recipient
            recipientWallet,   // computed UserWallet address on Base
            amount,            // amount being sent
            tokenSequence      // token transfer sequence number for matching
        );

        uint64 messageSequence = wormholeRelayer.sendPayloadToEvm{value: cost}(
            BASE_CHAIN_ID,
            walletFactoryOnBase,
            payload,
            0,                  // no receiver value
            GAS_LIMIT,
            ETHEREUM_CHAIN_ID,  // refund chain
            msg.sender          // refund address (original sender)
        );

        emit DepositInitiated(msg.sender, twitterHandle, recipientWallet, amount, tokenSequence, messageSequence);

        // Refund excess ETH
        uint256 excess = msg.value - cost;
        if (excess > 0) {
            (bool success, ) = msg.sender.call{value: excess}("");
            require(success, "Refund failed");
        }
    }

    /**
     * @notice Update WalletFactory address on Base
     */
    function setWalletFactoryOnBase(address _factory) external onlyOwner {
        require(_factory != address(0), "Invalid factory");
        walletFactoryOnBase = _factory;
    }

    /**
     * @notice Update UserWallet bytecode hash (if UserWallet contract changes)
     */
    function setUserWalletBytecodeHash(bytes32 _hash) external onlyOwner {
        require(_hash != bytes32(0), "Invalid hash");
        userWalletBytecodeHash = _hash;
    }

    /**
     * @notice Transfer ownership
     */
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Invalid owner");
        address oldOwner = owner;
        owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

    /**
     * @notice Receive ETH
     */
    receive() external payable {}
}
IWormholeRelayer.sol 35 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title IWormholeRelayer
 * @notice Interface for Wormhole Automatic Relayer
 * @dev Used for cross-chain message delivery with automatic relay
 */
interface IWormholeRelayer {
    function quoteEVMDeliveryPrice(
        uint16 targetChain,
        uint256 receiverValue,
        uint256 gasLimit
    ) external view returns (uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused);

    // Simple version (refunds go to delivery provider)
    function sendPayloadToEvm(
        uint16 targetChain,
        address targetAddress,
        bytes memory payload,
        uint256 receiverValue,
        uint256 gasLimit
    ) external payable returns (uint64 sequence);

    // Full version with refund parameters (REQUIRED for production)
    function sendPayloadToEvm(
        uint16 targetChain,
        address targetAddress,
        bytes memory payload,
        uint256 receiverValue,
        uint256 gasLimit,
        uint16 refundChain,
        address refundAddress
    ) external payable returns (uint64 sequence);
}
ITokenBridge.sol 42 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title ITokenBridge
 * @notice Interface for Wormhole Token Bridge
 */
interface ITokenBridge {
    struct Transfer {
        uint8 payloadID;
        uint256 amount;
        bytes32 tokenAddress;
        uint16 tokenChain;
        bytes32 to;
        uint16 toChain;
        uint256 fee;
    }

    function transferTokens(
        address token,
        uint256 amount,
        uint16 recipientChain,
        bytes32 recipient,
        uint256 arbiterFee,
        uint32 nonce
    ) external payable returns (uint64 sequence);

    function transferTokensWithPayload(
        address token,
        uint256 amount,
        uint16 toChain,
        bytes32 to,
        uint32 batchID,
        bytes memory payload
    ) external payable returns (uint64 sequence);

    function completeTransfer(bytes memory encodedVaa) external returns (bytes memory);

    function completeTransferWithPayload(bytes memory encodedVaa) external returns (bytes memory);

    function parseTransfer(bytes memory encodedVaa) external pure returns (Transfer memory transfer);
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}
ReentrancyGuard.sol 87 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

Read Contract

BASE_CHAIN_ID 0xefc21e3f → uint16
ETHEREUM_CHAIN_ID 0x1dac56d3 → uint16
GAS_LIMIT 0x091d2788 → uint256
computeUserWalletAddress 0x58c2689b → address
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
quoteCrossChainDeposit 0xf9c10fa9 → uint256
tokenBridge 0xc6328a46 → address
userWalletBytecodeHash 0x5cbab4e1 → bytes32
walletFactoryOnBase 0xcdf65f34 → address
wormholeRelayer 0xda25b725 → address
zeusToken 0x2c9465c6 → address

Write Contract 6 functions

These functions modify contract state and require a wallet transaction to execute.

depositAndBridge 0x967c0ccd
uint256 amount
string twitterHandle
pause 0x8456cb59
No parameters
setUserWalletBytecodeHash 0xb5d2a1e9
bytes32 _hash
setWalletFactoryOnBase 0xdc8b9850
address _factory
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters

Recent Transactions

No transactions found for this address