ETH Price: $3,104.01 (+0.72%)
 

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Score393973302025-12-13 0:00:0721 hrs ago1765584007IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000090.00120218
Set Score389440602025-12-02 12:11:0711 days ago1764677467IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000050.00122783
Set Score388897002025-12-01 5:59:0712 days ago1764568747IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00142992
Set Score388896992025-12-01 5:59:0512 days ago1764568745IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143301
Set Score388896992025-12-01 5:59:0512 days ago1764568745IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143301
Set Score388896982025-12-01 5:59:0312 days ago1764568743IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143326
Set Score388896972025-12-01 5:59:0112 days ago1764568741IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143289
Set Score388896962025-12-01 5:58:5912 days ago1764568739IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000080.0014345
Set Score388896962025-12-01 5:58:5912 days ago1764568739IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.0014345
Set Score388896942025-12-01 5:58:5512 days ago1764568735IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143641
Set Score388896932025-12-01 5:58:5312 days ago1764568733IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.0014387
Set Score388896912025-12-01 5:58:4912 days ago1764568729IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143695
Set Score388896912025-12-01 5:58:4912 days ago1764568729IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143695
Set Score388896902025-12-01 5:58:4712 days ago1764568727IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000080.00143648
Set Score388896892025-12-01 5:58:4512 days ago1764568725IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000110.00143875
Set Score388896892025-12-01 5:58:4512 days ago1764568725IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000110.00143875
Set Score388896872025-12-01 5:58:4112 days ago1764568721IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143721
Set Score388896862025-12-01 5:58:3912 days ago1764568719IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143935
Set Score388896852025-12-01 5:58:3712 days ago1764568717IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00143914
Set Score388896842025-12-01 5:58:3512 days ago1764568715IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000110.00144155
Set Score388896832025-12-01 5:58:3312 days ago1764568713IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000110.0014409
Set Score388896822025-12-01 5:58:3112 days ago1764568711IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00144423
Set Score388896812025-12-01 5:58:2912 days ago1764568709IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000080.00144357
Set Score388896802025-12-01 5:58:2712 days ago1764568707IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000110.00144282
Set Score388896792025-12-01 5:58:2512 days ago1764568705IN
0xBBFeDA7c...790B32D0B
0 ETH0.000000060.00144504
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PassportBuilderScore

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 1000 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./PassportRegistry.sol";

contract PassportBuilderScore is Ownable {
    PassportRegistry public passportRegistry;

    // Mapping to store scores for each passport ID
    mapping(uint256 => uint256) private passportScores;

    // Mapping to store timestamps of last updates for each passport ID
    mapping(uint256 => uint256) private passportLastUpdate;

    // Mapping to store trusted signers
    mapping(address => bool) public trustedSigners;

    event ScoreUpdated(uint256 indexed passportId, uint256 score, uint256 timestamp);
    event PassportRegistryChanged(address indexed oldAddress, address indexed newAddress);

    uint256 public EXPIRATION_TIME = 1 days * 90; // 90 days

    constructor(address passportRegistryAddress, address initialOwner) Ownable(initialOwner) {
        passportRegistry = PassportRegistry(passportRegistryAddress);
        trustedSigners[initialOwner] = true;
    }

    /**
     * @notice Sets the expiration time for the scores.
     * @dev Can only be called by the owner.
     * @param newExpirationTime The new expiration time in days.
     */
    function setExpirationTime(uint256 newExpirationTime) external onlyOwner {
        EXPIRATION_TIME = 1 days * newExpirationTime;
    }

    /**
     * @notice Adds the given address to the list of trusted signers.
     * @dev Can only be called by the owner.
     * @param signer The address to add to the list of trusted signers.
     */
    function addTrustedSigner(address signer) external onlyOwner {
        trustedSigners[signer] = true;
    }

    /**
     * @notice Removes the given address from the list of trusted signers.
     * @dev Can only be called by the owner.
     * @param signer The address to remove from the list of trusted signers.
     */
    function removeTrustedSigner(address signer) external onlyOwner {
        trustedSigners[signer] = false;
    }

    /**
     * @notice Sets the score for a given passport ID.
     * @dev Can only be called by the owner.
     * @param passportId The ID of the passport to set the score for.
     * @param score The score to set for the passport ID.
     */
    function setScore(uint256 passportId, uint256 score) external returns (bool) {
        require(trustedSigners[msg.sender], "Caller is not a trusted signer");
        require(passportRegistry.idPassport(passportId) != address(0), "Passport ID does not exist");
        passportScores[passportId] = score;
        passportLastUpdate[passportId] = block.timestamp;
        emit ScoreUpdated(passportId, score, block.timestamp);
        return true;
    }

    /**
     * @notice Gets the score of a given passport ID.
     * @param passportId The ID of the passport to get the score for.
     * @return The score of the given passport ID.
     */
    function getScore(uint256 passportId) public view returns (uint256) {
        uint256 lastUpdate = passportLastUpdate[passportId] == 0 ? block.timestamp : passportLastUpdate[passportId];
        require(lastUpdate + EXPIRATION_TIME >= block.timestamp, "Score is expired");
        return passportScores[passportId];
    }

    /**
     * @notice Gets the timestamp of the last update for a given passport ID.
     * @param passportId The ID of the passport to get the last update timestamp for.
     * @return The timestamp of the last update for the given passport ID.
     */
    function getLastUpdate(uint256 passportId) external view returns (uint256) {
        return passportLastUpdate[passportId];
    }

    function getLastUpdateByAddress(address wallet) external view returns (uint256) {
        return passportLastUpdate[passportRegistry.passportId(wallet)];
    }

    /**
     * @notice Gets the score of a given address.
     * @param wallet The address to get the score for.
     * @return The score of the given address.
     */
    function getScoreByAddress(address wallet) external view returns (uint256) {
        uint256 passportId = passportRegistry.passportId(wallet);
        require(passportRegistry.idPassport(passportId) != address(0), "Passport ID does not exist");

        uint256 score = getScore(passportId);
        return score;
    }

    /**
     * @notice Changes the address of the PassportRegistry contract.
     * @dev Can only be called by the owner.
     * @param newPassportRegistryAddress The address of the new PassportRegistry contract.
     */
    function setPassportRegistry(address newPassportRegistryAddress) external onlyOwner {
        require(newPassportRegistryAddress != address(0), "Invalid address");
        address oldAddress = address(passportRegistry);
        passportRegistry = PassportRegistry(newPassportRegistryAddress);
        emit PassportRegistryChanged(oldAddress, newPassportRegistryAddress);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    bool private _paused;

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract PassportRegistry is Ownable, Pausable {
    // wallet => passport id
    mapping(address => uint256) public passportId;

    // passport id => wallet
    mapping(uint256 => address) public idPassport;

    // wallet => bool
    mapping(address => bool) public walletActive;

    // id => bool
    mapping(uint256 => bool) public idActive;

    // id => source
    mapping(uint256 => string) public idSource;

    // source => # passports
    mapping(string => uint256) public sourcePassports;

    // Total number of passports created
    uint256 public totalCreates;

    // Total number of passports sequencially created
    uint256 public totalSequencialCreates;

    // Total number of passports created by admins
    uint256 public totalAdminsCreates;

    // Total number of passport transfers
    uint256 public totalPassportTransfers;

    // The next id to be issued
    uint256 private _nextSequentialPassportId;

    // Smart contract id in sequencial mode
    bool private _sequencial;

    // A new passport has been created
    event Create(address indexed wallet, uint256 passportId, string source);

    // A passport has been tranfered
    event Transfer(uint256 oldPassportId, uint256 newPassportId, address indexed oldWallet, address indexed newWallet);

    // A passport has been deactivated
    event Deactivate(address indexed wallet, uint256 passportId);

    // A passport has been activated
    event Activate(address indexed wallet, uint256 passportId);

    // Passport generation mode changed
    event PassportGenerationChanged(bool sequencial, uint256 nextSequencialPassportId);

    // Transfer request initiated
    event TransferRequested(address indexed fromWallet, address indexed toWallet, uint256 passportId);

    // Transfer request accepted
    event TransferAccepted(address indexed fromWallet, address indexed toWallet, uint256 passportId);

    // Transfer request revoked
    event TransferRevoked(address indexed wallet, uint256 passportId);

    mapping(uint256 => address) public transferRequests;

    /**
     * @dev Modifier to make a function callable only when the contract is in sequencial mode.
     *
     * Requirements:
     *
     * - The contract must be in sequencial mode.
     */
    modifier whenSequencialGeneration() {
        require(sequencial(), "Admin generation mode");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is in admin generation mode.
     *
     * Requirements:
     *
     * - The contract must be in admin generation mode.
     */
    modifier whenAdminGeneration() {
        require(!sequencial(), "Sequencial generation mode");
        _;
    }

    constructor(address initialOwner) Ownable(initialOwner) {
        _sequencial = false;
    }

    /**
     * @notice Creates a new passport with the next sequential ID.
     * @dev Can only be called when the contract is in sequential generation mode and not paused.
     * @param source The source of the passport creation.
     */
    function create(string memory source) public whenNotPaused whenSequencialGeneration {
        require(passportId[msg.sender] == 0, "Passport already exists");

        totalSequencialCreates++;

        _create(msg.sender, _nextSequentialPassportId, source);
        _nextSequentialPassportId += 1;
    }

    /**
     * @notice Creates a new passport with a specified ID for a specific wallet.
     * @dev Can only be called by the owner when the contract is in admin generation mode and not paused.
     * @param source The source of the passport creation.
     * @param wallet The address of the wallet to associate with the new passport.
     * @param id The ID to assign to the new passport.
     */
    function adminCreate(
        string memory source,
        address wallet,
        uint256 id
    ) public onlyOwner whenNotPaused whenAdminGeneration {
        require(passportId[wallet] == 0, "Passport already exists");

        totalAdminsCreates++;

        _create(wallet, id, source);
    }

    /**
     * @notice Transfers the passport ID of the msg.sender to the new wallet.
     * @dev Can only be called by the passport owner and when the contract is not paused.
     * @param newWallet The address of the new wallet to transfer the passport to.
     */
    function transfer(address newWallet) public whenNotPaused {
        uint256 id = passportId[msg.sender];
        require(newWallet != msg.sender, "You can not transfer to yourself");
        require(newWallet != address(0), "You can not transfer to zero address");
        require(id != 0, "Passport does not exist");
        require(passportId[newWallet] == 0, "Wallet passed already has a passport");
        require(transferRequests[id] == address(0), "Pending transfer already exists for this passport ID");

        transferRequests[id] = newWallet;

        emit TransferRequested(msg.sender, newWallet, id);
    }

    /**
     * @notice Accepts a pending passport transfer to the msg.sender's wallet.
     * @dev Can be called by the new wallet to accept the transfer.
     */
    function acceptTransfer(uint256 _passportId) public whenNotPaused {
        address newWallet = transferRequests[_passportId];
        require(newWallet == msg.sender, "You are not authorized to accept this transfer");

        address oldWallet = idPassport[_passportId];
        require(oldWallet != address(0), "Passport does not exist");

        passportId[oldWallet] = 0;
        passportId[newWallet] = _passportId;
        idPassport[_passportId] = newWallet;
        walletActive[oldWallet] = false;
        walletActive[newWallet] = true;
        totalPassportTransfers++;

        delete transferRequests[_passportId];

        emit TransferAccepted(oldWallet, newWallet, _passportId);
        emit Transfer(_passportId, _passportId, oldWallet, newWallet);
    }

    /**
     * @notice Revokes a pending passport transfer.
     * @dev Can only be called by the passport owner and when the contract is not paused.
     * @param _passportId The ID of the passport for which to revoke the transfer.
     */
    function revokeTransfer(uint256 _passportId) public whenNotPaused {
        address owner = idPassport[_passportId];
        require(owner == msg.sender, "You are not the owner of this passport");
        require(transferRequests[_passportId] != address(0), "No pending transfer to revoke");

        delete transferRequests[_passportId];

        emit TransferRevoked(msg.sender, _passportId);
    }

    // Admin

    /**
     * @notice Transfers the passport ID from one wallet to another.
     * @dev Can only be called by the owner (aka admin).
     * @param wallet The address of the wallet to transfer the passport from.
     * @param id The new passport ID to assign to the wallet.
     */
    function adminTransfer(address wallet, uint256 id) public onlyOwner {
        uint256 oldId = passportId[wallet];
        address idOwner = idPassport[id];
        require(oldId != 0, "Wallet does not have a passport to transfer from");
        require(idOwner == address(0), "New passport id already has a owner");

        string memory source = idSource[oldId];
        idSource[id] = source;
        idSource[oldId] = "";
        passportId[wallet] = id;
        idPassport[oldId] = address(0);
        walletActive[wallet] = true;
        idActive[id] = true;
        idActive[oldId] = false;

        totalPassportTransfers++;

        emit Transfer(oldId, id, wallet, wallet);
    }

    /**
     * @notice Activates the passport with the given passport ID.
     * @dev Can only be called by the owner when the contract is not paused.
     * @param _passportId The ID of the passport to activate.
     */
    function activate(uint256 _passportId) public whenNotPaused onlyOwner {
        address wallet = idPassport[_passportId];
        require(wallet != address(0), "Passport must exist");
        require(walletActive[wallet] == false, "Passport must be inactive");

        walletActive[wallet] = true;
        idActive[_passportId] = true;

        // emit event
        emit Activate(wallet, _passportId);
    }

    /**
     * @notice Deactivates the passport with the given passport ID.
     * @dev Can only be called by the owner when the contract is not paused.
     * @param _passportId The ID of the passport to deactivate.
     */
    function deactivate(uint256 _passportId) public whenNotPaused onlyOwner {
        address wallet = idPassport[_passportId];
        require(wallet != address(0), "Passport must exist");
        require(walletActive[wallet] == true, "Passport must be active");

        walletActive[wallet] = false;
        idActive[_passportId] = false;

        // emit event
        emit Deactivate(wallet, _passportId);
    }

    /**
     * @notice Pauses the contract, disabling future creations.
     * @dev Can only be called by the owner.
     */
    function pause() public whenNotPaused onlyOwner {
        _pause();
    }

    /**
     * @notice Enables the contract, enabling new creations.
     * @dev Can only be called by the owner.
     */
    function unpause() public whenPaused onlyOwner {
        _unpause();
    }

    /**
     * @notice Changes the contract generation mode.
     * @dev Can only be called by the owner.
     * @param sequentialFlag Set to true for sequential generation mode, false for admin generation mode.
     * @param nextSequentialPassportId The next sequential passport ID to be issued.
     */
    function setGenerationMode(bool sequentialFlag, uint256 nextSequentialPassportId) public onlyOwner {
        _sequencial = sequentialFlag;
        _nextSequentialPassportId = nextSequentialPassportId;

        emit PassportGenerationChanged(sequentialFlag, nextSequentialPassportId);
    }

    /**
     * @dev Returns true if the contract is in sequencial mode, and false otherwise.
     */
    function sequencial() public view virtual returns (bool) {
        return _sequencial;
    }

    /**
     * @dev Returns the next id to be generated.
     */
    function nextId() public view virtual returns (uint256) {
        return _nextSequentialPassportId;
    }

    // private

    /**
     * @dev Creates a new passport with the given ID for the specified wallet.
     * @param wallet The address of the wallet to associate with the new passport.
     * @param id The ID to assign to the new passport.
     * @param source The source of the passport creation.
     */
    function _create(address wallet, uint256 id, string memory source) private {
        require(idPassport[id] == address(0), "Passport id already issued");

        totalCreates++;

        idPassport[id] = wallet;
        passportId[wallet] = id;
        walletActive[wallet] = true;
        idActive[id] = true;
        idSource[id] = source;
        
        uint256 result = sourcePassports[source] + 1;
        sourcePassports[source] = result;

        emit Create(wallet, id, source);
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"passportRegistryAddress","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"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":"oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"PassportRegistryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"passportId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"score","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ScoreUpdated","type":"event"},{"inputs":[],"name":"EXPIRATION_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"addTrustedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"passportId","type":"uint256"}],"name":"getLastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getLastUpdateByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"passportId","type":"uint256"}],"name":"getScore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getScoreByAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passportRegistry","outputs":[{"internalType":"contract PassportRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"removeTrustedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newExpirationTime","type":"uint256"}],"name":"setExpirationTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPassportRegistryAddress","type":"address"}],"name":"setPassportRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"passportId","type":"uint256"},{"internalType":"uint256","name":"score","type":"uint256"}],"name":"setScore","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"trustedSigners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

60806040526276a70060055534801561001757600080fd5b50604051610b29380380610b2983398101604081905261003691610117565b806001600160a01b03811661006557604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61006e816100ab565b50600180546001600160a01b0319166001600160a01b0393841617815591166000908152600460205260409020805460ff1916909117905561014a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461011257600080fd5b919050565b6000806040838503121561012a57600080fd5b610133836100fb565b9150610141602084016100fb565b90509250929050565b6109d0806101596000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806358501f5311610097578063b276fa0a11610066578063b276fa0a146101ee578063c0cc365d14610211578063f2fde38b14610224578063f77776881461023757600080fd5b806358501f53146101a2578063715018a6146101c25780637d66527b146101ca5780638da5cb5b146101dd57600080fd5b80633fff987b116100d35780633fff987b14610148578063492cad131461015b5780634a5c7348146101865780634c58e0771461018f57600080fd5b80630e1af57b146100fa57806313c4b3181461012057806324ceaaff14610133575b600080fd5b61010d610108366004610897565b61025a565b6040519081526020015b60405180910390f35b61010d61012e3660046108c5565b6102fe565b6101466101413660046108c5565b61038a565b005b6101466101563660046108c5565b610447565b60015461016e906001600160a01b031681565b6040516001600160a01b039091168152602001610117565b61010d60055481565b61010d61019d3660046108c5565b610473565b61010d6101b0366004610897565b60009081526003602052604090205490565b6101466105c1565b6101466101d83660046108c5565b6105d5565b6000546001600160a01b031661016e565b6102016101fc3660046108e9565b6105fe565b6040519015158152602001610117565b61014661021f366004610897565b610782565b6101466102323660046108c5565b61079d565b6102016102453660046108c5565b60046020526000908152604090205460ff1681565b60008181526003602052604081205481901561028457600083815260036020526040902054610286565b425b90504260055482610297919061093a565b10156102ea5760405162461bcd60e51b815260206004820152601060248201527f53636f726520697320657870697265640000000000000000000000000000000060448201526064015b60405180910390fd5b505060009081526002602052604090205490565b600154604051631ca8b8ab60e01b81526001600160a01b038381166004830152600092600392849290911690631ca8b8ab90602401602060405180830381865afa158015610350573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610374919061094d565b8152602001908152602001600020549050919050565b6103926107f4565b6001600160a01b0381166103e85760405162461bcd60e51b815260206004820152600f60248201527f496e76616c69642061646472657373000000000000000000000000000000000060448201526064016102e1565b600180546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f202316c5d17e26ae345c94834d81088b666d9aa251023ad1fd0563826786d1f490600090a35050565b61044f6107f4565b6001600160a01b03166000908152600460205260409020805460ff19166001179055565b600154604051631ca8b8ab60e01b81526001600160a01b0383811660048301526000928392911690631ca8b8ab90602401602060405180830381865afa1580156104c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e5919061094d565b600154604051633defeee960e11b8152600481018390529192506000916001600160a01b0390911690637bdfddd290602401602060405180830381865afa158015610534573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105589190610966565b6001600160a01b0316036105ae5760405162461bcd60e51b815260206004820152601a60248201527f50617373706f727420494420646f6573206e6f7420657869737400000000000060448201526064016102e1565b60006105b98261025a565b949350505050565b6105c96107f4565b6105d3600061083a565b565b6105dd6107f4565b6001600160a01b03166000908152600460205260409020805460ff19169055565b3360009081526004602052604081205460ff1661065d5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f7420612074727573746564207369676e6572000060448201526064016102e1565b600154604051633defeee960e11b8152600481018590526000916001600160a01b031690637bdfddd290602401602060405180830381865afa1580156106a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106cb9190610966565b6001600160a01b0316036107215760405162461bcd60e51b815260206004820152601a60248201527f50617373706f727420494420646f6573206e6f7420657869737400000000000060448201526064016102e1565b60008381526002602090815260408083208590556003825291829020429081905582518581529182015284917fb2383e82269e758b9ec0fc961ac69cecc166570a12068c11b3f9cf29c8de9e88910160405180910390a25060015b92915050565b61078a6107f4565b6107978162015180610983565b60055550565b6107a56107f4565b6001600160a01b0381166107e8576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016102e1565b6107f18161083a565b50565b6000546001600160a01b031633146105d3576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016102e1565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156108a957600080fd5b5035919050565b6001600160a01b03811681146107f157600080fd5b6000602082840312156108d757600080fd5b81356108e2816108b0565b9392505050565b600080604083850312156108fc57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561077c5761077c61090b565b60006020828403121561095f57600080fd5b5051919050565b60006020828403121561097857600080fd5b81516108e2816108b0565b808202811582820484141761077c5761077c61090b56fea2646970667358221220b116ccc4829d4b93cc8a2bd132e70aa3cd2c5bb4228a1883b83ad0f698f01d6264736f6c63430008180033000000000000000000000000b477a9bd2547ad61f4ac22113172dd909e5b23310000000000000000000000003c16c7092fe83d874bc4dd52c3b51510c69f1d7b

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806358501f5311610097578063b276fa0a11610066578063b276fa0a146101ee578063c0cc365d14610211578063f2fde38b14610224578063f77776881461023757600080fd5b806358501f53146101a2578063715018a6146101c25780637d66527b146101ca5780638da5cb5b146101dd57600080fd5b80633fff987b116100d35780633fff987b14610148578063492cad131461015b5780634a5c7348146101865780634c58e0771461018f57600080fd5b80630e1af57b146100fa57806313c4b3181461012057806324ceaaff14610133575b600080fd5b61010d610108366004610897565b61025a565b6040519081526020015b60405180910390f35b61010d61012e3660046108c5565b6102fe565b6101466101413660046108c5565b61038a565b005b6101466101563660046108c5565b610447565b60015461016e906001600160a01b031681565b6040516001600160a01b039091168152602001610117565b61010d60055481565b61010d61019d3660046108c5565b610473565b61010d6101b0366004610897565b60009081526003602052604090205490565b6101466105c1565b6101466101d83660046108c5565b6105d5565b6000546001600160a01b031661016e565b6102016101fc3660046108e9565b6105fe565b6040519015158152602001610117565b61014661021f366004610897565b610782565b6101466102323660046108c5565b61079d565b6102016102453660046108c5565b60046020526000908152604090205460ff1681565b60008181526003602052604081205481901561028457600083815260036020526040902054610286565b425b90504260055482610297919061093a565b10156102ea5760405162461bcd60e51b815260206004820152601060248201527f53636f726520697320657870697265640000000000000000000000000000000060448201526064015b60405180910390fd5b505060009081526002602052604090205490565b600154604051631ca8b8ab60e01b81526001600160a01b038381166004830152600092600392849290911690631ca8b8ab90602401602060405180830381865afa158015610350573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610374919061094d565b8152602001908152602001600020549050919050565b6103926107f4565b6001600160a01b0381166103e85760405162461bcd60e51b815260206004820152600f60248201527f496e76616c69642061646472657373000000000000000000000000000000000060448201526064016102e1565b600180546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f202316c5d17e26ae345c94834d81088b666d9aa251023ad1fd0563826786d1f490600090a35050565b61044f6107f4565b6001600160a01b03166000908152600460205260409020805460ff19166001179055565b600154604051631ca8b8ab60e01b81526001600160a01b0383811660048301526000928392911690631ca8b8ab90602401602060405180830381865afa1580156104c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e5919061094d565b600154604051633defeee960e11b8152600481018390529192506000916001600160a01b0390911690637bdfddd290602401602060405180830381865afa158015610534573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105589190610966565b6001600160a01b0316036105ae5760405162461bcd60e51b815260206004820152601a60248201527f50617373706f727420494420646f6573206e6f7420657869737400000000000060448201526064016102e1565b60006105b98261025a565b949350505050565b6105c96107f4565b6105d3600061083a565b565b6105dd6107f4565b6001600160a01b03166000908152600460205260409020805460ff19169055565b3360009081526004602052604081205460ff1661065d5760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f7420612074727573746564207369676e6572000060448201526064016102e1565b600154604051633defeee960e11b8152600481018590526000916001600160a01b031690637bdfddd290602401602060405180830381865afa1580156106a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106cb9190610966565b6001600160a01b0316036107215760405162461bcd60e51b815260206004820152601a60248201527f50617373706f727420494420646f6573206e6f7420657869737400000000000060448201526064016102e1565b60008381526002602090815260408083208590556003825291829020429081905582518581529182015284917fb2383e82269e758b9ec0fc961ac69cecc166570a12068c11b3f9cf29c8de9e88910160405180910390a25060015b92915050565b61078a6107f4565b6107978162015180610983565b60055550565b6107a56107f4565b6001600160a01b0381166107e8576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016102e1565b6107f18161083a565b50565b6000546001600160a01b031633146105d3576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016102e1565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156108a957600080fd5b5035919050565b6001600160a01b03811681146107f157600080fd5b6000602082840312156108d757600080fd5b81356108e2816108b0565b9392505050565b600080604083850312156108fc57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561077c5761077c61090b565b60006020828403121561095f57600080fd5b5051919050565b60006020828403121561097857600080fd5b81516108e2816108b0565b808202811582820484141761077c5761077c61090b56fea2646970667358221220b116ccc4829d4b93cc8a2bd132e70aa3cd2c5bb4228a1883b83ad0f698f01d6264736f6c63430008180033

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

000000000000000000000000b477a9bd2547ad61f4ac22113172dd909e5b23310000000000000000000000003c16c7092fe83d874bc4dd52c3b51510c69f1d7b

-----Decoded View---------------
Arg [0] : passportRegistryAddress (address): 0xb477A9BD2547ad61f4Ac22113172Dd909E5B2331
Arg [1] : initialOwner (address): 0x3C16C7092FE83d874BC4dd52c3b51510C69F1D7b

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b477a9bd2547ad61f4ac22113172dd909e5b2331
Arg [1] : 0000000000000000000000003c16c7092fe83d874bc4dd52c3b51510c69f1d7b


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.