ETH Price: $2,430.69 (-9.58%)

Contract

0xBb7e1D6Cb6F243D6bdE81CE92a9f2aFF7Fbe7eac

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Transaction Hash
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GnosisSafeSameAddressMultisig

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 750 runs

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

// Gnosis Safe Master Copy interface extracted from the mainnet: https://etherscan.io/address/0xd9db270c1b5e3bd161e8c8503c55ceabee709552#code#F6#L126
interface IGnosisSafe {
    /// @dev Gets set of owners.
    /// @return Set of Safe owners.
    function getOwners() external view returns (address[] memory);

    /// @dev Gets threshold.
    /// @return Threshold
    function getThreshold() external view returns (uint256);
}

/// @dev Zero value when it has to be different from zero.
error ZeroValue();

/// @dev Provided zero address.
error ZeroAddress();

/// @dev Multisig proxy bytecode is not whitelisted.
/// @param multisig Address of a multisig proxy.
error UnauthorizedMultisig(address multisig);

/// @dev Provided incorrect data length.
/// @param expected Expected minimum data length.
/// @param provided Provided data length.
error IncorrectDataLength(uint256 expected, uint256 provided);

/// @dev Provided incorrect multisig threshold.
/// @param expected Expected threshold.
/// @param provided Provided threshold.
error WrongThreshold(uint256 expected, uint256 provided);

/// @dev Provided incorrect number of owners.
/// @param expected Expected number of owners.
/// @param provided Provided number of owners.
error WrongNumOwners(uint256 expected, uint256 provided);

/// @dev Provided incorrect multisig owner.
/// @param provided Provided owner address.
error WrongOwner(address provided);

/// @dev Multisig transaction resulted in a failure.
/// @param provided Provided multisig address.
error MultisigExecFailed(address provided);

/// @title Gnosis Safe Same Address - Smart contract for Gnosis Safe verification of an already existent multisig address.
/// @author Aleksandr Kuperman - <[email protected]>
contract GnosisSafeSameAddressMultisig {
    // Default data size to be parsed as an address of a Gnosis Safe multisig proxy address
    // This exact size suggests that all the changes to the multisig have been performed and only validation is needed
    uint256 public constant DEFAULT_DATA_LENGTH = 20;

    // Approved multisig proxy hash
    bytes32 public immutable proxyHash;

    /// @dev GnosisSafeSameAddressMultisig constructor.
    /// @param _proxyHash Approved multisig proxy hash.
    constructor(bytes32 _proxyHash) {
        if (_proxyHash == bytes32(0)) {
            revert ZeroValue();
        }

        // Record provided multisig proxy bytecode hash
        proxyHash = _proxyHash;
    }

    /// @dev Updates and/or verifies the existent gnosis safe multisig for changed owners and threshold.
    /// @notice This function operates with existent multisig proxy that is requested to be updated in terms of
    ///         the set of owners' addresses and the threshold. There are two scenarios possible:
    ///         1. The multisig proxy is already updated before reaching this function. Then the multisig address
    ///            must be passed as a payload such that its owners and threshold are verified against those specified
    ///            in the argument list.
    ///         2. The multisig proxy is not yet updated. Then the multisig address must be passed in a packed bytes of
    ///            data along with the Gnosis Safe `execTransaction()` function arguments packed payload. That payload
    ///            is going to modify the mulsisig proxy as per its signed transaction. At the end, the updated multisig
    ///            proxy is going to be verified with the provided set of owners' addresses and the threshold.
    ///         Note that owners' addresses in the multisig are stored in reverse order compared to how they were added:
    ///         https://etherscan.io/address/0xd9db270c1b5e3bd161e8c8503c55ceabee709552#code#F6#L56
    /// @param owners Set of updated multisig owners to verify against.
    /// @param threshold Updated number for multisig transaction confirmations.
    /// @param data Packed data containing address of an existent gnosis safe multisig and a payload to call the multisig with.
    /// @return multisig Address of a multisig (proxy).
    function create(
        address[] memory owners,
        uint256 threshold,
        bytes memory data
    ) external returns (address multisig)
    {
        // Check for the correct data length
        uint256 dataLength = data.length;
        if (dataLength < DEFAULT_DATA_LENGTH) {
            revert IncorrectDataLength(DEFAULT_DATA_LENGTH, data.length);
        }

        // Read the proxy multisig address (20 bytes) and the multisig-related data
        assembly {
            multisig := mload(add(data, DEFAULT_DATA_LENGTH))
        }

        // Check that the multisig address corresponds to the authorized multisig proxy bytecode hash
        bytes32 multisigProxyHash = keccak256(multisig.code);
        if (proxyHash != multisigProxyHash) {
            revert UnauthorizedMultisig(multisig);
        }

        // If provided, read the payload that is going to change the multisig ownership and threshold
        // The payload is expected to be the `execTransaction()` function call with all its arguments and signature(s)
        if (dataLength > DEFAULT_DATA_LENGTH) {
            uint256 payloadLength = dataLength - DEFAULT_DATA_LENGTH;
            bytes memory payload = new bytes(payloadLength);
            for (uint256 i = 0; i < payloadLength; ++i) {
                payload[i] = data[i + DEFAULT_DATA_LENGTH];
            }

            // Call the multisig with the provided payload
            (bool success, ) = multisig.call(payload);
            if (!success) {
                revert MultisigExecFailed(multisig);
            }
        }

        // Get the provided proxy multisig owners and threshold
        address[] memory checkOwners = IGnosisSafe(multisig).getOwners();
        uint256 checkThreshold = IGnosisSafe(multisig).getThreshold();

        // Verify updated multisig proxy for provided owners and threshold
        if (threshold != checkThreshold) {
            revert WrongThreshold(checkThreshold, threshold);
        }
        uint256 numOwners = owners.length;
        if (numOwners != checkOwners.length) {
            revert WrongNumOwners(checkOwners.length, numOwners);
        }
        // The owners' addresses in the multisig itself are stored in reverse order compared to how they were added:
        // https://etherscan.io/address/0xd9db270c1b5e3bd161e8c8503c55ceabee709552#code#F6#L56
        // Thus, the check must be carried out accordingly.
        for (uint256 i = 0; i < numOwners; ++i) {
            if (owners[i] != checkOwners[numOwners - i - 1]) {
                revert WrongOwner(owners[i]);
            }
        }
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"bytes32","name":"_proxyHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"provided","type":"uint256"}],"name":"IncorrectDataLength","type":"error"},{"inputs":[{"internalType":"address","name":"provided","type":"address"}],"name":"MultisigExecFailed","type":"error"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"name":"UnauthorizedMultisig","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"provided","type":"uint256"}],"name":"WrongNumOwners","type":"error"},{"inputs":[{"internalType":"address","name":"provided","type":"address"}],"name":"WrongOwner","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"provided","type":"uint256"}],"name":"WrongThreshold","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"inputs":[],"name":"DEFAULT_DATA_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"create","outputs":[{"internalType":"address","name":"multisig","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxyHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]

60a060405234801561001057600080fd5b5060405161088638038061088683398101604081905261002f91610055565b8061004d57604051637c946ed760e01b815260040160405180910390fd5b60805261006e565b60006020828403121561006757600080fd5b5051919050565b6080516107f761008f60003960008181604b015261012701526107f76000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063809cee2f14610046578063f02fb77414610080578063f398dba814610088575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61006d601481565b61009b6100963660046105b7565b6100b3565b6040516001600160a01b039091168152602001610077565b805160009060148110156100ec578251604051631a64813d60e11b81526014600482015260248101919091526044015b60405180910390fd5b601483015191506000826001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461016e5760405162a2307960e51b81526001600160a01b03841660048201526024016100e3565b60148211156102d757600061018460148461069d565b905060008167ffffffffffffffff8111156101a1576101a16104c4565b6040519080825280601f01601f1916602001820160405280156101cb576020820181803683370190505b50905060005b8281101561024957866101e56014836106b6565b815181106101f5576101f56106c9565b602001015160f81c60f81b828281518110610212576102126106c9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016101d1565b506000856001600160a01b03168260405161026491906106df565b6000604051808303816000865af19150503d80600081146102a1576040519150601f19603f3d011682016040523d82523d6000602084013e6102a6565b606091505b50509050806102d357604051632aacb4bd60e21b81526001600160a01b03871660048201526024016100e3565b5050505b6000836001600160a01b031663a0e67e2b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610317573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261033f919081019061070e565b90506000846001600160a01b031663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a591906107a8565b90508087146103d157604051635372461560e01b815260048101829052602481018890526044016100e3565b87518251811461040157825160405163f720290d60e01b81526004810191909152602481018290526044016100e3565b60005b818110156104b757836001610419838561069d565b610423919061069d565b81518110610433576104336106c9565b60200260200101516001600160a01b03168a8281518110610456576104566106c9565b60200260200101516001600160a01b0316146104af5789818151811061047e5761047e6106c9565b60200260200101516040516374dba67360e01b81526004016100e391906001600160a01b0391909116815260200190565b600101610404565b5050505050509392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610503576105036104c4565b604052919050565b600067ffffffffffffffff821115610525576105256104c4565b5060051b60200190565b6001600160a01b038116811461054457600080fd5b50565b600082601f83011261055857600080fd5b813567ffffffffffffffff811115610572576105726104c4565b610585601f8201601f19166020016104da565b81815284602083860101111561059a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156105cc57600080fd5b833567ffffffffffffffff808211156105e457600080fd5b818601915086601f8301126105f857600080fd5b8135602061060d6106088361050b565b6104da565b82815260059290921b8401810191818101908a84111561062c57600080fd5b948201945b838610156106535785356106448161052f565b82529482019490820190610631565b975050870135945050604086013591508082111561067057600080fd5b5061067d86828701610547565b9150509250925092565b634e487b7160e01b600052601160045260246000fd5b818103818111156106b0576106b0610687565b92915050565b808201808211156106b0576106b0610687565b634e487b7160e01b600052603260045260246000fd5b6000825160005b8181101561070057602081860181015185830152016106e6565b506000920191825250919050565b6000602080838503121561072157600080fd5b825167ffffffffffffffff81111561073857600080fd5b8301601f8101851361074957600080fd5b80516107576106088261050b565b81815260059190911b8201830190838101908783111561077657600080fd5b928401925b8284101561079d57835161078e8161052f565b8252928401929084019061077b565b979650505050505050565b6000602082840312156107ba57600080fd5b505191905056fea264697066735822122061c526595d40f3df0151de1eb5662587584ac2b55b8ca9a13ed4eff77e32e72f64736f6c63430008170033b89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063809cee2f14610046578063f02fb77414610080578063f398dba814610088575b600080fd5b61006d7fb89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b00081565b6040519081526020015b60405180910390f35b61006d601481565b61009b6100963660046105b7565b6100b3565b6040516001600160a01b039091168152602001610077565b805160009060148110156100ec578251604051631a64813d60e11b81526014600482015260248101919091526044015b60405180910390fd5b601483015191506000826001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807fb89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b0001461016e5760405162a2307960e51b81526001600160a01b03841660048201526024016100e3565b60148211156102d757600061018460148461069d565b905060008167ffffffffffffffff8111156101a1576101a16104c4565b6040519080825280601f01601f1916602001820160405280156101cb576020820181803683370190505b50905060005b8281101561024957866101e56014836106b6565b815181106101f5576101f56106c9565b602001015160f81c60f81b828281518110610212576102126106c9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016101d1565b506000856001600160a01b03168260405161026491906106df565b6000604051808303816000865af19150503d80600081146102a1576040519150601f19603f3d011682016040523d82523d6000602084013e6102a6565b606091505b50509050806102d357604051632aacb4bd60e21b81526001600160a01b03871660048201526024016100e3565b5050505b6000836001600160a01b031663a0e67e2b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610317573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261033f919081019061070e565b90506000846001600160a01b031663e75235b86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610381573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a591906107a8565b90508087146103d157604051635372461560e01b815260048101829052602481018890526044016100e3565b87518251811461040157825160405163f720290d60e01b81526004810191909152602481018290526044016100e3565b60005b818110156104b757836001610419838561069d565b610423919061069d565b81518110610433576104336106c9565b60200260200101516001600160a01b03168a8281518110610456576104566106c9565b60200260200101516001600160a01b0316146104af5789818151811061047e5761047e6106c9565b60200260200101516040516374dba67360e01b81526004016100e391906001600160a01b0391909116815260200190565b600101610404565b5050505050509392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610503576105036104c4565b604052919050565b600067ffffffffffffffff821115610525576105256104c4565b5060051b60200190565b6001600160a01b038116811461054457600080fd5b50565b600082601f83011261055857600080fd5b813567ffffffffffffffff811115610572576105726104c4565b610585601f8201601f19166020016104da565b81815284602083860101111561059a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000606084860312156105cc57600080fd5b833567ffffffffffffffff808211156105e457600080fd5b818601915086601f8301126105f857600080fd5b8135602061060d6106088361050b565b6104da565b82815260059290921b8401810191818101908a84111561062c57600080fd5b948201945b838610156106535785356106448161052f565b82529482019490820190610631565b975050870135945050604086013591508082111561067057600080fd5b5061067d86828701610547565b9150509250925092565b634e487b7160e01b600052601160045260246000fd5b818103818111156106b0576106b0610687565b92915050565b808201808211156106b0576106b0610687565b634e487b7160e01b600052603260045260246000fd5b6000825160005b8181101561070057602081860181015185830152016106e6565b506000920191825250919050565b6000602080838503121561072157600080fd5b825167ffffffffffffffff81111561073857600080fd5b8301601f8101851361074957600080fd5b80516107576106088261050b565b81815260059190911b8201830190838101908783111561077657600080fd5b928401925b8284101561079d57835161078e8161052f565b8252928401929084019061077b565b979650505050505050565b6000602082840312156107ba57600080fd5b505191905056fea264697066735822122061c526595d40f3df0151de1eb5662587584ac2b55b8ca9a13ed4eff77e32e72f64736f6c63430008170033

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

b89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b000

-----Decoded View---------------
Arg [0] : _proxyHash (bytes32): 0xb89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b000

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


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

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.