编译器
0.8.19+commit.7dd6d404
文件 1 的 7:AddressProvider.sol
pragma solidity 0.8.19;
import {IAddressProviderService} from "interfaces/IAddressProviderService.sol";
import {Constants} from "src/core/Constants.sol";
contract AddressProvider is Constants {
error RegistryAlreadyExists();
error AddressProviderUnsupported();
error NotGovernance(address);
error NotPendingGovernance(address);
error NullAddress();
event RegistryInitialised(address indexed registry, bytes32 indexed key);
event AuthorizedAddressInitialised(address indexed authorizedAddress, bytes32 indexed key);
event GovernanceTransferRequested(address indexed previousGovernance, address indexed newGovernance);
event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance);
address public governance;
address public pendingGovernance;
mapping(bytes32 => address) internal authorizedAddresses;
mapping(bytes32 => address) internal registries;
constructor(address _governance, address walletRegistry, address policyRegistry, address executorRegistry) {
_notNull(_governance);
governance = _governance;
_notNull(walletRegistry);
_notNull(policyRegistry);
_notNull(executorRegistry);
registries[_WALLET_REGISTRY_HASH] = walletRegistry;
registries[_POLICY_REGISTRY_HASH] = policyRegistry;
registries[_EXECUTOR_REGISTRY_HASH] = executorRegistry;
}
function setGovernance(address _newGovernance) external {
_notNull(_newGovernance);
_onlyGov();
emit GovernanceTransferRequested(governance, _newGovernance);
pendingGovernance = _newGovernance;
}
function acceptGovernance() external {
if (msg.sender != pendingGovernance) {
revert NotPendingGovernance(msg.sender);
}
emit GovernanceTransferred(governance, msg.sender);
governance = msg.sender;
delete pendingGovernance;
}
function setAuthorizedAddress(bytes32 _key, address _authorizedAddress, bool _overrideCheck) external {
_onlyGov();
_notNull(_authorizedAddress);
if (!_overrideCheck) {
if (_authorizedAddress.code.length != 0) _ensureAddressProvider(_authorizedAddress);
}
authorizedAddresses[_key] = _authorizedAddress;
emit AuthorizedAddressInitialised(_authorizedAddress, _key);
}
function setRegistry(bytes32 _key, address _registry) external {
_onlyGov();
_ensureAddressProvider(_registry);
if (registries[_key] != address(0)) revert RegistryAlreadyExists();
registries[_key] = _registry;
emit RegistryInitialised(_registry, _key);
}
function getAuthorizedAddress(bytes32 _key) external view returns (address) {
return authorizedAddresses[_key];
}
function getRegistry(bytes32 _key) external view returns (address) {
return registries[_key];
}
function _ensureAddressProvider(address _newAddress) internal view {
if (IAddressProviderService(_newAddress).addressProviderTarget() != address(this)) {
revert AddressProviderUnsupported();
}
}
function _onlyGov() internal view {
if (msg.sender != governance) revert NotGovernance(msg.sender);
}
function _notNull(address addr) internal pure {
if (addr == address(0)) revert NullAddress();
}
}
文件 2 的 7:AddressProviderService.sol
pragma solidity 0.8.19;
import {IAddressProviderService} from "../../interfaces/IAddressProviderService.sol";
import {AddressProvider} from "../core/AddressProvider.sol";
import {Constants} from "./Constants.sol";
abstract contract AddressProviderService is IAddressProviderService, Constants {
error InvalidAddressProvider();
error NotGovernance(address);
error InvalidAddress();
AddressProvider public immutable addressProvider;
address public immutable walletRegistry;
address public immutable policyRegistry;
address public immutable executorRegistry;
constructor(address _addressProvider) {
if (_addressProvider == address(0)) revert InvalidAddressProvider();
addressProvider = AddressProvider(_addressProvider);
walletRegistry = addressProvider.getRegistry(_WALLET_REGISTRY_HASH);
policyRegistry = addressProvider.getRegistry(_POLICY_REGISTRY_HASH);
executorRegistry = addressProvider.getRegistry(_EXECUTOR_REGISTRY_HASH);
_notNull(walletRegistry);
_notNull(policyRegistry);
_notNull(executorRegistry);
}
function addressProviderTarget() external view override returns (address) {
return address(addressProvider);
}
function _getAuthorizedAddress(bytes32 _key) internal view returns (address authorizedAddress) {
authorizedAddress = addressProvider.getAuthorizedAddress(_key);
_notNull(authorizedAddress);
}
function _notNull(address _addr) internal pure {
if (_addr == address(0)) revert InvalidAddress();
}
}
文件 3 的 7:Constants.sol
pragma solidity 0.8.19;
abstract contract Constants {
bytes32 internal constant _EXECUTOR_REGISTRY_HASH = bytes32(uint256(keccak256("console.core.ExecutorRegistry")) - 1);
bytes32 internal constant _WALLET_REGISTRY_HASH = bytes32(uint256(keccak256("console.core.WalletRegistry")) - 1);
bytes32 internal constant _POLICY_REGISTRY_HASH = bytes32(uint256(keccak256("console.core.PolicyRegistry")) - 1);
bytes32 internal constant _EXECUTOR_PLUGIN_HASH = bytes32(uint256(keccak256("console.core.ExecutorPlugin")) - 1);
bytes32 internal constant _CONSOLE_FALLBACK_HANDLER_HASH =
bytes32(uint256(keccak256("console.core.FallbackHandler")) - 1);
bytes32 internal constant _SAFE_FALLBACK_HANDLER_HASH = bytes32(uint256(keccak256("safe.FallbackHandler")) - 1);
bytes32 internal constant _SAFE_MULTI_SEND_HASH = bytes32(uint256(keccak256("safe.MultiSend")) - 1);
bytes32 internal constant _SAFE_PROXY_FACTORY_HASH = bytes32(uint256(keccak256("safe.ProxyFactory")) - 1);
bytes32 internal constant _SAFE_SINGLETON_HASH = bytes32(uint256(keccak256("safe.Singleton")) - 1);
bytes32 internal constant _POLICY_VALIDATOR_HASH = bytes32(uint256(keccak256("console.core.PolicyValidator")) - 1);
bytes32 internal constant _SAFE_DEPLOYER_HASH = bytes32(uint256(keccak256("console.core.SafeDeployer")) - 1);
bytes32 internal constant _SAFE_ENABLER_HASH = bytes32(uint256(keccak256("console.core.SafeEnabler")) - 1);
bytes32 internal constant _SAFE_MODERATOR_HASH = bytes32(uint256(keccak256("console.core.SafeModerator")) - 1);
bytes32 internal constant _SAFE_MODERATOR_OVERRIDABLE_HASH =
bytes32(uint256(keccak256("console.core.SafeModeratorOverridable")) - 1);
bytes32 internal constant _TRANSACTION_VALIDATOR_HASH =
bytes32(uint256(keccak256("console.core.TransactionValidator")) - 1);
bytes32 internal constant _CONSOLE_OP_BUILDER_HASH =
bytes32(uint256(keccak256("console.core.ConsoleOpBuilder")) - 1);
bytes32 internal constant _EXECUTION_BLOCKER_HASH = bytes32(uint256(keccak256("console.core.ExecutionBlocker")) - 1);
bytes32 internal constant _POLICY_AUTHENTICATOR_HASH =
bytes32(uint256(keccak256("console.roles.PolicyAuthenticator")) - 1);
}
文件 4 的 7:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 5 的 7:ExecutorRegistry.sol
pragma solidity 0.8.19;
import {AddressProviderService} from "../AddressProviderService.sol";
import {WalletRegistry} from "./WalletRegistry.sol";
import {EnumerableSet} from "openzeppelin-contracts/utils/structs/EnumerableSet.sol";
contract ExecutorRegistry is AddressProviderService {
using EnumerableSet for EnumerableSet.AddressSet;
error NotAuthorized();
error AlreadyExists();
error DoesNotExist();
error NoPolicyCommit();
event RegisterExecutor(address indexed _account, address indexed _authorizer, address indexed _executor);
event DeRegisterExecutor(address indexed _account, address indexed _authorizer, address indexed _executor);
mapping(address account => EnumerableSet.AddressSet) private accountExecutors;
constructor(address _addressProvider) AddressProviderService(_addressProvider) {}
function registerExecutor(address _account, address _executor) external {
_validateMsgSenderConsoleAccount(_account);
if (!accountExecutors[_account].add(_executor)) revert AlreadyExists();
emit RegisterExecutor(_account, msg.sender, _executor);
}
function deRegisterExecutor(address _account, address _executor) external {
_validateMsgSenderConsoleAccount(_account);
if (!accountExecutors[_account].remove(_executor)) revert DoesNotExist();
emit DeRegisterExecutor(_account, msg.sender, _executor);
}
function isExecutor(address _account, address _executor) external view returns (bool) {
return accountExecutors[_account].contains(_executor);
}
function getExecutorsForAccount(address _account) external view returns (address[] memory) {
return accountExecutors[_account].values();
}
function _validateMsgSenderConsoleAccount(address _account) internal view {
if (msg.sender == _account && WalletRegistry(walletRegistry).isWallet(msg.sender)) return;
if (WalletRegistry(walletRegistry).subAccountToWallet(_account) == msg.sender) return;
revert NotAuthorized();
}
}
文件 6 的 7:IAddressProviderService.sol
pragma solidity 0.8.19;
interface IAddressProviderService {
function addressProviderTarget() external view returns (address);
}
文件 7 的 7:WalletRegistry.sol
pragma solidity 0.8.19;
import {AddressProviderService} from "../AddressProviderService.sol";
contract WalletRegistry is AddressProviderService {
error AlreadyRegistered();
error InvalidSender();
error IsSubAccount();
event RegisterWallet(address indexed wallet);
event RegisterSubAccount(address indexed wallet, address indexed subAccount);
mapping(address subAccount => address wallet) public subAccountToWallet;
mapping(address wallet => address[] subAccountList) public walletToSubAccountList;
mapping(address => bool) public isWallet;
constructor(address _addressProvider) AddressProviderService(_addressProvider) {}
function registerWallet() external {
if (isWallet[msg.sender]) revert AlreadyRegistered();
if (subAccountToWallet[msg.sender] != address(0)) revert IsSubAccount();
isWallet[msg.sender] = true;
emit RegisterWallet(msg.sender);
}
function registerSubAccount(address _wallet, address _subAccount) external {
if (msg.sender != AddressProviderService._getAuthorizedAddress(_SAFE_DEPLOYER_HASH)) revert InvalidSender();
if (subAccountToWallet[_subAccount] != address(0) || isWallet[_subAccount]) revert AlreadyRegistered();
subAccountToWallet[_subAccount] = _wallet;
walletToSubAccountList[_wallet].push(_subAccount);
emit RegisterSubAccount(_wallet, _subAccount);
}
function getSubAccountsForWallet(address _wallet) external view returns (address[] memory) {
return walletToSubAccountList[_wallet];
}
}
{
"compilationTarget": {
"src/core/registries/ExecutorRegistry.sol": "ExecutorRegistry"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 20000
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":safe-contracts/=lib/safe-contracts/contracts/",
":solady/=lib/solady/src/",
":solidity-bytes-utils/=lib/solidity-bytes-utils/contracts/",
":solmate/=lib/solady/lib/solmate/src/"
]
}
[{"inputs":[{"internalType":"address","name":"_addressProvider","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExists","type":"error"},{"inputs":[],"name":"DoesNotExist","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAddressProvider","type":"error"},{"inputs":[],"name":"NoPolicyCommit","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"NotGovernance","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"},{"indexed":true,"internalType":"address","name":"_authorizer","type":"address"},{"indexed":true,"internalType":"address","name":"_executor","type":"address"}],"name":"DeRegisterExecutor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_account","type":"address"},{"indexed":true,"internalType":"address","name":"_authorizer","type":"address"},{"indexed":true,"internalType":"address","name":"_executor","type":"address"}],"name":"RegisterExecutor","type":"event"},{"inputs":[],"name":"addressProvider","outputs":[{"internalType":"contract AddressProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addressProviderTarget","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_executor","type":"address"}],"name":"deRegisterExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"executorRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getExecutorsForAccount","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_executor","type":"address"}],"name":"isExecutor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"policyRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_executor","type":"address"}],"name":"registerExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]