ETH Price: $3,766.68 (+1.49%)
Gas: 4 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...199447412024-05-25 5:16:355 hrs ago1716614195IN
Argent: Wallet Factory
0 ETH0.001168933.47357916
Create Counterfa...199444222024-05-25 4:11:596 hrs ago1716610319IN
Argent: Wallet Factory
0 ETH0.001272293.781
Create Counterfa...199440212024-05-25 2:50:238 hrs ago1716605423IN
Argent: Wallet Factory
0 ETH0.001256033.73255364
Create Counterfa...199428132024-05-24 22:46:4712 hrs ago1716590807IN
Argent: Wallet Factory
0 ETH0.001838315.46301373
Create Counterfa...199424062024-05-24 21:25:1113 hrs ago1716585911IN
Argent: Wallet Factory
0 ETH0.001935045.75055713
Create Counterfa...199416022024-05-24 18:43:1116 hrs ago1716576191IN
Argent: Wallet Factory
0 ETH0.003302529.81358799
Create Counterfa...199415872024-05-24 18:40:1116 hrs ago1716576011IN
Argent: Wallet Factory
0 ETH0.0033832610.05399964
Create Counterfa...199411222024-05-24 17:06:1117 hrs ago1716570371IN
Argent: Wallet Factory
0 ETH0.0039652911.7830169
Create Counterfa...199399742024-05-24 13:15:1121 hrs ago1716556511IN
Argent: Wallet Factory
0 ETH0.001957415.81662866
Create Counterfa...199384152024-05-24 8:01:1127 hrs ago1716537671IN
Argent: Wallet Factory
0 ETH0.0035977910.691
Create Counterfa...199355392024-05-23 22:23:2336 hrs ago1716503003IN
Argent: Wallet Factory
0 ETH0.0048111715.33309738
Create Counterfa...199334072024-05-23 15:13:5943 hrs ago1716477239IN
Argent: Wallet Factory
0 ETH0.0056587816.81615878
Create Counterfa...199301962024-05-23 4:28:472 days ago1716438527IN
Argent: Wallet Factory
0 ETH0.001328123.94658628
Create Counterfa...199289372024-05-23 0:15:112 days ago1716423311IN
Argent: Wallet Factory
0 ETH0.002368597.0383783
Create Counterfa...199288052024-05-22 23:48:472 days ago1716421727IN
Argent: Wallet Factory
0 ETH0.001973875.86543601
Create Counterfa...199277372024-05-22 20:14:352 days ago1716408875IN
Argent: Wallet Factory
0 ETH0.0045729813.58832682
Create Counterfa...199255522024-05-22 12:55:112 days ago1716382511IN
Argent: Wallet Factory
0 ETH0.0061587618.30129465
Create Counterfa...199248852024-05-22 10:39:593 days ago1716374399IN
Argent: Wallet Factory
0 ETH0.002813188.36022107
Create Counterfa...199247812024-05-22 10:19:113 days ago1716373151IN
Argent: Wallet Factory
0 ETH0.002105676.25740587
Create Counterfa...199246742024-05-22 9:57:353 days ago1716371855IN
Argent: Wallet Factory
0 ETH0.002167556.442
Create Counterfa...199206402024-05-21 20:22:353 days ago1716322955IN
Argent: Wallet Factory
0 ETH0.0050195314.91595258
Create Counterfa...199200612024-05-21 18:26:473 days ago1716316007IN
Argent: Wallet Factory
0 ETH0.0067960520.19546191
Create Counterfa...199195792024-05-21 16:49:353 days ago1716310175IN
Argent: Wallet Factory
0 ETH0.0074012421.99231062
Create Counterfa...199169052024-05-21 7:50:594 days ago1716277859IN
Argent: Wallet Factory
0 ETH0.0034031810.11284434
Create Counterfa...199167052024-05-21 7:10:354 days ago1716275435IN
Argent: Wallet Factory
0 ETH0.0034271710.18363225
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
199447412024-05-25 5:16:355 hrs ago1716614195
Argent: Wallet Factory
 Contract Creation0 ETH
199444222024-05-25 4:11:596 hrs ago1716610319
Argent: Wallet Factory
 Contract Creation0 ETH
199440212024-05-25 2:50:238 hrs ago1716605423
Argent: Wallet Factory
 Contract Creation0 ETH
199428132024-05-24 22:46:4712 hrs ago1716590807
Argent: Wallet Factory
 Contract Creation0 ETH
199424062024-05-24 21:25:1113 hrs ago1716585911
Argent: Wallet Factory
 Contract Creation0 ETH
199416022024-05-24 18:43:1116 hrs ago1716576191
Argent: Wallet Factory
 Contract Creation0 ETH
199415872024-05-24 18:40:1116 hrs ago1716576011
Argent: Wallet Factory
 Contract Creation0 ETH
199411222024-05-24 17:06:1117 hrs ago1716570371
Argent: Wallet Factory
 Contract Creation0 ETH
199399742024-05-24 13:15:1121 hrs ago1716556511
Argent: Wallet Factory
 Contract Creation0 ETH
199384152024-05-24 8:01:1127 hrs ago1716537671
Argent: Wallet Factory
 Contract Creation0 ETH
199355392024-05-23 22:23:2336 hrs ago1716503003
Argent: Wallet Factory
 Contract Creation0 ETH
199334072024-05-23 15:13:5943 hrs ago1716477239
Argent: Wallet Factory
 Contract Creation0 ETH
199301962024-05-23 4:28:472 days ago1716438527
Argent: Wallet Factory
 Contract Creation0 ETH
199289372024-05-23 0:15:112 days ago1716423311
Argent: Wallet Factory
 Contract Creation0 ETH
199288052024-05-22 23:48:472 days ago1716421727
Argent: Wallet Factory
 Contract Creation0 ETH
199277372024-05-22 20:14:352 days ago1716408875
Argent: Wallet Factory
 Contract Creation0 ETH
199255522024-05-22 12:55:112 days ago1716382511
Argent: Wallet Factory
 Contract Creation0 ETH
199248852024-05-22 10:39:593 days ago1716374399
Argent: Wallet Factory
 Contract Creation0 ETH
199247812024-05-22 10:19:113 days ago1716373151
Argent: Wallet Factory
 Contract Creation0 ETH
199246742024-05-22 9:57:353 days ago1716371855
Argent: Wallet Factory
 Contract Creation0 ETH
199206402024-05-21 20:22:353 days ago1716322955
Argent: Wallet Factory
 Contract Creation0 ETH
199200612024-05-21 18:26:473 days ago1716316007
Argent: Wallet Factory
 Contract Creation0 ETH
199195792024-05-21 16:49:353 days ago1716310175
Argent: Wallet Factory
 Contract Creation0 ETH
199169052024-05-21 7:50:594 days ago1716277859
Argent: Wallet Factory
 Contract Creation0 ETH
199167052024-05-21 7:10:354 days ago1716275435
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 3 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 4 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 5 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 6 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 7 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 8 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 9 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 10 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.