Skip to content

Instantly share code, notes, and snippets.

@adamgall
Last active August 12, 2023 18:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamgall/6e6fadef01a48d58b6c34fcc39d099f2 to your computer and use it in GitHub Desktop.
Save adamgall/6e6fadef01a48d58b6c34fcc39d099f2 to your computer and use it in GitHub Desktop.
SimpleSafe: a bare-minimum 1-of-1 "multisig" contract with a rotatable owner. Inspired by @0xfoobar.
// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.21;
contract SimpleSafe {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != msg.sender) {
revert OwnableUnauthorizedAccount(msg.sender);
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @notice Executes either a delegatecall or a call with provided parameters.
* @dev This method doesn't perform any sanity check of the transaction, such as:
* - if the contract at `to` address has code or not
* It is the responsibility of the caller to perform such checks.
* @param to Destination address.
* @param value Ether value.
* @param data Data payload.
* @param delegate should delegatecall or not..
* @return success boolean flag indicating if the call succeeded.
*/
function execute(
address to,
uint256 value,
bytes memory data,
bool delegate
) public onlyOwner returns (bool success) {
if (delegate) {
(success,) = to.delegatecall(data);
} else {
(success,) = to.call{value: value}(data);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment