Goerli Testnet

Contract

0xDA107A1CAf36d198B12c16c7B6a1d1C795978C42
Source Code

Overview

ETH Balance

0 ETH

Token Holdings

Transaction Hash
Method
Block
From
To
Value
Transfer95665192023-08-23 9:37:1235 days 6 hrs ago1692783432IN
0xDA107A...95978C42
0 ETH0.000076441.50000001
Transfer95664962023-08-23 9:31:0035 days 6 hrs ago1692783060IN
0xDA107A...95978C42
0 ETH0.000076441.50000001
Transfer95664742023-08-23 9:26:0035 days 6 hrs ago1692782760IN
0xDA107A...95978C42
0 ETH0.000076441.50000001
Transfer95664172023-08-23 9:12:0035 days 6 hrs ago1692781920IN
0xDA107A...95978C42
0 ETH0.000076441.50000001
Change Recovery ...94459052023-08-01 18:11:1256 days 21 hrs ago1690913472IN
0xDA107A...95978C42
0 ETH0.000074981.5001131
Change Recovery ...94248832023-07-28 23:28:3660 days 16 hrs ago1690586916IN
0xDA107A...95978C42
0 ETH0.000082971.65940611
Trusted Register94082382023-07-25 23:06:3663 days 16 hrs ago1690326396IN
0xDA107A...95978C42
0 ETH0.000108784
Trusted Register94081912023-07-25 22:54:3663 days 16 hrs ago1690325676IN
0xDA107A...95978C42
0 ETH0.000108784
Trusted Register94080862023-07-25 22:26:3663 days 17 hrs ago1690323996IN
0xDA107A...95978C42
0 ETH0.000108784
Transfer93854232023-07-22 0:38:4867 days 15 hrs ago1689986328IN
0xDA107A...95978C42
0 ETH0.000158793.11614727
Transfer93743232023-07-20 2:23:0069 days 13 hrs ago1689819780IN
0xDA107A...95978C42
0 ETH0.000076441.50000004
Transfer93726372023-07-19 19:07:3669 days 20 hrs ago1689793656IN
0xDA107A...95978C42
0 ETH0.000076441.50000581
Change Recovery ...93272632023-07-11 10:13:2478 days 5 hrs ago1689070404IN
0xDA107A...95978C42
0 ETH0.000286595.73186051
Change Recovery ...93271512023-07-11 9:44:0078 days 5 hrs ago1689068640IN
0xDA107A...95978C42
0 ETH0.000365167.30336286
Change Recovery ...93232822023-07-10 17:11:3678 days 22 hrs ago1689009096IN
0xDA107A...95978C42
0 ETH0.000151115.02051322
Change Recovery ...93229882023-07-10 16:00:1278 days 23 hrs ago1689004812IN
0xDA107A...95978C42
0 ETH0.00025845.16809417
Change Recovery ...93222662023-07-10 12:49:3679 days 2 hrs ago1688993376IN
0xDA107A...95978C42
0 ETH0.00120
Change Recovery ...93221402023-07-10 12:17:4879 days 3 hrs ago1688991468IN
0xDA107A...95978C42
0 ETH0.00042638.52602105
Change Recovery ...93216222023-07-10 10:05:3679 days 5 hrs ago1688983536IN
0xDA107A...95978C42
0 ETH0.000918
Change Recovery ...93195812023-07-10 1:04:1279 days 14 hrs ago1688951052IN
0xDA107A...95978C42
0 ETH0.000057371.1474258
Change Recovery ...93195082023-07-10 0:45:3679 days 14 hrs ago1688949936IN
0xDA107A...95978C42
0 ETH0.000054491.08987003
Change Recovery ...93193462023-07-10 0:06:0079 days 15 hrs ago1688947560IN
0xDA107A...95978C42
0 ETH0.000075761.51529404
Change Recovery ...93190242023-07-09 22:40:4879 days 17 hrs ago1688942448IN
0xDA107A...95978C42
0 ETH0.000075191.50381323
Register92367902023-06-25 6:53:1294 days 8 hrs ago1687675992IN
0xDA107A...95978C42
0 ETH0.000046551.85132928
Change Home92367852023-06-25 6:52:0094 days 8 hrs ago1687675920IN
0xDA107A...95978C42
0 ETH0.000048111.96902741
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Txn Hash Block From To Value
96032582023-08-29 21:28:3628 days 18 hrs ago1693344516
0xDA107A...95978C42
0 ETH
96032582023-08-29 21:28:3628 days 18 hrs ago1693344516
0xDA107A...95978C42
0 ETH
96028322023-08-29 19:42:3628 days 19 hrs ago1693338156
0xDA107A...95978C42
0 ETH
96028322023-08-29 19:42:3628 days 19 hrs ago1693338156
0xDA107A...95978C42
0 ETH
96027972023-08-29 19:33:0028 days 20 hrs ago1693337580
0xDA107A...95978C42
0 ETH
96027972023-08-29 19:33:0028 days 20 hrs ago1693337580
0xDA107A...95978C42
0 ETH
96022922023-08-29 17:23:1228 days 22 hrs ago1693329792
0xDA107A...95978C42
0 ETH
96022922023-08-29 17:23:1228 days 22 hrs ago1693329792
0xDA107A...95978C42
0 ETH
96022382023-08-29 17:10:2428 days 22 hrs ago1693329024
0xDA107A...95978C42
0 ETH
96022382023-08-29 17:10:2428 days 22 hrs ago1693329024
0xDA107A...95978C42
0 ETH
96022332023-08-29 17:08:4828 days 22 hrs ago1693328928
0xDA107A...95978C42
0 ETH
96022332023-08-29 17:08:4828 days 22 hrs ago1693328928
0xDA107A...95978C42
0 ETH
96021962023-08-29 16:58:3628 days 22 hrs ago1693328316
0xDA107A...95978C42
0 ETH
96021962023-08-29 16:58:3628 days 22 hrs ago1693328316
0xDA107A...95978C42
0 ETH
96020712023-08-29 16:23:2428 days 23 hrs ago1693326204
0xDA107A...95978C42
0 ETH
96020712023-08-29 16:23:2428 days 23 hrs ago1693326204
0xDA107A...95978C42
0 ETH
96019732023-08-29 15:58:0028 days 23 hrs ago1693324680
0xDA107A...95978C42
0 ETH
96019732023-08-29 15:58:0028 days 23 hrs ago1693324680
0xDA107A...95978C42
0 ETH
96018352023-08-29 15:24:2429 days 17 mins ago1693322664
0xDA107A...95978C42
0 ETH
96018352023-08-29 15:24:2429 days 17 mins ago1693322664
0xDA107A...95978C42
0 ETH
96018202023-08-29 15:20:2429 days 21 mins ago1693322424
0xDA107A...95978C42
0 ETH
96018202023-08-29 15:20:2429 days 21 mins ago1693322424
0xDA107A...95978C42
0 ETH
96014572023-08-29 13:48:0029 days 1 hr ago1693316880
0xDA107A...95978C42
0 ETH
96014572023-08-29 13:48:0029 days 1 hr ago1693316880
0xDA107A...95978C42
0 ETH
96013582023-08-29 13:24:2429 days 2 hrs ago1693315464
0xDA107A...95978C42
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
IdRegistry

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 4 : IdRegistry.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;

import {Context} from "openzeppelin/contracts/utils/Context.sol";
import {ERC2771Context} from "../lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol";
import {Ownable} from "openzeppelin/contracts/access/Ownable.sol";

/**
 * @title IdRegistry
 * @author @v
 * @custom:version 2.0.0
 *
 * @notice IdRegistry enables any ETH address to claim a unique Farcaster ID (fid). An address
 *         can only custody one fid at a time and may transfer it to another address. The Registry
 *         starts in a trusted mode where only a trusted caller can register an fid and can move
 *         to an untrusted mode where any address can register an fid. The Registry implements
 *         a recovery system which allows the custody address to nominate a recovery address that
 *         can transfer the fid to a new address after a delay.
 */
contract IdRegistry is ERC2771Context, Ownable {
    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /// @dev Revert when the caller does not have the authority to perform the action
    error Unauthorized();

    /// @dev Revert when the caller is required to have an fid but does not have one.
    error HasNoId();

    /// @dev Revert when the destination is required to be empty, but has an fid.
    error HasId();

    /// @dev Revert if trustedRegister is invoked after trustedCallerOnly is disabled
    error Registrable();

    /// @dev Revert if register is invoked before trustedCallerOnly is disabled
    error Invitable();

    /// @dev Revert if a recovery operation is called when there is no active recovery.
    error NoRecovery();

    /// @dev Revert when completeRecovery() is called before the escrow period has elapsed.
    error Escrow();

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev Emit an event when a new Farcaster ID is registered.
     *
     * @param to       The custody address that owns the fid
     * @param id       The fid that was registered.
     * @param recovery The address that can initiate a recovery request for the fid
     * @param url      The home url of the fid
     */
    event Register(address indexed to, uint256 indexed id, address recovery, string url);

    /**
     * @dev Emit an event when a Farcaster ID is transferred to a new custody address.
     *
     * @param from The custody address that previously owned the fid
     * @param to   The custody address that now owns the fid
     * @param id   The fid that was transferred.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    /**
     * @dev Emit an event when a Farcaster ID's home url is updated
     *
     * @param id  The fid whose home url was updated.
     * @param url The new home url.
     */
    event ChangeHome(uint256 indexed id, string url);

    /**
     * @dev Emit an event when a Farcaster ID's recovery address is updated
     *
     * @param id       The fid whose recovery address was updated.
     * @param recovery The new recovery address.
     */
    event ChangeRecoveryAddress(uint256 indexed id, address indexed recovery);

    /**
     * @dev Emit an event when a recovery request is initiated for a Farcaster Id
     *
     * @param from The custody address of the fid being recovered.
     * @param to   The destination address for the fid when the recovery is completed.
     * @param id   The id being recovered.
     */
    event RequestRecovery(address indexed from, address indexed to, uint256 indexed id);

    /**
     * @dev Emit an event when a recovery request is cancelled
     *
     * @param by  The address that cancelled the recovery request
     * @param id  The id being recovered.
     */
    event CancelRecovery(address indexed by, uint256 indexed id);

    /**
     * @dev Emit an event when the trusted caller is modified.
     *
     * @param trustedCaller The address of the new trusted caller.
     */
    event ChangeTrustedCaller(address indexed trustedCaller);

    /**
     * @dev Emit an event when the trusted only state is disabled.
     */
    event DisableTrustedOnly();

    /*//////////////////////////////////////////////////////////////
                                CONSTANTS
    //////////////////////////////////////////////////////////////*/

    uint256 private constant ESCROW_PERIOD = 3 days;

    /*//////////////////////////////////////////////////////////////
                                 STORAGE
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev The last farcaster id that was issued.
     */
    uint256 internal idCounter;

    /**
     * @dev The Farcaster Invite service address that is allowed to call trustedRegister.
     */
    address internal trustedCaller;

    /**
     * @dev The address is allowed to call _completeTransferOwnership() and become the owner. Set to
     *      address(0) when no ownership transfer is pending.
     */
    address internal pendingOwner;

    /**
     * @dev Allows calling trustedRegister() when set 0, and register() when set to 1. The value is
     *      set to 1 and can be changed to 0, but never back to 1.
     */
    uint256 internal trustedOnly = 1;

    /**
     * @notice Maps each address to a fid, or zero if it does not own a fid.
     */
    mapping(address => uint256) public idOf;

    /**
     * @dev Maps each fid to an address that can initiate a recovery.
     */
    mapping(uint256 => address) internal recoveryOf;

    /**
     * @dev Maps each fid to the timestamp at which the recovery request was started. This is set
     *      to zero when there is no active recovery.
     */
    mapping(uint256 => uint256) internal recoveryClockOf;

    /**
     * @dev Maps each fid to the destination for the last recovery attempted. This value is left
     *      dirty to save gas and a non-zero value does not indicate an active recovery.
     */
    mapping(uint256 => address) internal recoveryDestinationOf;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Set the owner of the contract to the deployer and configure the trusted forwarder.
     *
     * @param _forwarder The address of the ERC2771 forwarder contract that this contract trusts to
     *                  verify the authenticity of signed meta-transaction requests.
     */
    // solhint-disable-next-line no-empty-blocks
    constructor(address _forwarder) ERC2771Context(_forwarder) Ownable() {}

    /*//////////////////////////////////////////////////////////////
                             REGISTRATION LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Register a new, unique Farcaster ID (fid) for an address that doesn't have one. This
     *        method can be called by anyone when trustedOnly is set to 0.
     *
     * @param to       The address which will control the fid
     * @param recovery The address which can recover the fid
     * @param url      The home url for the fid's off-chain data
     */
    function register(
        address to,
        address recovery,
        string calldata url
    ) external {
        // Perf: Don't check to == address(0) to save 29 gas since 0x0 can only register 1 fid

        if (trustedOnly == 1) revert Invitable();

        _unsafeRegister(to, recovery);

        // Perf: instead of returning the id from _unsafeRegister, fetch the latest value of idCounter
        emit Register(to, idCounter, recovery, url);
    }

    /**
     * @notice Register a new unique Farcaster ID (fid) for an address that does not have one. This
     *         can only be invoked by the trusted caller when trustedOnly is set to 1.
     *
     * @param to       The address which will control the fid
     * @param recovery The address which can recover the fid
     * @param url      The home url for the fid's off-chain data
     */
    function trustedRegister(
        address to,
        address recovery,
        string calldata url
    ) external {
        // Perf: Don't check to == address(0) to save 29 gas since 0x0 can only register 1 fid

        if (trustedOnly == 0) revert Registrable();

        // Perf: Check msg.sender instead of msgSender() because saves 100 gas and trusted caller
        // doesn't need meta transactions
        if (msg.sender != trustedCaller) revert Unauthorized();

        _unsafeRegister(to, recovery);

        // Assumption: the most recent value of the idCounter must equal the id of this user
        emit Register(to, idCounter, recovery, url);
    }

    /**
     * @notice Emit an event with a new home url if the caller owns an fid. This function supports
     *         ERC 2771 meta-transactions and can be called via a relayer.
     *
     * @param url The new home url for the fid
     */
    function changeHome(string calldata url) external {
        uint256 id = idOf[_msgSender()];
        if (id == 0) revert HasNoId();

        emit ChangeHome(id, url);
    }

    /**
     * @dev Registers a new, unique fid and sets up a recovery address for a caller without
     *      checking any invariants or emitting events.
     */
    function _unsafeRegister(address to, address recovery) internal {
        // Perf: inlining this can save ~ 20-40 gas per call at the expense of readability
        if (idOf[to] != 0) revert HasId();

        unchecked {
            idCounter++;
        }

        // Incrementing before assigning ensures that 0 is never issued as a valid ID.
        idOf[to] = idCounter;
        recoveryOf[idCounter] = recovery;
    }

    /*//////////////////////////////////////////////////////////////
                             TRANSFER LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Transfer the fid owned by this address to another address that does not have an fid.
     *         Supports ERC 2771 meta-transactions and can be called via a relayer.
     *
     * @param to The address to transfer the fid to.
     */
    function transfer(address to) external {
        address sender = _msgSender();
        uint256 id = idOf[sender];

        // Ensure that the caller owns an fid and that the destination address does not.
        if (id == 0) revert HasNoId();
        if (idOf[to] != 0) revert HasId();

        _unsafeTransfer(id, sender, to);
    }

    /**
     * @dev Transfer the fid to another address, clear the recovery address and reset active
     *      recovery requests, without checking any invariants.
     */
    function _unsafeTransfer(
        uint256 id,
        address from,
        address to
    ) internal {
        idOf[to] = id;
        delete idOf[from];

        // Perf: clear any active recovery requests, but check if they exist before deleting
        // because this usually already zero
        if (recoveryClockOf[id] != 0) delete recoveryClockOf[id];
        recoveryOf[id] = address(0);

        emit Transfer(from, to, id);
    }

    /*//////////////////////////////////////////////////////////////
                             RECOVERY LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * INVARIANT 1: If msgSender() is a recovery address for another address, that address
     *              must own an fid
     *
     *  if _msgSender() == recoveryOf[idOf[addr]], then idOf[addr] != 0 during requestRecovery(),
     *  completeRecovery() and cancelRecovery()
     *
     *
     * 1. at the start, idOf[addr] = 0 && recoveryOf[idOf[addr]] == address(0) ∀ addr
     * 2. _msgSender() != address(0) ∀ _msgSender()
     * 3. recoveryOf[addr] becomes non-zero only in register(), trustedRegister() and
     *    changeRecoveryAddress(), which requires idOf[addr] != 0
     * 4. idOf[addr] becomes 0 only in transfer() and completeRecovery(), which requires
     *    recoveryOf[addr] == address(0)
     **/

    /**
     * INVARIANT 2: If an address has a non-zero recoveryClock, it must also have an fid
     *
     * if recoveryClockOf[idOf[address]] != 0 then idOf[addr] != 0
     *
     * 1. at the start, idOf[addr] = 0 and recoveryClockOf[idOf[addr]] == 0 ∀ addr
     * 2. recoveryClockOf[idOf[addr]] becomes non-zero only in requestRecovery(), which
     *    requires idOf[addr] != 0
     * 3. idOf[addr] becomes zero only in transfer() and completeRecovery(), which requires
     *    recoveryClockOf[id[addr]] == 0
     */

    /**
     * @notice Change the recovery address of the fid owned by this address and reset active
     *         recovery requests. Supports ERC 2771 meta-transactions and can be called by a
     *         relayer.
     *
     * @param recovery The address which can recover the fid (set to 0x0 to disable recovery)
     */
    function changeRecoveryAddress(address recovery) external {
        uint256 id = idOf[_msgSender()];
        if (id == 0) revert HasNoId();

        recoveryOf[id] = recovery;

        // Perf: clear any active recovery requests, but check if they exist before deleting
        // because this usually already zero
        if (recoveryClockOf[id] != 0) delete recoveryClockOf[id];

        emit ChangeRecoveryAddress(id, recovery);
    }

    /**
     * @notice Request a recovery of an fid to a new address if the caller is the recovery address.
     *         Supports ERC 2771 meta-transactions and can be called by a relayer.
     *
     * @param from The address that owns the fid
     * @param to   The address where the fid should be sent
     */
    function requestRecovery(address from, address to) external {
        uint256 id = idOf[from];
        if (_msgSender() != recoveryOf[id]) revert Unauthorized();

        // Assumption: id != 0 because of Invariant 1

        // Track when the escrow period started
        recoveryClockOf[id] = block.timestamp;

        // Store the final destination so that it cannot be modified unless completed or cancelled
        recoveryDestinationOf[id] = to;

        emit RequestRecovery(from, to, id);
    }

    /**
     * @notice Complete a recovery request and transfer the fid if the caller is the recovery
     *         address and the escrow period has passed. Supports ERC 2771 meta-transactions and
     *         can be called via a relayer.
     *
     * @param from The address that owns the id.
     */
    function completeRecovery(address from) external {
        uint256 id = idOf[from];

        if (_msgSender() != recoveryOf[id]) revert Unauthorized();

        uint256 _recoveryClock = recoveryClockOf[id];

        if (_recoveryClock == 0) revert NoRecovery();

        // Assumption: we don't need to check that the id still lives in the address because any
        // transfer would have reset this clock to zero causing a revert

        // Revert if the recovery is still in its escrow period
        unchecked {
            // Safety: rhs cannot overflow because _recoveryClock is a block.timestamp
            if (block.timestamp < _recoveryClock + ESCROW_PERIOD) revert Escrow();
        }

        address to = recoveryDestinationOf[id];
        if (idOf[to] != 0) revert HasId();

        // Assumption: id != 0 because of invariant 1 and 2 (either asserts this)
        _unsafeTransfer(id, from, to);
    }

    /**
     * @notice Cancel an active recovery request if the caller is the recovery address or the
     *         custody address. Supports ERC 2771 meta-transactions and can be called by a relayer.
     *
     * @param from The address that owns the id.
     */
    function cancelRecovery(address from) external {
        uint256 id = idOf[from];
        address sender = _msgSender();

        // Allow cancellation only if the sender is the recovery address or the custody address
        if (sender != from && sender != recoveryOf[id]) revert Unauthorized();

        // Assumption: id != 0 because of Invariant 1

        // Check if there is a recovery to avoid emitting incorrect CancelRecovery events
        if (recoveryClockOf[id] == 0) revert NoRecovery();

        // Clear the recovery request so that it cannot be completed
        delete recoveryClockOf[id];

        emit CancelRecovery(sender, id);
    }

    /*//////////////////////////////////////////////////////////////
                              OWNER ACTIONS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Change the trusted caller by calling this from the contract's owner.
     *
     * @param _trustedCaller The address of the new trusted caller
     */
    function changeTrustedCaller(address _trustedCaller) external onlyOwner {
        trustedCaller = _trustedCaller;
        emit ChangeTrustedCaller(_trustedCaller);
    }

    /**
     * @notice Disable trustedRegister() and let anyone get an fid by calling register(). This must
     *         be called by the contract's owner.
     */
    function disableTrustedOnly() external onlyOwner {
        delete trustedOnly;
        emit DisableTrustedOnly();
    }

    /**
     * @notice Override to prevent a single-step transfer of ownership
     */
    function transferOwnership(
        address /*newOwner*/
    ) public view override onlyOwner {
        revert Unauthorized();
    }

    /**
     * @notice Begin a request to transfer ownership to a new address ("pendingOwner"). This must
     *         be called by the contract's owner. A transfer request can be cancelled by calling
     *         this again with address(0).
     */
    function requestTransferOwnership(address newOwner) public onlyOwner {
        pendingOwner = newOwner;
    }

    /**
     * @notice Complete a request to transfer ownership. This must be called by the pendingOwner
     */
    function completeTransferOwnership() external {
        // Safety: burning ownership is not possible since this can never be called by address(0)

        // msg.sender is used instead of _msgSender() to keep surface area for attacks low
        if (msg.sender != pendingOwner) revert Unauthorized();

        _transferOwnership(msg.sender);
        delete pendingOwner;
    }

    /*//////////////////////////////////////////////////////////////
                         OPEN ZEPPELIN OVERRIDES
    //////////////////////////////////////////////////////////////*/

    function _msgSender() internal view override(Context, ERC2771Context) returns (address) {
        return ERC2771Context._msgSender();
    }

    function _msgData() internal view override(Context, ERC2771Context) returns (bytes calldata) {
        return ERC2771Context._msgData();
    }
}

File 2 of 4 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 3 of 4 : ERC2771Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)

pragma solidity ^0.8.9;

import "../utils/Context.sol";

/**
 * @dev Context variant with ERC2771 support.
 */
abstract contract ERC2771Context is Context {
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
    address private immutable _trustedForwarder;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor(address trustedForwarder) {
        _trustedForwarder = trustedForwarder;
    }

    function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
        return forwarder == _trustedForwarder;
    }

    function _msgSender() internal view virtual override returns (address sender) {
        if (isTrustedForwarder(msg.sender)) {
            // The assembly code is more direct than the Solidity version using `abi.decode`.
            /// @solidity memory-safe-assembly
            assembly {
                sender := shr(96, calldataload(sub(calldatasize(), 20)))
            }
        } else {
            return super._msgSender();
        }
    }

    function _msgData() internal view virtual override returns (bytes calldata) {
        if (isTrustedForwarder(msg.sender)) {
            return msg.data[:msg.data.length - 20];
        } else {
            return super._msgData();
        }
    }
}

File 4 of 4 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_forwarder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Escrow","type":"error"},{"inputs":[],"name":"HasId","type":"error"},{"inputs":[],"name":"HasNoId","type":"error"},{"inputs":[],"name":"Invitable","type":"error"},{"inputs":[],"name":"NoRecovery","type":"error"},{"inputs":[],"name":"Registrable","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CancelRecovery","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"url","type":"string"}],"name":"ChangeHome","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"recovery","type":"address"}],"name":"ChangeRecoveryAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trustedCaller","type":"address"}],"name":"ChangeTrustedCaller","type":"event"},{"anonymous":false,"inputs":[],"name":"DisableTrustedOnly","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"recovery","type":"address"},{"indexed":false,"internalType":"string","name":"url","type":"string"}],"name":"Register","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"RequestRecovery","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"cancelRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"url","type":"string"}],"name":"changeHome","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recovery","type":"address"}],"name":"changeRecoveryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"}],"name":"changeTrustedCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"completeRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"completeTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableTrustedOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"idOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"recovery","type":"address"},{"internalType":"string","name":"url","type":"string"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"requestRecovery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"requestTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"recovery","type":"address"},{"internalType":"string","name":"url","type":"string"}],"name":"trustedRegister","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405260016004553480156200001657600080fd5b506040516200139738038062001397833981016040819052620000399162000109565b6001600160a01b0381166080526200005a6200005462000061565b6200007d565b506200013b565b600062000078620000cd60201b62000cac1760201c565b905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6080516000906001600160a01b03163303620000f0575060131936013560601c90565b620000786200010560201b62000d201760201c565b3390565b6000602082840312156200011c57600080fd5b81516001600160a01b03811681146200013457600080fd5b9392505050565b6080516112396200015e600039600081816101730152610cb001526112396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80638da5cb5b116100b2578063d94fe83211610081578063f1f0b22411610066578063f1f0b2241461028a578063f2fde38b1461029d578063f480dd7e146102b057600080fd5b8063d94fe83214610249578063ede497391461027757600080fd5b80638da5cb5b146101e85780639d6fa61814610210578063aa217f2514610223578063c90db4471461023657600080fd5b8063572b6c05116100ee578063572b6c05146101635780636e9bde49146101c5578063715018a6146101cd578063881b1956146101d557600080fd5b8063052a30a3146101205780631a6952301461013557806336bacd731461014857806353f0447e1461015b575b600080fd5b61013361012e36600461106d565b6102c3565b005b6101336101433660046110ce565b6103b5565b6101336101563660046110f0565b61048e565b6101336105aa565b6101b06101713660046110ce565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405190151581526020015b60405180910390f35b61013361062e565b610133610666565b6101336101e33660046110ce565b61067a565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b61013361021e3660046110ce565b6106f1565b610133610231366004611123565b610740565b6101336102443660046110ce565b610804565b6102696102573660046110ce565b60056020526000908152604090205481565b6040519081526020016101bc565b61013361028536600461106d565b61096c565b6101336102983660046110ce565b6109a8565b6101336102ab3660046110ce565b610ae0565b6101336102be3660046110ce565b610b1a565b6004546000036102ff576040517f7cb40a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff163314610350576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61035a8484610d24565b6001548473ffffffffffffffffffffffffffffffffffffffff167f3cd6a0ffcc37406d9958e09bba79ff19d8237819eb2e1911f9edbce656499c878585856040516103a7939291906111ae565b60405180910390a350505050565b60006103bf610dec565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040812054919250819003610421576040517f210b4b2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600560205260409020541561047e576040517ff90230a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610489818385610df6565b505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600560209081526040808320548084526006909252909120549091166104cf610dec565b73ffffffffffffffffffffffffffffffffffffffff161461051c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600760209081526040808320429055600890915280822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917ffab80e8bf242ed27bf595552dfdddbdd794f201d6dfcd8df7347f82f8e1f1f9b91a4505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633146105fb576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61060433610ec8565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b610636610f3d565b600060048190556040517f03732e5295a5bd18e6ef95b03b41aa8bcadae292a7ef40468144c7a727dfa8b59190a1565b61066e610f3d565b6106786000610ec8565b565b610682610f3d565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f255ba3357fefe42b361c216b6e0bc5541f1e6ea4c6178d4a45ad8dd7ec28139d90600090a250565b6106f9610f3d565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006005600061074e610dec565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050806000036107c5576040517f210b4b2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b807f5d926244a310a9e23d7caac05945165ecf7ef6f4a47fae87eb5e8a005629fdb084846040516107f79291906111e7565b60405180910390a2505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081205490610833610dec565b90508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610898575060008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff828116911614155b156108cf576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260408120549003610916576040517fc993b99300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604080822082905551839173ffffffffffffffffffffffffffffffffffffffff8416917f6181d4215ebc71e962cc193554c17f05a825da06230fdf9ece45081f09cb206f9190a3505050565b600454600103610350576040517f40adbefd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600560006109b6610dec565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905080600003610a2d576040517f210b4b2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260066020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716179055600790915290205415610a99576000818152600760205260408120555b60405173ffffffffffffffffffffffffffffffffffffffff83169082907f8e700b803af43e14651431cd73c9fe7d11b131ad797576a70b893ce5766f65c390600090a35050565b610ae8610f3d565b6040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808216600090815260056020908152604080832054808452600690925290912054909116610b5b610dec565b73ffffffffffffffffffffffffffffffffffffffff1614610ba8576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604081205490819003610bf1576040517fc993b99300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6203f4808101421015610c30576040517f22f607f600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526008602090815260408083205473ffffffffffffffffffffffffffffffffffffffff1680845260059092529091205415610c9b576040517ff90230a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca6838583610df6565b50505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163303610d1657507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36013560601c90565b503390565b905090565b3390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526005602052604090205415610d81576040517ff90230a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff9283166000908152600560209081526040808320849055928252600690522080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b6000610d1b610cac565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152600560209081526040808320879055928516825282822082905585825260079052205415610e4b576000838152600760205260408120555b60008381526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905551849173ffffffffffffffffffffffffffffffffffffffff84811692908616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610f45610dec565b73ffffffffffffffffffffffffffffffffffffffff16610f7a60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461101f57600080fd5b919050565b60008083601f84011261103657600080fd5b50813567ffffffffffffffff81111561104e57600080fd5b60208301915083602082850101111561106657600080fd5b9250929050565b6000806000806060858703121561108357600080fd5b61108c85610ffb565b935061109a60208601610ffb565b9250604085013567ffffffffffffffff8111156110b657600080fd5b6110c287828801611024565b95989497509550505050565b6000602082840312156110e057600080fd5b6110e982610ffb565b9392505050565b6000806040838503121561110357600080fd5b61110c83610ffb565b915061111a60208401610ffb565b90509250929050565b6000806020838503121561113657600080fd5b823567ffffffffffffffff81111561114d57600080fd5b61115985828601611024565b90969095509350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006111de604083018486611165565b95945050505050565b6020815260006111fb602083018486611165565b94935050505056fea26469706673582212207d9385ab4c4d1fa6a6159e0543a8f938e3e37cbf73970869a882e93a99f82fb064736f6c634300081000330000000000000000000000007a95fa73250dc53556d264522150a940d4c50238

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061011b5760003560e01c80638da5cb5b116100b2578063d94fe83211610081578063f1f0b22411610066578063f1f0b2241461028a578063f2fde38b1461029d578063f480dd7e146102b057600080fd5b8063d94fe83214610249578063ede497391461027757600080fd5b80638da5cb5b146101e85780639d6fa61814610210578063aa217f2514610223578063c90db4471461023657600080fd5b8063572b6c05116100ee578063572b6c05146101635780636e9bde49146101c5578063715018a6146101cd578063881b1956146101d557600080fd5b8063052a30a3146101205780631a6952301461013557806336bacd731461014857806353f0447e1461015b575b600080fd5b61013361012e36600461106d565b6102c3565b005b6101336101433660046110ce565b6103b5565b6101336101563660046110f0565b61048e565b6101336105aa565b6101b06101713660046110ce565b7f0000000000000000000000007a95fa73250dc53556d264522150a940d4c5023873ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405190151581526020015b60405180910390f35b61013361062e565b610133610666565b6101336101e33660046110ce565b61067a565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b61013361021e3660046110ce565b6106f1565b610133610231366004611123565b610740565b6101336102443660046110ce565b610804565b6102696102573660046110ce565b60056020526000908152604090205481565b6040519081526020016101bc565b61013361028536600461106d565b61096c565b6101336102983660046110ce565b6109a8565b6101336102ab3660046110ce565b610ae0565b6101336102be3660046110ce565b610b1a565b6004546000036102ff576040517f7cb40a3900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff163314610350576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61035a8484610d24565b6001548473ffffffffffffffffffffffffffffffffffffffff167f3cd6a0ffcc37406d9958e09bba79ff19d8237819eb2e1911f9edbce656499c878585856040516103a7939291906111ae565b60405180910390a350505050565b60006103bf610dec565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040812054919250819003610421576040517f210b4b2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600560205260409020541561047e576040517ff90230a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610489818385610df6565b505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600560209081526040808320548084526006909252909120549091166104cf610dec565b73ffffffffffffffffffffffffffffffffffffffff161461051c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600760209081526040808320429055600890915280822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917ffab80e8bf242ed27bf595552dfdddbdd794f201d6dfcd8df7347f82f8e1f1f9b91a4505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633146105fb576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61060433610ec8565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b610636610f3d565b600060048190556040517f03732e5295a5bd18e6ef95b03b41aa8bcadae292a7ef40468144c7a727dfa8b59190a1565b61066e610f3d565b6106786000610ec8565b565b610682610f3d565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f255ba3357fefe42b361c216b6e0bc5541f1e6ea4c6178d4a45ad8dd7ec28139d90600090a250565b6106f9610f3d565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006005600061074e610dec565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050806000036107c5576040517f210b4b2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b807f5d926244a310a9e23d7caac05945165ecf7ef6f4a47fae87eb5e8a005629fdb084846040516107f79291906111e7565b60405180910390a2505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081205490610833610dec565b90508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015610898575060008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff828116911614155b156108cf576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600760205260408120549003610916576040517fc993b99300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526007602052604080822082905551839173ffffffffffffffffffffffffffffffffffffffff8416917f6181d4215ebc71e962cc193554c17f05a825da06230fdf9ece45081f09cb206f9190a3505050565b600454600103610350576040517f40adbefd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600560006109b6610dec565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905080600003610a2d576040517f210b4b2600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260066020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716179055600790915290205415610a99576000818152600760205260408120555b60405173ffffffffffffffffffffffffffffffffffffffff83169082907f8e700b803af43e14651431cd73c9fe7d11b131ad797576a70b893ce5766f65c390600090a35050565b610ae8610f3d565b6040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808216600090815260056020908152604080832054808452600690925290912054909116610b5b610dec565b73ffffffffffffffffffffffffffffffffffffffff1614610ba8576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526007602052604081205490819003610bf1576040517fc993b99300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6203f4808101421015610c30576040517f22f607f600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526008602090815260408083205473ffffffffffffffffffffffffffffffffffffffff1680845260059092529091205415610c9b576040517ff90230a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca6838583610df6565b50505050565b60007f0000000000000000000000007a95fa73250dc53556d264522150a940d4c5023873ffffffffffffffffffffffffffffffffffffffff163303610d1657507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec36013560601c90565b503390565b905090565b3390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526005602052604090205415610d81576040517ff90230a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001805481019081905573ffffffffffffffffffffffffffffffffffffffff9283166000908152600560209081526040808320849055928252600690522080547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b6000610d1b610cac565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152600560209081526040808320879055928516825282822082905585825260079052205415610e4b576000838152600760205260408120555b60008381526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905551849173ffffffffffffffffffffffffffffffffffffffff84811692908616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610f45610dec565b73ffffffffffffffffffffffffffffffffffffffff16610f7a60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461101f57600080fd5b919050565b60008083601f84011261103657600080fd5b50813567ffffffffffffffff81111561104e57600080fd5b60208301915083602082850101111561106657600080fd5b9250929050565b6000806000806060858703121561108357600080fd5b61108c85610ffb565b935061109a60208601610ffb565b9250604085013567ffffffffffffffff8111156110b657600080fd5b6110c287828801611024565b95989497509550505050565b6000602082840312156110e057600080fd5b6110e982610ffb565b9392505050565b6000806040838503121561110357600080fd5b61110c83610ffb565b915061111a60208401610ffb565b90509250929050565b6000806020838503121561113657600080fd5b823567ffffffffffffffff81111561114d57600080fd5b61115985828601611024565b90969095509350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff841681526040602082015260006111de604083018486611165565b95945050505050565b6020815260006111fb602083018486611165565b94935050505056fea26469706673582212207d9385ab4c4d1fa6a6159e0543a8f938e3e37cbf73970869a882e93a99f82fb064736f6c63430008100033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000007a95fa73250dc53556d264522150a940d4c50238

-----Decoded View---------------
Arg [0] : _forwarder (address): 0x7A95fA73250dc53556d264522150A940d4C50238

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a95fa73250dc53556d264522150a940d4c50238


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.