ETH Price: $3,410.41 (-1.00%)
Gas: 2 Gwei

Contract

0x536384FCd25b576265B6775F383D5ac408FF9dB7
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Create Counterfa...202196582024-07-02 15:14:5910 hrs ago1719933299IN
Argent: Wallet Factory
0 ETH0.002587478.24591683
Create Counterfa...202153142024-07-02 0:40:3525 hrs ago1719880835IN
Argent: Wallet Factory
0 ETH0.000629021.781
Create Counterfa...202148862024-07-01 23:14:4726 hrs ago1719875687IN
Argent: Wallet Factory
0 ETH0.000712.11
Create Counterfa...202068532024-06-30 20:20:352 days ago1719778835IN
Argent: Wallet Factory
0 ETH0.001548334.601
Create Counterfa...202065432024-06-30 19:18:352 days ago1719775115IN
Argent: Wallet Factory
0 ETH0.001126513.18959564
Create Counterfa...202061852024-06-30 18:06:472 days ago1719770807IN
Argent: Wallet Factory
0 ETH0.00090592.69197622
Create Counterfa...202055502024-06-30 15:58:592 days ago1719763139IN
Argent: Wallet Factory
0 ETH0.001267463.76652625
Create Counterfa...202040222024-06-30 10:51:352 days ago1719744695IN
Argent: Wallet Factory
0 ETH0.000760872.261
Create Counterfa...202033292024-06-30 8:32:352 days ago1719736355IN
Argent: Wallet Factory
0 ETH0.000634162.021
Create Counterfa...202014462024-06-30 2:13:472 days ago1719713627IN
Argent: Wallet Factory
0 ETH0.000494711.47
Create Counterfa...201994642024-06-29 19:35:113 days ago1719689711IN
Argent: Wallet Factory
0 ETH0.000497511.58550841
Create Counterfa...201985702024-06-29 16:35:353 days ago1719678935IN
Argent: Wallet Factory
0 ETH0.000686812.041
Create Counterfa...201985222024-06-29 16:25:593 days ago1719678359IN
Argent: Wallet Factory
0 ETH0.000614231.73618887
Create Counterfa...201979462024-06-29 14:30:233 days ago1719671423IN
Argent: Wallet Factory
0 ETH0.001282163.81018977
Create Counterfa...201965772024-06-29 9:54:233 days ago1719654863IN
Argent: Wallet Factory
0 ETH0.000613021.82170923
Create Counterfa...201965312024-06-29 9:44:593 days ago1719654299IN
Argent: Wallet Factory
0 ETH0.0005321.581
Create Counterfa...201922822024-06-28 19:29:474 days ago1719602987IN
Argent: Wallet Factory
0 ETH0.000834482.47971196
Create Counterfa...201918982024-06-28 18:12:594 days ago1719598379IN
Argent: Wallet Factory
0 ETH0.001524954.86
Create Counterfa...201917502024-06-28 17:42:594 days ago1719596579IN
Argent: Wallet Factory
0 ETH0.00102943.05881133
Create Counterfa...201913042024-06-28 16:12:594 days ago1719591179IN
Argent: Wallet Factory
0 ETH0.002334616.938
Create Counterfa...201911092024-06-28 15:33:474 days ago1719588827IN
Argent: Wallet Factory
0 ETH0.00300618.93274554
Create Counterfa...201814982024-06-27 7:21:355 days ago1719472895IN
Argent: Wallet Factory
0 ETH0.001246673.7045934
Create Counterfa...201752372024-06-26 10:22:356 days ago1719397355IN
Argent: Wallet Factory
0 ETH0.00097182.88779055
Create Counterfa...201716012024-06-25 22:12:117 days ago1719353531IN
Argent: Wallet Factory
0 ETH0.001046473.10954233
Create Counterfa...201694372024-06-25 14:56:597 days ago1719327419IN
Argent: Wallet Factory
0 ETH0.0037458711.13117962
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
202196582024-07-02 15:14:5910 hrs ago1719933299
Argent: Wallet Factory
 Contract Creation0 ETH
202153142024-07-02 0:40:3525 hrs ago1719880835
Argent: Wallet Factory
 Contract Creation0 ETH
202148862024-07-01 23:14:4726 hrs ago1719875687
Argent: Wallet Factory
 Contract Creation0 ETH
202068532024-06-30 20:20:352 days ago1719778835
Argent: Wallet Factory
 Contract Creation0 ETH
202065432024-06-30 19:18:352 days ago1719775115
Argent: Wallet Factory
 Contract Creation0 ETH
202061852024-06-30 18:06:472 days ago1719770807
Argent: Wallet Factory
 Contract Creation0 ETH
202055502024-06-30 15:58:592 days ago1719763139
Argent: Wallet Factory
 Contract Creation0 ETH
202040222024-06-30 10:51:352 days ago1719744695
Argent: Wallet Factory
 Contract Creation0 ETH
202033292024-06-30 8:32:352 days ago1719736355
Argent: Wallet Factory
 Contract Creation0 ETH
202014462024-06-30 2:13:472 days ago1719713627
Argent: Wallet Factory
 Contract Creation0 ETH
201994642024-06-29 19:35:113 days ago1719689711
Argent: Wallet Factory
 Contract Creation0 ETH
201985702024-06-29 16:35:353 days ago1719678935
Argent: Wallet Factory
 Contract Creation0 ETH
201985222024-06-29 16:25:593 days ago1719678359
Argent: Wallet Factory
 Contract Creation0 ETH
201979462024-06-29 14:30:233 days ago1719671423
Argent: Wallet Factory
 Contract Creation0 ETH
201965772024-06-29 9:54:233 days ago1719654863
Argent: Wallet Factory
 Contract Creation0 ETH
201965312024-06-29 9:44:593 days ago1719654299
Argent: Wallet Factory
 Contract Creation0 ETH
201922822024-06-28 19:29:474 days ago1719602987
Argent: Wallet Factory
 Contract Creation0 ETH
201918982024-06-28 18:12:594 days ago1719598379
Argent: Wallet Factory
 Contract Creation0 ETH
201917502024-06-28 17:42:594 days ago1719596579
Argent: Wallet Factory
 Contract Creation0 ETH
201913042024-06-28 16:12:594 days ago1719591179
Argent: Wallet Factory
 Contract Creation0 ETH
201911092024-06-28 15:33:474 days ago1719588827
Argent: Wallet Factory
 Contract Creation0 ETH
201814982024-06-27 7:21:355 days ago1719472895
Argent: Wallet Factory
 Contract Creation0 ETH
201752372024-06-26 10:22:356 days ago1719397355
Argent: Wallet Factory
 Contract Creation0 ETH
201716012024-06-25 22:12:117 days ago1719353531
Argent: Wallet Factory
 Contract Creation0 ETH
201694372024-06-25 14:56:597 days ago1719327419
Argent: Wallet Factory
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WalletFactory

Compiler Version
v0.8.3+commit.8d00100c

Optimization Enabled:
Yes with 999 runs

Other Settings:
default evmVersion
File 1 of 9 : WalletFactory.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.3;

import "../wallet/Proxy.sol";
import "../wallet/BaseWallet.sol";
import "./base/Managed.sol";
import "./storage/IGuardianStorage.sol";
import "../modules/common/Utils.sol";

/**
 * @title WalletFactory
 * @notice The WalletFactory contract creates and assigns wallets to accounts.
 * @author Julien Niset, Olivier VDB - <[email protected]>, <[email protected]>
 */
contract WalletFactory is Managed {

    address constant internal ETH_TOKEN = address(0);

    // The address of the base wallet implementation
    address immutable public walletImplementation;
    // The address of the GuardianStorage
    address immutable public guardianStorage;
    // The recipient of the refund
    address public refundAddress; 

    // *************** Events *************************** //

    event RefundAddressChanged(address addr);
    event WalletCreated(address indexed wallet, address indexed owner, address indexed guardian, address refundToken, uint256 refundAmount);

    // *************** Constructor ********************** //

    /**
     * @notice Default constructor.
     */
    constructor(address _walletImplementation, address _guardianStorage, address _refundAddress) {
        require(_walletImplementation != address(0), "WF: empty wallet implementation");
        require(_guardianStorage != address(0), "WF: empty guardian storage");
        require(_refundAddress != address(0), "WF: empty refund address");
        walletImplementation = _walletImplementation;
        guardianStorage = _guardianStorage;
        refundAddress = _refundAddress;
    }

    // *************** External Functions ********************* //

    /**
    * @notice Disables the ability for the owner of the factory to revoke a manager.
    */
    function revokeManager(address /*_manager*/) override external pure {
        revert("WF: managers can't be revoked");
    }
     
    /**
     * @notice Creates a wallet for an owner account at a specific address.
     * The wallet is initialised with the target modules and a first guardian by default.
     * The wallet is created using the CREATE2 opcode and must have been approved 
     * by a manager of the factory.
     * @param _owner The account address.
     * @param _modules The list of modules for the wallet.
     * @param _guardian The guardian address.
     * @param _salt The salt.
     * @param _refundAmount The amount to refund to the relayer.
     * @param _refundToken The token to use to refund the relayer.
     * @param _ownerSignature The owner signature on the refund info.
     * @param _managerSignature The manager signature on the wallet address.
     */
    function createCounterfactualWallet(
        address _owner,
        address[] calldata _modules,
        address _guardian,
        bytes20 _salt,
        uint256 _refundAmount,
        address _refundToken,
        bytes calldata _ownerSignature,
        bytes calldata _managerSignature
    )
        external
        returns (address _wallet)
    {
        validateInputs(_owner, _modules, _guardian);
        bytes32 newsalt = newSalt(_salt, _owner, _modules, _guardian);
        address payable wallet = payable(new Proxy{salt: newsalt}(walletImplementation));
        validateAuthorisedCreation(wallet, _managerSignature);
        configureWallet(BaseWallet(wallet), _owner, _modules, _guardian);
        if (_refundAmount > 0 && _ownerSignature.length == 65) {
            validateAndRefund(wallet, _owner, _refundAmount, _refundToken, _ownerSignature);
        }
        // remove the factory from the authorised modules
        BaseWallet(wallet).authoriseModule(address(this), false);

        // emit event
        emit WalletCreated(wallet, _owner, _guardian, _refundToken, _refundAmount);

        return wallet;
    }

    /**
     * @notice Gets the address of a counterfactual wallet with a first default guardian.
     * @param _owner The account address.
     * @param _modules The list of modules for wallet.
     * @param _guardian The guardian address.
     * @param _salt The salt.
     * @return _wallet The address that the wallet will have when created using CREATE2 and the same input parameters.
     */
    function getAddressForCounterfactualWallet(
        address _owner,
        address[] calldata _modules,
        address _guardian,
        bytes20 _salt
    )
        external
        view
        returns (address _wallet)
    {
        validateInputs(_owner, _modules, _guardian);
        bytes32 newsalt = newSalt(_salt, _owner, _modules, _guardian);
        bytes memory code = abi.encodePacked(type(Proxy).creationCode, uint256(uint160(walletImplementation)));
        bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), newsalt, keccak256(code)));
        _wallet = address(uint160(uint256(hash)));
    }

    /**
     * @notice Lets the owner of the factory change the refund address.
     * @param _refundAddress The address to use for refunds.
     */
    function changeRefundAddress(address _refundAddress) external onlyOwner {
        require(_refundAddress != address(0), "WF: cannot set to empty");
        refundAddress = _refundAddress;
        emit RefundAddressChanged(_refundAddress);
    }

    /**
     * @notice Required to make the factory a module during the 
     * initialisation of the wallet. 
     * @param _wallet The wallet.
     */
    function init(BaseWallet _wallet) external pure {
        //do nothing
    }

    // *************** Internal Functions ********************* //

    /**
     * @notice Helper method to configure a wallet for a set of input parameters.
     * @param _wallet The target wallet
     * @param _owner The owner address.
     * @param _modules The list of modules.
     * @param _guardian The guardian.
     */
    function configureWallet(BaseWallet _wallet, address _owner, address[] calldata _modules, address _guardian) internal {
        // add the factory to modules so it can add the first guardian and trigger the refund
        address[] memory extendedModules = new address[](_modules.length + 1);
        extendedModules[0] = address(this);
        for (uint i = 0; i < _modules.length; i++) {
            extendedModules[i + 1] = _modules[i];
        }

        // initialise the wallet with the owner and the extended modules
        _wallet.init(_owner, extendedModules);

        // add the first guardian
        IGuardianStorage(guardianStorage).addGuardian(address(_wallet), _guardian);
    }

    /**
     * @notice Generates a new salt based on a provided salt, an owner, a list of modules and an optional guardian.
     * The extra parameters are pre-hashed to be compatible with zk-sync CREATE2 API (!! the order of the parameters 
     * assumes https://github.com/matter-labs/zksync/pull/259 has been merged !!).
     * @param _salt The salt provided. In practice the hash of the L2 public key.
     * @param _owner The owner address.
     * @param _modules The list of modules for wallet.
     * @param _guardian The guardian address.
     */
    function newSalt(bytes20 _salt, address _owner, address[] calldata _modules, address _guardian) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(keccak256(abi.encodePacked(_owner, _modules, _guardian)), _salt));
    }

    /**
     * @notice Throws if the owner, guardian, or module array is invalid.
     * @param _owner The owner address.
     * @param _modules The list of modules for the wallet.
     * @param _guardian The guardian address.
     */
    function validateInputs(address _owner, address[] calldata _modules, address _guardian) internal pure {
        require(_owner != address(0), "WF: empty owner address");
        require(_owner != _guardian, "WF: owner cannot be guardian");
        require(_modules.length > 0, "WF: empty modules");
        require(_guardian != (address(0)), "WF: empty guardian");        
    }

    /**
     * @notice Throws if the sender is not a manager and the manager's signature for the
     * creation of the new wallet is invalid.
     * @param _wallet The wallet address
     * @param _managerSignature The manager's signature
     */
    function validateAuthorisedCreation(address _wallet, bytes memory _managerSignature) internal view {
        address manager;
        if(_managerSignature.length != 65) {
            manager = msg.sender;
        } else {
            bytes32 signedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", bytes32(uint256(uint160(_wallet)))));
            manager = Utils.recoverSigner(signedHash, _managerSignature, 0);
        }
        require(managers[manager], "WF: unauthorised wallet creation");
    }

    /**
     * @notice Refunds the creation of the wallet when provided with a valid signature from the wallet owner.
     * @param _wallet The wallet created
     * @param _owner The owner address
     * @param _refundAmount The amount to refund
     * @param _refundToken The token to use for the refund
     * @param _ownerSignature A signature from the wallet owner approving the refund amount and token. 
     */
    function validateAndRefund(
        address _wallet,
        address _owner,
        uint256 _refundAmount,
        address _refundToken,
        bytes memory _ownerSignature
    )
        internal
    {
        bytes32 signedHash = keccak256(abi.encodePacked(
                "\x19Ethereum Signed Message:\n32",
                keccak256(abi.encodePacked(_wallet, _refundAmount, _refundToken))
            ));
        address signer = Utils.recoverSigner(signedHash, _ownerSignature, 0);
        if (signer == _owner) {
            if (_refundToken == ETH_TOKEN) {
                invokeWallet(_wallet, refundAddress, _refundAmount, "");
            } else {
                bytes memory methodData = abi.encodeWithSignature("transfer(address,uint256)", refundAddress, _refundAmount);
                bytes memory transferSuccessBytes = invokeWallet(_wallet, _refundToken, 0, methodData);
                if (transferSuccessBytes.length > 0) {
                    require(abi.decode(transferSuccessBytes, (bool)), "WF: Refund transfer failed");
                }
            }
        }
    }

    /**
     * @notice Invoke the wallet to execute the refund transfer.
     * @param _wallet The wallet
     * @param _to The destination of the call
     * @param _value The value of the call
     * @param _data The data associated to the call
     */
    function invokeWallet(
        address _wallet,
        address _to,
        uint256 _value,
        bytes memory _data
    )
        internal
        returns (bytes memory _res)
    {
        bool success;
        (success, _res) = _wallet.call(abi.encodeWithSignature("invoke(address,uint256,bytes)", _to, _value, _data));
        if (success) {
            (_res) = abi.decode(_res, (bytes));
        } else {
            // solhint-disable-next-line no-inline-assembly
            assembly {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }
    }
}

File 2 of 9 : Managed.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.3;

import "./Owned.sol";

/**
 * @title Managed
 * @notice Basic contract that defines a set of managers. Only the owner can add/remove managers.
 * @author Julien Niset, Olivier VDB - <[email protected]>, <[email protected]>
 */
contract Managed is Owned {

    // The managers
    mapping (address => bool) public managers;

    /**
     * @notice Throws if the sender is not a manager.
     */
    modifier onlyManager {
        require(managers[msg.sender] == true, "M: Must be manager");
        _;
    }

    event ManagerAdded(address indexed _manager);
    event ManagerRevoked(address indexed _manager);

    /**
    * @notice Adds a manager.
    * @param _manager The address of the manager.
    */
    function addManager(address _manager) external onlyOwner {
        require(_manager != address(0), "M: Address must not be null");
        if (managers[_manager] == false) {
            managers[_manager] = true;
            emit ManagerAdded(_manager);
        }
    }

    /**
    * @notice Revokes a manager.
    * @param _manager The address of the manager.
    */
    function revokeManager(address _manager) external virtual onlyOwner {
        // solhint-disable-next-line reason-string
        require(managers[_manager] == true, "M: Target must be an existing manager");
        delete managers[_manager];
        emit ManagerRevoked(_manager);
    }
}

File 3 of 9 : Owned.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.4 <0.9.0;

/**
 * @title Owned
 * @notice Basic contract to define an owner.
 * @author Julien Niset - <[email protected]>
 */
contract Owned {

    // The owner
    address public owner;

    event OwnerChanged(address indexed _newOwner);

    /**
     * @notice Throws if the sender is not the owner.
     */
    modifier onlyOwner {
        require(msg.sender == owner, "Must be owner");
        _;
    }

    constructor() public {
        owner = msg.sender;
    }

    /**
     * @notice Lets the owner transfer ownership of the contract to a new owner.
     * @param _newOwner The new owner.
     */
    function changeOwner(address _newOwner) external onlyOwner {
        require(_newOwner != address(0), "Address must not be null");
        owner = _newOwner;
        emit OwnerChanged(_newOwner);
    }
}

File 4 of 9 : IGuardianStorage.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.4 <0.9.0;

interface IGuardianStorage {

    /**
     * @notice Lets an authorised module add a guardian to a wallet.
     * @param _wallet The target wallet.
     * @param _guardian The guardian to add.
     */
    function addGuardian(address _wallet, address _guardian) external;

    /**
     * @notice Lets an authorised module revoke a guardian from a wallet.
     * @param _wallet The target wallet.
     * @param _guardian The guardian to revoke.
     */
    function revokeGuardian(address _wallet, address _guardian) external;

    /**
     * @notice Checks if an account is a guardian for a wallet.
     * @param _wallet The target wallet.
     * @param _guardian The account.
     * @return true if the account is a guardian for a wallet.
     */
    function isGuardian(address _wallet, address _guardian) external view returns (bool);

    function isLocked(address _wallet) external view returns (bool);

    function getLock(address _wallet) external view returns (uint256);

    function getLocker(address _wallet) external view returns (address);

    function setLock(address _wallet, uint256 _releaseAfter) external;

    function getGuardians(address _wallet) external view returns (address[] memory);

    function guardianCount(address _wallet) external view returns (uint256);
}

File 5 of 9 : IModule.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.3;

/**
 * @title IModule
 * @notice Interface for a Module.
 * @author Julien Niset - <[email protected]>, Olivier VDB - <[email protected]>
 */
interface IModule {

    /**	
     * @notice Adds a module to a wallet. Cannot execute when wallet is locked (or under recovery)	
     * @param _wallet The target wallet.	
     * @param _module The modules to authorise.	
     */	
    function addModule(address _wallet, address _module) external;

    /**
     * @notice Inits a Module for a wallet by e.g. setting some wallet specific parameters in storage.
     * @param _wallet The wallet.
     */
    function init(address _wallet) external;


    /**
     * @notice Returns whether the module implements a callback for a given static call method.
     * @param _methodId The method id.
     */
    function supportsStaticCall(bytes4 _methodId) external view returns (bool _isSupported);
}

File 6 of 9 : Utils.sol
// Copyright (C) 2020  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.3;

/**
 * @title Utils
 * @notice Common utility methods used by modules.
 */
library Utils {

    // ERC20, ERC721 & ERC1155 transfers & approvals
    bytes4 private constant ERC20_TRANSFER = bytes4(keccak256("transfer(address,uint256)"));
    bytes4 private constant ERC20_APPROVE = bytes4(keccak256("approve(address,uint256)"));
    bytes4 private constant ERC721_SET_APPROVAL_FOR_ALL = bytes4(keccak256("setApprovalForAll(address,bool)"));
    bytes4 private constant ERC721_TRANSFER_FROM = bytes4(keccak256("transferFrom(address,address,uint256)"));
    bytes4 private constant ERC721_SAFE_TRANSFER_FROM = bytes4(keccak256("safeTransferFrom(address,address,uint256)"));
    bytes4 private constant ERC721_SAFE_TRANSFER_FROM_BYTES = bytes4(keccak256("safeTransferFrom(address,address,uint256,bytes)"));
    bytes4 private constant ERC1155_SAFE_TRANSFER_FROM = bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)"));

    bytes4 private constant OWNER_SIG = 0x8da5cb5b;
    /**
    * @notice Helper method to recover the signer at a given position from a list of concatenated signatures.
    * @param _signedHash The signed hash
    * @param _signatures The concatenated signatures.
    * @param _index The index of the signature to recover.
    */
    function recoverSigner(bytes32 _signedHash, bytes memory _signatures, uint _index) internal pure returns (address) {
        uint8 v;
        bytes32 r;
        bytes32 s;
        // we jump 32 (0x20) as the first slot of bytes contains the length
        // we jump 65 (0x41) per signature
        // for v we load 32 bytes ending with v (the first 31 come from s) then apply a mask
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(_signatures, add(0x20,mul(0x41,_index))))
            s := mload(add(_signatures, add(0x40,mul(0x41,_index))))
            v := and(mload(add(_signatures, add(0x41,mul(0x41,_index)))), 0xff)
        }
        require(v == 27 || v == 28, "Utils: bad v value in signature");

        address recoveredAddress = ecrecover(_signedHash, v, r, s);
        require(recoveredAddress != address(0), "Utils: ecrecover returned 0");
        return recoveredAddress;
    }

    /**
    * @notice Helper method to recover the spender from a contract call. 
    * The method returns the contract unless the call is to a standard method of a ERC20/ERC721/ERC1155 token
    * in which case the spender is recovered from the data.
    * @param _to The target contract.
    * @param _data The data payload.
    */
    function recoverSpender(address _to, bytes memory _data) internal pure returns (address spender) {
        if(_data.length >= 68) {
            bytes4 methodId;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                methodId := mload(add(_data, 0x20))
            }
            if(
                methodId == ERC20_TRANSFER ||
                methodId == ERC20_APPROVE ||
                methodId == ERC721_SET_APPROVAL_FOR_ALL) 
            {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    spender := mload(add(_data, 0x24))
                }
                return spender;
            }
            if(
                methodId == ERC721_TRANSFER_FROM ||
                methodId == ERC721_SAFE_TRANSFER_FROM ||
                methodId == ERC721_SAFE_TRANSFER_FROM_BYTES ||
                methodId == ERC1155_SAFE_TRANSFER_FROM)
            {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    spender := mload(add(_data, 0x44))
                }
                return spender;
            }
        }

        spender = _to;
    }

    /**
    * @notice Helper method to parse data and extract the method signature.
    */
    function functionPrefix(bytes memory _data) internal pure returns (bytes4 prefix) {
        require(_data.length >= 4, "Utils: Invalid functionPrefix");
        // solhint-disable-next-line no-inline-assembly
        assembly {
            prefix := mload(add(_data, 0x20))
        }
    }

    /**
    * @notice Checks if an address is a contract.
    * @param _addr The address.
    */
    function isContract(address _addr) internal view returns (bool) {
        uint32 size;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            size := extcodesize(_addr)
        }
        return (size > 0);
    }

    /**
    * @notice Checks if an address is a guardian or an account authorised to sign on behalf of a smart-contract guardian
    * given a list of guardians.
    * @param _guardians the list of guardians
    * @param _guardian the address to test
    * @return true and the list of guardians minus the found guardian upon success, false and the original list of guardians if not found.
    */
    function isGuardianOrGuardianSigner(address[] memory _guardians, address _guardian) internal view returns (bool, address[] memory) {
        if (_guardians.length == 0 || _guardian == address(0)) {
            return (false, _guardians);
        }
        bool isFound = false;
        address[] memory updatedGuardians = new address[](_guardians.length - 1);
        uint256 index = 0;
        for (uint256 i = 0; i < _guardians.length; i++) {
            if (!isFound) {
                // check if _guardian is an account guardian
                if (_guardian == _guardians[i]) {
                    isFound = true;
                    continue;
                }
                // check if _guardian is the owner of a smart contract guardian
                if (isContract(_guardians[i]) && isGuardianOwner(_guardians[i], _guardian)) {
                    isFound = true;
                    continue;
                }
            }
            if (index < updatedGuardians.length) {
                updatedGuardians[index] = _guardians[i];
                index++;
            }
        }
        return isFound ? (true, updatedGuardians) : (false, _guardians);
    }

    /**
    * @notice Checks if an address is the owner of a guardian contract.
    * The method does not revert if the call to the owner() method consumes more then 25000 gas.
    * @param _guardian The guardian contract
    * @param _owner The owner to verify.
    */
    function isGuardianOwner(address _guardian, address _owner) internal view returns (bool) {
        address owner = address(0);

        // solhint-disable-next-line no-inline-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr,OWNER_SIG)
            let result := staticcall(25000, _guardian, ptr, 0x20, ptr, 0x20)
            if eq(result, 1) {
                owner := mload(ptr)
            }
        }
        return owner == _owner;
    }

    /**
    * @notice Returns ceil(a / b).
    */
    function ceil(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a / b;
        if (a % b == 0) {
            return c;
        } else {
            return c + 1;
        }
    }
}

File 7 of 9 : BaseWallet.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.3;

import "../modules/common/IModule.sol";
import "./IWallet.sol";

/**
 * @title BaseWallet
 * @notice Simple modular wallet that authorises modules to call its invoke() method.
 * @author Julien Niset - <[email protected]>
 */
contract BaseWallet is IWallet {

    // The owner
    address public override owner;
    // The authorised modules
    mapping (address => bool) public override authorised;
    // module executing static calls
    address public staticCallExecutor;
    // The number of modules
    uint public override modules;

    event AuthorisedModule(address indexed module, bool value);
    event Invoked(address indexed module, address indexed target, uint indexed value, bytes data);
    event Received(uint indexed value, address indexed sender, bytes data);
    event OwnerChanged(address owner);

    /**
     * @notice Throws if the sender is not an authorised module.
     */
    modifier moduleOnly {
        require(authorised[msg.sender], "BW: sender not authorized");
        _;
    }

    /**
     * @notice Inits the wallet by setting the owner and authorising a list of modules.
     * @param _owner The owner.
     * @param _modules The modules to authorise.
     */
    function init(address _owner, address[] calldata _modules) external {
        require(owner == address(0) && modules == 0, "BW: wallet already initialised");
        require(_modules.length > 0, "BW: empty modules");
        owner = _owner;
        modules = _modules.length;
        for (uint256 i = 0; i < _modules.length; i++) {
            require(authorised[_modules[i]] == false, "BW: module is already added");
            authorised[_modules[i]] = true;
            IModule(_modules[i]).init(address(this));
            emit AuthorisedModule(_modules[i], true);
        }
        if (address(this).balance > 0) {
            emit Received(address(this).balance, address(0), "");
        }
    }

    /**
     * @inheritdoc IWallet
     */
    function authoriseModule(address _module, bool _value) external override moduleOnly {
        if (authorised[_module] != _value) {
            emit AuthorisedModule(_module, _value);
            if (_value == true) {
                modules += 1;
                authorised[_module] = true;
                IModule(_module).init(address(this));
            } else {
                modules -= 1;
                require(modules > 0, "BW: cannot remove last module");
                delete authorised[_module];
            }
        }
    }

    /**
    * @inheritdoc IWallet
    */
    function enabled(bytes4 _sig) public view override returns (address) {
        address executor = staticCallExecutor;
        if(executor != address(0) && IModule(executor).supportsStaticCall(_sig)) {
            return executor;
        }
        return address(0);
    }

    /**
    * @inheritdoc IWallet
    */
    function enableStaticCall(address _module, bytes4 /* _method */) external override moduleOnly {
        if(staticCallExecutor != _module) {
            require(authorised[_module], "BW: unauthorized executor");
            staticCallExecutor = _module;
        }
    }

    /**
     * @inheritdoc IWallet
     */
    function setOwner(address _newOwner) external override moduleOnly {
        require(_newOwner != address(0), "BW: address cannot be null");
        owner = _newOwner;
        emit OwnerChanged(_newOwner);
    }

    /**
     * @notice Performs a generic transaction.
     * @param _target The address for the transaction.
     * @param _value The value of the transaction.
     * @param _data The data of the transaction.
     */
    function invoke(address _target, uint _value, bytes calldata _data) external moduleOnly returns (bytes memory _result) {
        bool success;
        (success, _result) = _target.call{value: _value}(_data);
        if (!success) {
            // solhint-disable-next-line no-inline-assembly
            assembly {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }
        emit Invoked(msg.sender, _target, _value, _data);
    }

    /**
     * @notice This method delegates the static call to a target contract if the data corresponds
     * to an enabled module, or logs the call otherwise.
     */
    fallback() external payable {
        address module = enabled(msg.sig);
        if (module == address(0)) {
            emit Received(msg.value, msg.sender, msg.data);
        } else {
            require(authorised[module], "BW: unauthorised module");

            // solhint-disable-next-line no-inline-assembly
            assembly {
                calldatacopy(0, 0, calldatasize())
                let result := staticcall(gas(), module, 0, calldatasize(), 0, 0)
                returndatacopy(0, 0, returndatasize())
                switch result
                case 0 {revert(0, returndatasize())}
                default {return (0, returndatasize())}
            }
        }
    }

    receive() external payable {
    }
}

File 8 of 9 : IWallet.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.4 <0.9.0;

/**
 * @title IWallet
 * @notice Interface for the BaseWallet
 */
interface IWallet {
    /**
     * @notice Returns the wallet owner.
     * @return The wallet owner address.
     */
    function owner() external view returns (address);

    /**
     * @notice Returns the number of authorised modules.
     * @return The number of authorised modules.
     */
    function modules() external view returns (uint);

    /**
     * @notice Sets a new owner for the wallet.
     * @param _newOwner The new owner.
     */
    function setOwner(address _newOwner) external;

    /**
     * @notice Checks if a module is authorised on the wallet.
     * @param _module The module address to check.
     * @return `true` if the module is authorised, otherwise `false`.
     */
    function authorised(address _module) external view returns (bool);

    /**
     * @notice Returns the module responsible for a static call redirection.
     * @param _sig The signature of the static call.
     * @return the module doing the redirection
     */
    function enabled(bytes4 _sig) external view returns (address);

    /**
     * @notice Enables/Disables a module.
     * @param _module The target module.
     * @param _value Set to `true` to authorise the module.
     */
    function authoriseModule(address _module, bool _value) external;

    /**
    * @notice Enables a static method by specifying the target module to which the call must be delegated.
    * @param _module The target module.
    * @param _method The static method signature.
    */
    function enableStaticCall(address _module, bytes4 _method) external;
}

File 9 of 9 : Proxy.sol
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.3;

/**
 * @title Proxy
 * @notice Basic proxy that delegates all calls to a fixed implementing contract.
 * The implementing contract cannot be upgraded.
 * @author Julien Niset - <[email protected]>
 */
contract Proxy {

    address immutable public implementation;

    event Received(uint indexed value, address indexed sender, bytes data);

    constructor(address _implementation) {
        implementation = _implementation;
    }

    fallback() external payable {
        address target = implementation;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch result
            case 0 {revert(0, returndatasize())}
            default {return (0, returndatasize())}
        }
    }

    receive() external payable {
        emit Received(msg.value, msg.sender, "");
    }
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 999
  },
  "evmVersion": "istanbul",
  "libraries": {
    "": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_walletImplementation","type":"address"},{"internalType":"address","name":"_guardianStorage","type":"address"},{"internalType":"address","name":"_refundAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_manager","type":"address"}],"name":"ManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_manager","type":"address"}],"name":"ManagerRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"RefundAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":false,"internalType":"address","name":"refundToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"refundAmount","type":"uint256"}],"name":"WalletCreated","type":"event"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"addManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_refundAddress","type":"address"}],"name":"changeRefundAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_modules","type":"address[]"},{"internalType":"address","name":"_guardian","type":"address"},{"internalType":"bytes20","name":"_salt","type":"bytes20"},{"internalType":"uint256","name":"_refundAmount","type":"uint256"},{"internalType":"address","name":"_refundToken","type":"address"},{"internalType":"bytes","name":"_ownerSignature","type":"bytes"},{"internalType":"bytes","name":"_managerSignature","type":"bytes"}],"name":"createCounterfactualWallet","outputs":[{"internalType":"address","name":"_wallet","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_modules","type":"address[]"},{"internalType":"address","name":"_guardian","type":"address"},{"internalType":"bytes20","name":"_salt","type":"bytes20"}],"name":"getAddressForCounterfactualWallet","outputs":[{"internalType":"address","name":"_wallet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardianStorage","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract BaseWallet","name":"_wallet","type":"address"}],"name":"init","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"managers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"revokeManager","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"walletImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b5060405162001b0f38038062001b0f8339810160408190526200003491620001b0565b600080546001600160a01b031916331790556001600160a01b038316620000a25760405162461bcd60e51b815260206004820152601f60248201527f57463a20656d7074792077616c6c657420696d706c656d656e746174696f6e0060448201526064015b60405180910390fd5b6001600160a01b038216620000fa5760405162461bcd60e51b815260206004820152601a60248201527f57463a20656d70747920677561726469616e2073746f72616765000000000000604482015260640162000099565b6001600160a01b038116620001525760405162461bcd60e51b815260206004820152601860248201527f57463a20656d70747920726566756e6420616464726573730000000000000000604482015260640162000099565b606092831b6001600160601b03199081166080529190921b1660a052600280546001600160a01b0319166001600160a01b03909216919091179055620001f9565b80516001600160a01b0381168114620001ab57600080fd5b919050565b600080600060608486031215620001c5578283fd5b620001d08462000193565b9250620001e06020850162000193565b9150620001f06040850162000193565b90509250925092565b60805160601c60a05160601c6118d56200023a600039600081816101ba0152610d3801526000818161015a0152818161059801526107e501526118d56000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063d89784fc1161005b578063d89784fc146101b5578063fbe2ec7d146101dc578063fdff9b4d146101ef576100d4565b80638da5cb5b1461017c578063a6f9dae11461018f578063a80dd9df146101a2576100d4565b80632d06177a116100b25780632d06177a1461012f578063377e32e6146101425780638117abc114610155576100d4565b80630cb61f6c146100d957806319ab453c146101095780632c8285251461011c575b600080fd5b6002546100ec906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61011a6101173660046112a1565b50565b005b61011a61012a3660046112a1565b610222565b61011a61013d3660046112a1565b610328565b61011a6101503660046112a1565b610437565b6100ec7f000000000000000000000000000000000000000000000000000000000000000081565b6000546100ec906001600160a01b031681565b61011a61019d3660046112a1565b61047f565b6100ec6101b036600461133b565b610574565b6100ec7f000000000000000000000000000000000000000000000000000000000000000081565b6100ec6101ea3660046112c4565b610790565b6102126101fd3660046112a1565b60016020526000908152604090205460ff1681565b6040519015158152602001610100565b6000546001600160a01b031633146102715760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1031329037bbb732b960991b60448201526064015b60405180910390fd5b6001600160a01b0381166102c75760405162461bcd60e51b815260206004820152601760248201527f57463a2063616e6e6f742073657420746f20656d7074790000000000000000006044820152606401610268565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fa7cb165192538768851363c5aa55b1ade75d692a51063730feccdd57d002a6ed9060200160405180910390a150565b6000546001600160a01b031633146103725760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1031329037bbb732b960991b6044820152606401610268565b6001600160a01b0381166103c85760405162461bcd60e51b815260206004820152601b60248201527f4d3a2041646472657373206d757374206e6f74206265206e756c6c00000000006044820152606401610268565b6001600160a01b03811660009081526001602052604090205460ff16610117576001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a9190a250565b60405162461bcd60e51b815260206004820152601d60248201527f57463a206d616e61676572732063616e2774206265207265766f6b65640000006044820152606401610268565b6000546001600160a01b031633146104c95760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1031329037bbb732b960991b6044820152606401610268565b6001600160a01b03811661051f5760405162461bcd60e51b815260206004820152601860248201527f41646472657373206d757374206e6f74206265206e756c6c00000000000000006044820152606401610268565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117825560405190917fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3691a250565b60006105828c8c8c8c610898565b6000610591898e8e8e8e6109f9565b90506000817f00000000000000000000000000000000000000000000000000000000000000006040516105c3906111dd565b6001600160a01b0390911681526020018190604051809103906000f59050801580156105f3573d6000803e3d6000fd5b5090506106368186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a6692505050565b610643818f8f8f8f610b4b565b6000891180156106535750604186145b1561069b5761069b818f8b8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610d9e92505050565b6040517f1f17732d000000000000000000000000000000000000000000000000000000008152306004820152600060248201526001600160a01b03821690631f17732d90604401600060405180830381600087803b1580156106fc57600080fd5b505af1158015610710573d6000803e3d6000fd5b505050508a6001600160a01b03168e6001600160a01b0316826001600160a01b03167facd43e061b8ee386537b57919358cfa44933c4e47ccd4b2e1916e54133cec7488b8d6040516107779291906001600160a01b03929092168252602082015260400190565b60405180910390a49d9c50505050505050505050505050565b600061079e86868686610898565b60006107ad83888888886109f9565b90506000604051806020016107c1906111dd565b601f1982820381018352601f90910116604081905261080e91906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690602001611565565b60408051808303601f1901815282825280516020918201207fff00000000000000000000000000000000000000000000000000000000000000828501523060601b6bffffffffffffffffffffffff19166021850152603584019590955260558084019590955281518084039095018552607590920190528251920191909120979650505050505050565b6001600160a01b0384166108ee5760405162461bcd60e51b815260206004820152601760248201527f57463a20656d707479206f776e657220616464726573730000000000000000006044820152606401610268565b806001600160a01b0316846001600160a01b031614156109505760405162461bcd60e51b815260206004820152601c60248201527f57463a206f776e65722063616e6e6f7420626520677561726469616e000000006044820152606401610268565b8161099d5760405162461bcd60e51b815260206004820152601160248201527f57463a20656d707479206d6f64756c65730000000000000000000000000000006044820152606401610268565b6001600160a01b0381166109f35760405162461bcd60e51b815260206004820152601260248201527f57463a20656d70747920677561726469616e00000000000000000000000000006044820152606401610268565b50505050565b600084848484604051602001610a1294939291906114e2565b60408051601f198184030181528282528051602091820120908301526bffffffffffffffffffffffff1988169082015260540160405160208183030381529060405280519060200120905095945050505050565b60008151604114610a78575033610ade565b6040517f19457468657265756d205369676e6564204d6573736167653a0a33320000000060208201526001600160a01b038416603c820152600090605c01604051602081830303815290604052805190602001209050610ada81846000610f9c565b9150505b6001600160a01b03811660009081526001602052604090205460ff16610b465760405162461bcd60e51b815260206004820181905260248201527f57463a20756e617574686f72697365642077616c6c6574206372656174696f6e6044820152606401610268565b505050565b6000610b5883600161162b565b67ffffffffffffffff811115610b7e57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610ba7578160200160208202803683370190505b5090503081600081518110610bcc57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060005b83811015610c8057848482818110610c1757634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610c2c91906112a1565b82610c3883600161162b565b81518110610c5657634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280610c788161166f565b915050610bef565b506040517f3c5a3cea0000000000000000000000000000000000000000000000000000000081526001600160a01b03871690633c5a3cea90610cc89088908590600401611587565b600060405180830381600087803b158015610ce257600080fd5b505af1158015610cf6573d6000803e3d6000fd5b50506040517fc68452100000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015285811660248301527f000000000000000000000000000000000000000000000000000000000000000016925063c68452109150604401600060405180830381600087803b158015610d7e57600080fd5b505af1158015610d92573d6000803e3d6000fd5b50505050505050505050565b6040516bffffffffffffffffffffffff19606087811b821660208401526034830186905284901b16605482015260009060680160408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c016040516020818303038152906040528051906020012090506000610e4082846000610f9c565b9050856001600160a01b0316816001600160a01b03161415610f93576001600160a01b038416610e9b57600254604080516020810190915260008152610e959189916001600160a01b039091169088906110dc565b50610f93565b6002546040516001600160a01b0390911660248201526044810186905260009060640160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905290506000610f26898783856110dc565b805190915015610f905780806020019051810190610f449190611424565b610f905760405162461bcd60e51b815260206004820152601a60248201527f57463a20526566756e64207472616e73666572206661696c65640000000000006044820152606401610268565b50505b50505050505050565b6041808202830160208101516040820151919092015160009260ff9190911691601b831480610fce57508260ff16601c145b61101a5760405162461bcd60e51b815260206004820152601f60248201527f5574696c733a2062616420762076616c756520696e207369676e6174757265006044820152606401610268565b604080516000808252602082018084528a905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa15801561106e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110d15760405162461bcd60e51b815260206004820152601b60248201527f5574696c733a2065637265636f7665722072657475726e6564203000000000006044820152606401610268565b979650505050505050565b60606000856001600160a01b03168585856040516024016110ff939291906115e1565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8f6f033200000000000000000000000000000000000000000000000000000000179052516111629190611549565b6000604051808303816000865af19150503d806000811461119f576040519150601f19603f3d011682016040523d82523d6000602084013e6111a4565b606091505b509250905080156111ca57818060200190518101906111c39190611444565b91506111d4565b3d6000803e3d6000fd5b50949350505050565b6101d4806116cc83390190565b80356111f5816116b6565b919050565b60008083601f84011261120b578081fd5b50813567ffffffffffffffff811115611222578182fd5b6020830191508360208260051b850101111561123d57600080fd5b9250929050565b80356bffffffffffffffffffffffff19811681146111f557600080fd5b60008083601f840112611272578182fd5b50813567ffffffffffffffff811115611289578182fd5b60208301915083602082850101111561123d57600080fd5b6000602082840312156112b2578081fd5b81356112bd816116b6565b9392505050565b6000806000806000608086880312156112db578081fd5b85356112e6816116b6565b9450602086013567ffffffffffffffff811115611301578182fd5b61130d888289016111fa565b9095509350506040860135611321816116b6565b915061132f60608701611244565b90509295509295909350565b60008060008060008060008060008060006101008c8e03121561135c578586fd5b6113658c6111ea565b9a5067ffffffffffffffff8060208e01351115611380578687fd5b6113908e60208f01358f016111fa565b909b5099506113a160408e016111ea565b98506113af60608e01611244565b975060808d013596506113c460a08e016111ea565b95508060c08e013511156113d6578485fd5b6113e68e60c08f01358f01611261565b909550935060e08d01358110156113fb578283fd5b5061140c8d60e08e01358e01611261565b81935080925050509295989b509295989b9093969950565b600060208284031215611435578081fd5b815180151581146112bd578182fd5b600060208284031215611455578081fd5b815167ffffffffffffffff8082111561146c578283fd5b818401915084601f83011261147f578283fd5b815181811115611491576114916116a0565b604051601f8201601f19908116603f011681019083821181831017156114b9576114b96116a0565b816040528281528760208487010111156114d1578586fd5b6110d1836020830160208801611643565b60006bffffffffffffffffffffffff19808760601b1683526014830186835b87811015611532578135611514816116b6565b6001600160a01b031683526020928301929190910190600101611501565b505060609490941b16835250506014019392505050565b6000825161155b818460208701611643565b9190910192915050565b60008351611577818460208801611643565b9190910191825250602001919050565b6000604082016001600160a01b03808616845260206040818601528286518085526060870191508288019450855b818110156115d35785518516835294830194918301916001016115b5565b509098975050505050505050565b60006001600160a01b0385168252836020830152606060408301528251806060840152611615816080850160208701611643565b601f01601f191691909101608001949350505050565b6000821982111561163e5761163e61168a565b500190565b60005b8381101561165e578181015183820152602001611646565b838111156109f35750506000910152565b60006000198214156116835761168361168a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461011757600080fdfe60a060405234801561001057600080fd5b506040516101d43803806101d483398101604081905261002f91610044565b60601b6001600160601b031916608052610072565b600060208284031215610055578081fd5b81516001600160a01b038116811461006b578182fd5b9392505050565b60805160601c61013f610095600039600081816069015260be015261013f6000f3fe6080604052600436106100225760003560e01c80635c60da1b146100ac57610067565b3661006757604080516020808252600090820152339134917f606834f57405380c4fb88d1f4850326ad3885f014bab3b568dfbf7a041eef738910160405180910390a3005b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100a7573d6000f35b3d6000fd5b3480156100b857600080fd5b506100e07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f3fea2646970667358221220b88a14f52e9d465328c9b3ab476e4b7fa40ed3615fd5409a6afc9885366e03a964736f6c63430008030033a2646970667358221220dec5ae87a38d164692a0d9f7a489556203efa01d593e3bbffea1447231dc89d664736f6c63430008030033000000000000000000000000ab00ea153c43575184ff11dd5e713c96be00557300000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f000000000000000000000000482579f93dc13e6b434e38b5a0447ca543d88a46

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063d89784fc1161005b578063d89784fc146101b5578063fbe2ec7d146101dc578063fdff9b4d146101ef576100d4565b80638da5cb5b1461017c578063a6f9dae11461018f578063a80dd9df146101a2576100d4565b80632d06177a116100b25780632d06177a1461012f578063377e32e6146101425780638117abc114610155576100d4565b80630cb61f6c146100d957806319ab453c146101095780632c8285251461011c575b600080fd5b6002546100ec906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61011a6101173660046112a1565b50565b005b61011a61012a3660046112a1565b610222565b61011a61013d3660046112a1565b610328565b61011a6101503660046112a1565b610437565b6100ec7f000000000000000000000000ab00ea153c43575184ff11dd5e713c96be00557381565b6000546100ec906001600160a01b031681565b61011a61019d3660046112a1565b61047f565b6100ec6101b036600461133b565b610574565b6100ec7f00000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f81565b6100ec6101ea3660046112c4565b610790565b6102126101fd3660046112a1565b60016020526000908152604090205460ff1681565b6040519015158152602001610100565b6000546001600160a01b031633146102715760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1031329037bbb732b960991b60448201526064015b60405180910390fd5b6001600160a01b0381166102c75760405162461bcd60e51b815260206004820152601760248201527f57463a2063616e6e6f742073657420746f20656d7074790000000000000000006044820152606401610268565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fa7cb165192538768851363c5aa55b1ade75d692a51063730feccdd57d002a6ed9060200160405180910390a150565b6000546001600160a01b031633146103725760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1031329037bbb732b960991b6044820152606401610268565b6001600160a01b0381166103c85760405162461bcd60e51b815260206004820152601b60248201527f4d3a2041646472657373206d757374206e6f74206265206e756c6c00000000006044820152606401610268565b6001600160a01b03811660009081526001602052604090205460ff16610117576001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a9190a250565b60405162461bcd60e51b815260206004820152601d60248201527f57463a206d616e61676572732063616e2774206265207265766f6b65640000006044820152606401610268565b6000546001600160a01b031633146104c95760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1031329037bbb732b960991b6044820152606401610268565b6001600160a01b03811661051f5760405162461bcd60e51b815260206004820152601860248201527f41646472657373206d757374206e6f74206265206e756c6c00000000000000006044820152606401610268565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117825560405190917fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3691a250565b60006105828c8c8c8c610898565b6000610591898e8e8e8e6109f9565b90506000817f000000000000000000000000ab00ea153c43575184ff11dd5e713c96be0055736040516105c3906111dd565b6001600160a01b0390911681526020018190604051809103906000f59050801580156105f3573d6000803e3d6000fd5b5090506106368186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a6692505050565b610643818f8f8f8f610b4b565b6000891180156106535750604186145b1561069b5761069b818f8b8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610d9e92505050565b6040517f1f17732d000000000000000000000000000000000000000000000000000000008152306004820152600060248201526001600160a01b03821690631f17732d90604401600060405180830381600087803b1580156106fc57600080fd5b505af1158015610710573d6000803e3d6000fd5b505050508a6001600160a01b03168e6001600160a01b0316826001600160a01b03167facd43e061b8ee386537b57919358cfa44933c4e47ccd4b2e1916e54133cec7488b8d6040516107779291906001600160a01b03929092168252602082015260400190565b60405180910390a49d9c50505050505050505050505050565b600061079e86868686610898565b60006107ad83888888886109f9565b90506000604051806020016107c1906111dd565b601f1982820381018352601f90910116604081905261080e91906001600160a01b037f000000000000000000000000ab00ea153c43575184ff11dd5e713c96be0055731690602001611565565b60408051808303601f1901815282825280516020918201207fff00000000000000000000000000000000000000000000000000000000000000828501523060601b6bffffffffffffffffffffffff19166021850152603584019590955260558084019590955281518084039095018552607590920190528251920191909120979650505050505050565b6001600160a01b0384166108ee5760405162461bcd60e51b815260206004820152601760248201527f57463a20656d707479206f776e657220616464726573730000000000000000006044820152606401610268565b806001600160a01b0316846001600160a01b031614156109505760405162461bcd60e51b815260206004820152601c60248201527f57463a206f776e65722063616e6e6f7420626520677561726469616e000000006044820152606401610268565b8161099d5760405162461bcd60e51b815260206004820152601160248201527f57463a20656d707479206d6f64756c65730000000000000000000000000000006044820152606401610268565b6001600160a01b0381166109f35760405162461bcd60e51b815260206004820152601260248201527f57463a20656d70747920677561726469616e00000000000000000000000000006044820152606401610268565b50505050565b600084848484604051602001610a1294939291906114e2565b60408051601f198184030181528282528051602091820120908301526bffffffffffffffffffffffff1988169082015260540160405160208183030381529060405280519060200120905095945050505050565b60008151604114610a78575033610ade565b6040517f19457468657265756d205369676e6564204d6573736167653a0a33320000000060208201526001600160a01b038416603c820152600090605c01604051602081830303815290604052805190602001209050610ada81846000610f9c565b9150505b6001600160a01b03811660009081526001602052604090205460ff16610b465760405162461bcd60e51b815260206004820181905260248201527f57463a20756e617574686f72697365642077616c6c6574206372656174696f6e6044820152606401610268565b505050565b6000610b5883600161162b565b67ffffffffffffffff811115610b7e57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610ba7578160200160208202803683370190505b5090503081600081518110610bcc57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060005b83811015610c8057848482818110610c1757634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610c2c91906112a1565b82610c3883600161162b565b81518110610c5657634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280610c788161166f565b915050610bef565b506040517f3c5a3cea0000000000000000000000000000000000000000000000000000000081526001600160a01b03871690633c5a3cea90610cc89088908590600401611587565b600060405180830381600087803b158015610ce257600080fd5b505af1158015610cf6573d6000803e3d6000fd5b50506040517fc68452100000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015285811660248301527f00000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f16925063c68452109150604401600060405180830381600087803b158015610d7e57600080fd5b505af1158015610d92573d6000803e3d6000fd5b50505050505050505050565b6040516bffffffffffffffffffffffff19606087811b821660208401526034830186905284901b16605482015260009060680160408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c016040516020818303038152906040528051906020012090506000610e4082846000610f9c565b9050856001600160a01b0316816001600160a01b03161415610f93576001600160a01b038416610e9b57600254604080516020810190915260008152610e959189916001600160a01b039091169088906110dc565b50610f93565b6002546040516001600160a01b0390911660248201526044810186905260009060640160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905290506000610f26898783856110dc565b805190915015610f905780806020019051810190610f449190611424565b610f905760405162461bcd60e51b815260206004820152601a60248201527f57463a20526566756e64207472616e73666572206661696c65640000000000006044820152606401610268565b50505b50505050505050565b6041808202830160208101516040820151919092015160009260ff9190911691601b831480610fce57508260ff16601c145b61101a5760405162461bcd60e51b815260206004820152601f60248201527f5574696c733a2062616420762076616c756520696e207369676e6174757265006044820152606401610268565b604080516000808252602082018084528a905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa15801561106e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110d15760405162461bcd60e51b815260206004820152601b60248201527f5574696c733a2065637265636f7665722072657475726e6564203000000000006044820152606401610268565b979650505050505050565b60606000856001600160a01b03168585856040516024016110ff939291906115e1565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8f6f033200000000000000000000000000000000000000000000000000000000179052516111629190611549565b6000604051808303816000865af19150503d806000811461119f576040519150601f19603f3d011682016040523d82523d6000602084013e6111a4565b606091505b509250905080156111ca57818060200190518101906111c39190611444565b91506111d4565b3d6000803e3d6000fd5b50949350505050565b6101d4806116cc83390190565b80356111f5816116b6565b919050565b60008083601f84011261120b578081fd5b50813567ffffffffffffffff811115611222578182fd5b6020830191508360208260051b850101111561123d57600080fd5b9250929050565b80356bffffffffffffffffffffffff19811681146111f557600080fd5b60008083601f840112611272578182fd5b50813567ffffffffffffffff811115611289578182fd5b60208301915083602082850101111561123d57600080fd5b6000602082840312156112b2578081fd5b81356112bd816116b6565b9392505050565b6000806000806000608086880312156112db578081fd5b85356112e6816116b6565b9450602086013567ffffffffffffffff811115611301578182fd5b61130d888289016111fa565b9095509350506040860135611321816116b6565b915061132f60608701611244565b90509295509295909350565b60008060008060008060008060008060006101008c8e03121561135c578586fd5b6113658c6111ea565b9a5067ffffffffffffffff8060208e01351115611380578687fd5b6113908e60208f01358f016111fa565b909b5099506113a160408e016111ea565b98506113af60608e01611244565b975060808d013596506113c460a08e016111ea565b95508060c08e013511156113d6578485fd5b6113e68e60c08f01358f01611261565b909550935060e08d01358110156113fb578283fd5b5061140c8d60e08e01358e01611261565b81935080925050509295989b509295989b9093969950565b600060208284031215611435578081fd5b815180151581146112bd578182fd5b600060208284031215611455578081fd5b815167ffffffffffffffff8082111561146c578283fd5b818401915084601f83011261147f578283fd5b815181811115611491576114916116a0565b604051601f8201601f19908116603f011681019083821181831017156114b9576114b96116a0565b816040528281528760208487010111156114d1578586fd5b6110d1836020830160208801611643565b60006bffffffffffffffffffffffff19808760601b1683526014830186835b87811015611532578135611514816116b6565b6001600160a01b031683526020928301929190910190600101611501565b505060609490941b16835250506014019392505050565b6000825161155b818460208701611643565b9190910192915050565b60008351611577818460208801611643565b9190910191825250602001919050565b6000604082016001600160a01b03808616845260206040818601528286518085526060870191508288019450855b818110156115d35785518516835294830194918301916001016115b5565b509098975050505050505050565b60006001600160a01b0385168252836020830152606060408301528251806060840152611615816080850160208701611643565b601f01601f191691909101608001949350505050565b6000821982111561163e5761163e61168a565b500190565b60005b8381101561165e578181015183820152602001611646565b838111156109f35750506000910152565b60006000198214156116835761168361168a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461011757600080fdfe60a060405234801561001057600080fd5b506040516101d43803806101d483398101604081905261002f91610044565b60601b6001600160601b031916608052610072565b600060208284031215610055578081fd5b81516001600160a01b038116811461006b578182fd5b9392505050565b60805160601c61013f610095600039600081816069015260be015261013f6000f3fe6080604052600436106100225760003560e01c80635c60da1b146100ac57610067565b3661006757604080516020808252600090820152339134917f606834f57405380c4fb88d1f4850326ad3885f014bab3b568dfbf7a041eef738910160405180910390a3005b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100a7573d6000f35b3d6000fd5b3480156100b857600080fd5b506100e07f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f3fea2646970667358221220b88a14f52e9d465328c9b3ab476e4b7fa40ed3615fd5409a6afc9885366e03a964736f6c63430008030033a2646970667358221220dec5ae87a38d164692a0d9f7a489556203efa01d593e3bbffea1447231dc89d664736f6c63430008030033

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

000000000000000000000000ab00ea153c43575184ff11dd5e713c96be00557300000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f000000000000000000000000482579f93dc13e6b434e38b5a0447ca543d88a46

-----Decoded View---------------
Arg [0] : _walletImplementation (address): 0xAb00eA153c43575184ff11Dd5e713c96bE005573
Arg [1] : _guardianStorage (address): 0x44DA3A8051bA88EAB0440DB3779cAB9D679ae76f
Arg [2] : _refundAddress (address): 0x482579F93dC13e6B434E38b5a0447ca543D88A46

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ab00ea153c43575184ff11dd5e713c96be005573
Arg [1] : 00000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f
Arg [2] : 000000000000000000000000482579f93dc13e6b434e38b5a0447ca543d88a46


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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  ]
[ 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.