Overview
xDAI Balance
xDAI Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 34 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer* | 39696474 | 14 hrs ago | IN | 0 xDAI | 0.00028615 | ||||
Transfer* | 39696472 | 14 hrs ago | IN | 0 xDAI | 0.00004942 | ||||
Transfer* | 39696109 | 14 hrs ago | IN | 0 xDAI | 0.00038977 | ||||
Transfer* | 39696107 | 14 hrs ago | IN | 0 xDAI | 0.00005274 | ||||
Transfer* | 39694760 | 16 hrs ago | IN | 0 xDAI | 0.000616 | ||||
Transfer* | 39694723 | 16 hrs ago | IN | 0 xDAI | 0.00028157 | ||||
Transfer* | 39694721 | 16 hrs ago | IN | 0 xDAI | 0.00005274 | ||||
Transfer* | 39693935 | 17 hrs ago | IN | 0 xDAI | 0.00057331 | ||||
Transfer* | 39693898 | 18 hrs ago | IN | 0 xDAI | 0.00028191 | ||||
Transfer* | 39693896 | 18 hrs ago | IN | 0 xDAI | 0.00005274 | ||||
Transfer* | 39693855 | 18 hrs ago | IN | 0 xDAI | 0.0006612 | ||||
Transfer* | 39693818 | 18 hrs ago | IN | 0 xDAI | 0.00028157 | ||||
Transfer* | 39693817 | 18 hrs ago | IN | 0 xDAI | 0.00005274 | ||||
Transfer* | 39579218 | 7 days ago | IN | 0 xDAI | 0.00015629 | ||||
Transfer* | 39579182 | 7 days ago | IN | 0 xDAI | 0.00022449 | ||||
Transfer* | 39579181 | 7 days ago | IN | 0 xDAI | 0.00005274 | ||||
Transfer* | 39543060 | 9 days ago | IN | 0 xDAI | 0.0007248 | ||||
Transfer* | 39543021 | 9 days ago | IN | 0 xDAI | 0.00028588 | ||||
Transfer* | 39543019 | 9 days ago | IN | 0 xDAI | 0.00005274 | ||||
Transfer* | 39138658 | 33 days ago | IN | 0 xDAI | 0.00013064 | ||||
Transfer* | 39138626 | 33 days ago | IN | 0 xDAI | 0.00012915 | ||||
Transfer* | 39138592 | 33 days ago | IN | 0 xDAI | 0.00022449 | ||||
Transfer* | 39102743 | 35 days ago | IN | 0 xDAI | 0.00013064 | ||||
Transfer* | 39102706 | 35 days ago | IN | 0 xDAI | 0.00022449 | ||||
Transfer* | 39102192 | 35 days ago | IN | 0 xDAI | 0.00015629 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
38629692 | 63 days ago | Contract Creation | 0 xDAI |
Loading...
Loading
Minimal Proxy Contract for 0x4a97e65188a950dd4b0f21f9b5434daee0bbf9f5
Contract Name:
Delay
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0; import {Enum, Modifier} from "@gnosis.pm/zodiac/contracts/core/Modifier.sol"; contract Delay is Modifier { event DelaySetup( address indexed initiator, address indexed owner, address indexed avatar, address target ); event TxCooldownSet(uint256 cooldown); event TxExpirationSet(uint256 expiration); event TxNonceSet(uint256 nonce); event TransactionAdded( uint256 indexed queueNonce, bytes32 indexed txHash, address to, uint256 value, bytes data, Enum.Operation operation ); uint256 public txCooldown; uint256 public txExpiration; uint256 public txNonce; uint256 public queueNonce; // Mapping of queue nonce to transaction hash. mapping(uint256 => bytes32) public txHash; // Mapping of queue nonce to creation timestamp. mapping(uint256 => uint256) public txCreatedAt; /// @param _owner Address of the owner /// @param _avatar Address of the avatar (e.g. a Gnosis Safe) /// @param _target Address of the contract that will call exec function /// @param _cooldown Cooldown in seconds that should be required after a transaction is proposed /// @param _expiration Duration that a proposed transaction is valid for after the cooldown, in seconds (or 0 if valid forever) /// @notice There need to be at least 60 seconds between end of cooldown and expiration constructor( address _owner, address _avatar, address _target, uint256 _cooldown, uint256 _expiration ) { bytes memory initParams = abi.encode( _owner, _avatar, _target, _cooldown, _expiration ); setUp(initParams); } function setUp(bytes memory initParams) public override initializer { ( address _owner, address _avatar, address _target, uint256 _cooldown, uint256 _expiration ) = abi.decode( initParams, (address, address, address, uint256, uint256) ); require(_avatar != address(0), "Avatar can not be zero address"); require(_target != address(0), "Target can not be zero address"); require( _expiration == 0 || _expiration >= 60, "Expiration must be 0 or at least 60 seconds" ); _transferOwnership(_owner); avatar = _avatar; target = _target; txExpiration = _expiration; txCooldown = _cooldown; setupModules(); emit DelaySetup(msg.sender, _owner, _avatar, _target); emit AvatarSet(address(0), _avatar); emit TargetSet(address(0), _target); } /// @dev Sets the cooldown before a transaction can be executed. /// @param _txCooldown Cooldown in seconds that should be required before the transaction can be executed /// @notice This can only be called by the owner function setTxCooldown(uint256 _txCooldown) public onlyOwner { txCooldown = _txCooldown; emit TxCooldownSet(_txCooldown); } /// @dev Sets the duration for which a transaction is valid. /// @param _txExpiration Duration that a transaction is valid in seconds (or 0 if valid forever) after the cooldown /// @notice There need to be at least 60 seconds between end of cooldown and expiration /// @notice This can only be called by the owner function setTxExpiration(uint256 _txExpiration) public onlyOwner { require( _txExpiration == 0 || _txExpiration >= 60, "Expiration must be 0 or at least 60 seconds" ); txExpiration = _txExpiration; emit TxExpirationSet(_txExpiration); } /// @dev Sets transaction nonce. Used to invalidate or skip transactions in queue. /// @param _txNonce New transaction nonce /// @notice This can only be called by the owner function setTxNonce(uint256 _txNonce) public onlyOwner { require( _txNonce > txNonce, "New nonce must be higher than current txNonce" ); require(_txNonce <= queueNonce, "Cannot be higher than queueNonce"); txNonce = _txNonce; emit TxNonceSet(_txNonce); } /// @dev Adds a transaction to the queue (same as avatar interface so that this can be placed between other modules and the avatar). /// @param to Destination address of module transaction /// @param value Ether value of module transaction /// @param data Data payload of module transaction /// @param operation Operation type of module transaction /// @return success Whether or not the call was successfully queued for execution /// @notice Can only be called by enabled modules function execTransactionFromModule( address to, uint256 value, bytes calldata data, Enum.Operation operation ) public override moduleOnly returns (bool success) { bytes32 hash = getTransactionHash(to, value, data, operation); txHash[queueNonce] = hash; txCreatedAt[queueNonce] = block.timestamp; emit TransactionAdded(queueNonce, hash, to, value, data, operation); queueNonce++; success = true; } /// @dev Adds a transaction to the queue (same as avatar interface so that this can be placed between other modules and the avatar). /// @param to Destination address of module transaction /// @param value Ether value of module transaction /// @param data Data payload of module transaction /// @param operation Operation type of module transaction /// @return success Whether or not the call was successfully queued for execution /// @return returnData ABI encoded queue nonce (uint256), transaction hash (bytes32), and block.timestamp (uint256) /// @notice Can only be called by enabled modules function execTransactionFromModuleReturnData( address to, uint256 value, bytes calldata data, Enum.Operation operation ) public override moduleOnly returns (bool success, bytes memory returnData) { bytes32 hash = getTransactionHash(to, value, data, operation); txHash[queueNonce] = hash; txCreatedAt[queueNonce] = block.timestamp; emit TransactionAdded(queueNonce, hash, to, value, data, operation); success = true; returnData = abi.encode(queueNonce, hash, block.timestamp); queueNonce++; } /// @dev Executes the next transaction only if the cooldown has passed and the transaction has not expired /// @param to Destination address of module transaction /// @param value Ether value of module transaction /// @param data Data payload of module transaction /// @param operation Operation type of module transaction /// @notice The txIndex used by this function is always 0 function executeNextTx( address to, uint256 value, bytes calldata data, Enum.Operation operation ) public { require(txNonce < queueNonce, "Transaction queue is empty"); uint256 txCreationTimestamp = txCreatedAt[txNonce]; require( block.timestamp - txCreationTimestamp >= txCooldown, "Transaction is still in cooldown" ); if (txExpiration != 0) { require( txCreationTimestamp + txCooldown + txExpiration >= block.timestamp, "Transaction expired" ); } require( txHash[txNonce] == getTransactionHash(to, value, data, operation), "Transaction hashes do not match" ); txNonce++; require(exec(to, value, data, operation), "Module transaction failed"); } function skipExpired() public { while ( txExpiration != 0 && txCreatedAt[txNonce] + txCooldown + txExpiration < block.timestamp && txNonce < queueNonce ) { txNonce++; } } function getTransactionHash( address to, uint256 value, bytes memory data, Enum.Operation operation ) public pure returns (bytes32) { return keccak256(abi.encodePacked(to, value, data, operation)); } function getTxHash(uint256 _nonce) public view returns (bytes32) { return (txHash[_nonce]); } function getTxCreatedAt(uint256 _nonce) public view returns (uint256) { return (txCreatedAt[_nonce]); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /// @title Enum - Collection of enums /// @author Richard Meissner - <[email protected]> contract Enum { enum Operation {Call, DelegateCall} }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; import {ExecutionTracker} from "../signature/ExecutionTracker.sol"; import {IAvatar} from "../interfaces/IAvatar.sol"; import {Module} from "./Module.sol"; import {SignatureChecker} from "../signature/SignatureChecker.sol"; /// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. abstract contract Modifier is Module, ExecutionTracker, SignatureChecker, IAvatar { address internal constant SENTINEL_MODULES = address(0x1); /// Mapping of modules. mapping(address => address) internal modules; /// `sender` is not an authorized module. /// @param sender The address of the sender. error NotAuthorized(address sender); /// `module` is invalid. error InvalidModule(address module); /// `pageSize` is invalid. error InvalidPageSize(); /// `module` is already disabled. error AlreadyDisabledModule(address module); /// `module` is already enabled. error AlreadyEnabledModule(address module); /// @dev `setModules()` was already called. error SetupModulesAlreadyCalled(); /* -------------------------------------------------- You must override both of the following virtual functions, execTransactionFromModule() and execTransactionFromModuleReturnData(). It is recommended that implementations of both functions make use the onlyModule modifier. */ /// @dev Passes a transaction to the modifier. /// @notice Can only be called by enabled modules. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction. function execTransactionFromModule( address to, uint256 value, bytes calldata data, Enum.Operation operation ) public virtual returns (bool success); /// @dev Passes a transaction to the modifier, expects return data. /// @notice Can only be called by enabled modules. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction. function execTransactionFromModuleReturnData( address to, uint256 value, bytes calldata data, Enum.Operation operation ) public virtual returns (bool success, bytes memory returnData); /* -------------------------------------------------- */ modifier moduleOnly() { if (modules[msg.sender] == address(0)) { (bytes32 hash, address signer) = moduleTxSignedBy(); // is the signer a module? if (modules[signer] == address(0)) { revert NotAuthorized(msg.sender); } // is the provided signature fresh? if (consumed[signer][hash]) { revert HashAlreadyConsumed(hash); } consumed[signer][hash] = true; emit HashExecuted(hash); } _; } function sentOrSignedByModule() internal view returns (address) { if (modules[msg.sender] != address(0)) { return msg.sender; } (, address signer) = moduleTxSignedBy(); if (modules[signer] != address(0)) { return signer; } return address(0); } /// @dev Disables a module on the modifier. /// @notice This can only be called by the owner. /// @param prevModule Module that pointed to the module to be removed in the linked list. /// @param module Module to be removed. function disableModule( address prevModule, address module ) public override onlyOwner { if (module == address(0) || module == SENTINEL_MODULES) revert InvalidModule(module); if (modules[prevModule] != module) revert AlreadyDisabledModule(module); modules[prevModule] = modules[module]; modules[module] = address(0); emit DisabledModule(module); } /// @dev Enables a module that can add transactions to the queue /// @param module Address of the module to be enabled /// @notice This can only be called by the owner function enableModule(address module) public override onlyOwner { if (module == address(0) || module == SENTINEL_MODULES) revert InvalidModule(module); if (modules[module] != address(0)) revert AlreadyEnabledModule(module); modules[module] = modules[SENTINEL_MODULES]; modules[SENTINEL_MODULES] = module; emit EnabledModule(module); } /// @dev Returns if an module is enabled /// @return True if the module is enabled function isModuleEnabled( address _module ) public view override returns (bool) { return SENTINEL_MODULES != _module && modules[_module] != address(0); } /// @dev Returns array of modules. /// If all entries fit into a single page, the next pointer will be 0x1. /// If another page is present, next will be the last element of the returned array. /// @param start Start of the page. Has to be a module or start pointer (0x1 address) /// @param pageSize Maximum number of modules that should be returned. Has to be > 0 /// @return array Array of modules. /// @return next Start of the next page. function getModulesPaginated( address start, uint256 pageSize ) external view override returns (address[] memory array, address next) { if (start != SENTINEL_MODULES && !isModuleEnabled(start)) { revert InvalidModule(start); } if (pageSize == 0) { revert InvalidPageSize(); } // Init array with max page size array = new address[](pageSize); // Populate return array uint256 moduleCount = 0; next = modules[start]; while ( next != address(0) && next != SENTINEL_MODULES && moduleCount < pageSize ) { array[moduleCount] = next; next = modules[next]; moduleCount++; } // Because of the argument validation we can assume that // the `currentModule` will always be either a module address // or sentinel address (aka the end). If we haven't reached the end // inside the loop, we need to set the next pointer to the last element // because it skipped over to the next module which is neither included // in the current page nor won't be included in the next one // if you pass it as a start. if (next != SENTINEL_MODULES) { next = array[moduleCount - 1]; } // Set correct size of returned array // solhint-disable-next-line no-inline-assembly assembly { mstore(array, moduleCount) } } /// @dev Initializes the modules linked list. /// @notice Should be called as part of the `setUp` / initializing function and can only be called once. function setupModules() internal { if (modules[SENTINEL_MODULES] != address(0)) revert SetupModulesAlreadyCalled(); modules[SENTINEL_MODULES] = SENTINEL_MODULES; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; import {FactoryFriendly} from "../factory/FactoryFriendly.sol"; import {IAvatar} from "../interfaces/IAvatar.sol"; /// @title Module Interface - A contract that can pass messages to a Module Manager contract if enabled by that contract. abstract contract Module is FactoryFriendly { /// @dev Address that will ultimately execute function calls. address public avatar; /// @dev Address that this module will pass transactions to. address public target; /// @dev Emitted each time the avatar is set. event AvatarSet(address indexed previousAvatar, address indexed newAvatar); /// @dev Emitted each time the Target is set. event TargetSet(address indexed previousTarget, address indexed newTarget); /// @dev Sets the avatar to a new avatar (`newAvatar`). /// @notice Can only be called by the current owner. function setAvatar(address _avatar) public onlyOwner { address previousAvatar = avatar; avatar = _avatar; emit AvatarSet(previousAvatar, _avatar); } /// @dev Sets the target to a new target (`newTarget`). /// @notice Can only be called by the current owner. function setTarget(address _target) public onlyOwner { address previousTarget = target; target = _target; emit TargetSet(previousTarget, _target); } /// @dev Passes a transaction to be executed by the avatar. /// @notice Can only be called by this contract. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. function exec( address to, uint256 value, bytes memory data, Enum.Operation operation ) internal virtual returns (bool success) { return IAvatar(target).execTransactionFromModule(to, value, data, operation); } /// @dev Passes a transaction to be executed by the target and returns data. /// @notice Can only be called by this contract. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. function execAndReturnData( address to, uint256 value, bytes memory data, Enum.Operation operation ) internal virtual returns (bool success, bytes memory returnData) { return IAvatar(target).execTransactionFromModuleReturnData( to, value, data, operation ); } }
// SPDX-License-Identifier: LGPL-3.0-only /// @title Zodiac FactoryFriendly - A contract that allows other contracts to be initializable and pass bytes as arguments to define contract state pragma solidity >=0.7.0 <0.9.0; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract FactoryFriendly is OwnableUpgradeable { function setUp(bytes memory initializeParams) public virtual; }
// SPDX-License-Identifier: LGPL-3.0-only /// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract. pragma solidity >=0.7.0 <0.9.0; import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; interface IAvatar { event EnabledModule(address module); event DisabledModule(address module); event ExecutionFromModuleSuccess(address indexed module); event ExecutionFromModuleFailure(address indexed module); /// @dev Enables a module on the avatar. /// @notice Can only be called by the avatar. /// @notice Modules should be stored as a linked list. /// @notice Must emit EnabledModule(address module) if successful. /// @param module Module to be enabled. function enableModule(address module) external; /// @dev Disables a module on the avatar. /// @notice Can only be called by the avatar. /// @notice Must emit DisabledModule(address module) if successful. /// @param prevModule Address that pointed to the module to be removed in the linked list /// @param module Module to be removed. function disableModule(address prevModule, address module) external; /// @dev Allows a Module to execute a transaction. /// @notice Can only be called by an enabled module. /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful. /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. function execTransactionFromModule( address to, uint256 value, bytes memory data, Enum.Operation operation ) external returns (bool success); /// @dev Allows a Module to execute a transaction and return data /// @notice Can only be called by an enabled module. /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful. /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful. /// @param to Destination address of module transaction. /// @param value Ether value of module transaction. /// @param data Data payload of module transaction. /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call. function execTransactionFromModuleReturnData( address to, uint256 value, bytes memory data, Enum.Operation operation ) external returns (bool success, bytes memory returnData); /// @dev Returns if an module is enabled /// @return True if the module is enabled function isModuleEnabled(address module) external view returns (bool); /// @dev Returns array of modules. /// @param start Start of the page. /// @param pageSize Maximum number of modules that should be returned. /// @return array Array of modules. /// @return next Start of the next page. function getModulesPaginated( address start, uint256 pageSize ) external view returns (address[] memory array, address next); }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; /// @title ExecutionTracker - A contract that keeps track of executed and invalidated hashes contract ExecutionTracker { error HashAlreadyConsumed(bytes32); event HashExecuted(bytes32); event HashInvalidated(bytes32); mapping(address => mapping(bytes32 => bool)) public consumed; function invalidate(bytes32 hash) external { consumed[msg.sender][hash] = true; emit HashInvalidated(hash); } }
// SPDX-License-Identifier: LGPL-3.0-only /* solhint-disable one-contract-per-file */ pragma solidity >=0.7.0 <0.9.0; interface IERC1271 { /** * @notice EIP1271 method to validate a signature. * @param hash Hash of the data signed on the behalf of address(this). * @param signature Signature byte array associated with _data. * * MUST return the bytes4 magic value 0x1626ba7e when function passes. * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) * MUST allow external calls */ function isValidSignature( bytes32 hash, bytes memory signature ) external view returns (bytes4); }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; import {IERC1271} from "./IERC1271.sol"; /// @title SignatureChecker - A contract that retrieves and validates signatures appended to transaction calldata. /// @dev currently supports eip-712 and eip-1271 signatures abstract contract SignatureChecker { /** * @notice Searches for a signature, validates it, and returns the signer's address. * @dev When signature not found or invalid, zero address is returned * @return The address of the signer. */ function moduleTxSignedBy() internal view returns (bytes32, address) { bytes calldata data = msg.data; /* * The idea is to extend `onlyModule` and provide signature checking * without code changes to inheriting contracts (Modifiers). * * Since it's a generic mechanism, there is no way to conclusively * identify the trailing bytes as a signature. We simply slice those * and recover signer. * * As a result, we impose a minimum calldata length equal to a function * selector plus salt, plus a signature (i.e., 4 + 32 + 65 bytes), any * shorter and calldata it guaranteed to not contain a signature. */ if (data.length < 4 + 32 + 65) { return (bytes32(0), address(0)); } (uint8 v, bytes32 r, bytes32 s) = _splitSignature(data); uint256 end = data.length - (32 + 65); bytes32 salt = bytes32(data[end:]); /* * When handling contract signatures: * v - is zero * r - contains the signer * s - contains the offset within calldata where the signer specific * signature is located * * We detect contract signatures by checking: * 1- `v` is zero * 2- `s` points within the buffer, is after selector, is before * salt and delimits a non-zero length buffer */ if (v == 0) { uint256 start = uint256(s); if (start < 4 || start > end) { return (bytes32(0), address(0)); } address signer = address(uint160(uint256(r))); bytes32 hash = moduleTxHash(data[:start], salt); return _isValidContractSignature(signer, hash, data[start:end]) ? (hash, signer) : (bytes32(0), address(0)); } else { bytes32 hash = moduleTxHash(data[:end], salt); return (hash, ecrecover(hash, v, r, s)); } } /** * @notice Hashes the transaction EIP-712 data structure. * @dev The produced hash is intended to be signed. * @param data The current transaction's calldata. * @param salt The salt value. * @return The 32-byte hash that is to be signed. */ function moduleTxHash( bytes calldata data, bytes32 salt ) public view returns (bytes32) { bytes32 domainSeparator = keccak256( abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this) ); bytes memory moduleTxData = abi.encodePacked( bytes1(0x19), bytes1(0x01), domainSeparator, keccak256(abi.encode(MODULE_TX_TYPEHASH, keccak256(data), salt)) ); return keccak256(moduleTxData); } /** * @dev Extracts signature from calldata, and divides it into `uint8 v, bytes32 r, bytes32 s`. * @param data The current transaction's calldata. * @return v The ECDSA v value * @return r The ECDSA r value * @return s The ECDSA s value */ function _splitSignature( bytes calldata data ) private pure returns (uint8 v, bytes32 r, bytes32 s) { v = uint8(bytes1(data[data.length - 1:])); r = bytes32(data[data.length - 65:]); s = bytes32(data[data.length - 33:]); } /** * @dev Calls the signer contract, and validates the contract signature. * @param signer The address of the signer contract. * @param hash Hash of the data signed * @param signature The contract signature. * @return result Indicates whether the signature is valid. */ function _isValidContractSignature( address signer, bytes32 hash, bytes calldata signature ) internal view returns (bool result) { uint256 size; // eslint-disable-line no-inline-assembly assembly { size := extcodesize(signer) } if (size == 0) { return false; } (, bytes memory returnData) = signer.staticcall( abi.encodeWithSelector( IERC1271.isValidSignature.selector, hash, signature ) ); return bytes4(returnData) == EIP1271_MAGIC_VALUE; } // keccak256( // "EIP712Domain(uint256 chainId,address verifyingContract)" // ); bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; // keccak256( // "ModuleTx(bytes data,bytes32 salt)" // ); bytes32 private constant MODULE_TX_TYPEHASH = 0x2939aeeda3ca260200c9f7b436b19e13207547ccc65cfedc857751c5ea6d91d4; // bytes4(keccak256( // "isValidSignature(bytes32,bytes)" // )); bytes4 private constant EIP1271_MAGIC_VALUE = 0x1626ba7e; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_avatar","type":"address"},{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_cooldown","type":"uint256"},{"internalType":"uint256","name":"_expiration","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"AlreadyDisabledModule","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"AlreadyEnabledModule","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"HashAlreadyConsumed","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"InvalidModule","type":"error"},{"inputs":[],"name":"InvalidPageSize","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"SetupModulesAlreadyCalled","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousAvatar","type":"address"},{"indexed":true,"internalType":"address","name":"newAvatar","type":"address"}],"name":"AvatarSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"avatar","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"}],"name":"DelaySetup","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"DisabledModule","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"EnabledModule","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"module","type":"address"}],"name":"ExecutionFromModuleFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"module","type":"address"}],"name":"ExecutionFromModuleSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"","type":"bytes32"}],"name":"HashExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"","type":"bytes32"}],"name":"HashInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTarget","type":"address"},{"indexed":true,"internalType":"address","name":"newTarget","type":"address"}],"name":"TargetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"queueNonce","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"enum Enum.Operation","name":"operation","type":"uint8"}],"name":"TransactionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cooldown","type":"uint256"}],"name":"TxCooldownSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"expiration","type":"uint256"}],"name":"TxExpirationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"TxNonceSet","type":"event"},{"inputs":[],"name":"avatar","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"consumed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"prevModule","type":"address"},{"internalType":"address","name":"module","type":"address"}],"name":"disableModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"enableModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"}],"name":"execTransactionFromModule","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"}],"name":"execTransactionFromModuleReturnData","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"}],"name":"executeNextTx","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"start","type":"address"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"getModulesPaginated","outputs":[{"internalType":"address[]","name":"array","type":"address[]"},{"internalType":"address","name":"next","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"}],"name":"getTransactionHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"getTxCreatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"getTxHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"invalidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_module","type":"address"}],"name":"isModuleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"moduleTxHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"queueNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_avatar","type":"address"}],"name":"setAvatar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"setTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txCooldown","type":"uint256"}],"name":"setTxCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txExpiration","type":"uint256"}],"name":"setTxExpiration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txNonce","type":"uint256"}],"name":"setTxNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"initParams","type":"bytes"}],"name":"setUp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skipExpired","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"target","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"txCooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"txCreatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"txExpiration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"txHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"txNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.