Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
AccessManager
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;
import {OwnableRoles} from "solady/src/auth/OwnableRoles.sol";
import {Initializable} from "solady/src/utils/Initializable.sol";
import {Multicallable} from "solady/src/utils/Multicallable.sol";
import "../Constants.sol" as Constants;
import {Errors} from "../Errors.sol";
/// @notice Access Manager module for managing single owner and multiple roles for multiple contracts and functions.
/// @dev Each PrincipalToken instance will have its own AccessManager instance to manage access control.
/// @dev AccessManager is a minimal proxy implementation to reduce deployment costs.
/// @dev Note: AccessManager must be initialized after deployment to set initial owner.
contract AccessManager is OwnableRoles, Initializable, Multicallable {
/// @notice Mapping of target contracts to their function selectors and roles that are allowed to call the function
mapping(address target => mapping(bytes4 selector => uint256 roles)) private s_targets;
/// @notice Emitted when roles are granted for a target function
/// @param target The address of the target contract
/// @param selector The function selector
/// @param roles The roles being granted
event TargetFunctionRolesGranted(address indexed target, bytes4 indexed selector, uint256 indexed roles);
/// @notice Emitted when roles are revoked for a target function
/// @param target The address of the target contract
/// @param selector The function selector
/// @param roles The roles being revoked
event TargetFunctionRolesRevoked(address indexed target, bytes4 indexed selector, uint256 indexed roles);
/// @notice Initializes the contract by setting the initial owner
/// @param curator The address of the initial owner
function initializeOwner(address curator) external initializer {
_initializeOwner(curator);
}
/// @dev Allows the owner to grant `user` `roles`.
/// If the `user` already has a role, then it will be an no-op for the role.
function grantRoles(address user, uint256 roles) public payable override onlyOwnerOrCanCall {
_grantRoles(user, roles);
}
/// @dev Allows the owner to remove `user` `roles`.
/// If the `user` does not have a role, then it will be an no-op for the role.
function revokeRoles(address user, uint256 roles) public payable override onlyOwnerOrCanCall {
_removeRoles(user, roles);
}
/// @notice Grants roles for multiple function selectors on a target contract
/// @param target The address of the target contract
/// @param selectors An array of function selectors
/// @param roles The roles to grant
function grantTargetFunctionRoles(address target, bytes4[] calldata selectors, uint256 roles)
public
payable
onlyOwnerOrCanCall
{
uint256 length = selectors.length;
for (uint256 i = 0; i != length;) {
_grantTargetFunctionRoles(target, selectors[i], roles);
unchecked {
++i;
}
}
}
/// @notice Revokes roles for multiple function selectors on a target contract
/// @param target The address of the target contract
/// @param selectors An array of function selectors
/// @param roles The roles to revoke
function revokeTargetFunctionRoles(address target, bytes4[] calldata selectors, uint256 roles)
public
payable
onlyOwnerOrCanCall
{
uint256 length = selectors.length;
for (uint256 i = 0; i != length;) {
_revokeTargetFunctionRoles(target, selectors[i], roles);
unchecked {
++i;
}
}
}
/// @notice Internal function to grant a role for a specific function on a target contract
/// @param target The address of the target contract
/// @param selector The function selector
/// @param roles The role to grant
function _grantTargetFunctionRoles(address target, bytes4 selector, uint256 roles) internal {
s_targets[target][selector] = s_targets[target][selector] | roles;
emit TargetFunctionRolesGranted(target, selector, roles);
}
/// @notice Internal function to revoke a role for a specific function on a target contract
/// @param target The address of the target contract
/// @param selector The function selector
/// @param roles The roles to revoke
function _revokeTargetFunctionRoles(address target, bytes4 selector, uint256 roles) internal {
s_targets[target][selector] = s_targets[target][selector] & ~roles;
emit TargetFunctionRolesRevoked(target, selector, roles);
}
/// @notice Checks if a caller has permission to call a specific function on a target contract
/// @param caller The address of the caller
/// @param target The address of the target contract
/// @param selector The function selector
/// @return bool True if the caller has permission, false otherwise
function canCall(address caller, address target, bytes4 selector) public view returns (bool) {
return hasAnyRole(caller, s_targets[target][selector]);
}
/// @dev Marks a function as only callable by the owner or by the caller with any role allowed to call the function
modifier onlyOwnerOrCanCall() {
_checkOwnerOrRoles({roles: s_targets[address(this)][bytes4(msg.data[0:4])]});
_;
}
}
abstract contract AccessManaged {
function i_accessManager() public view virtual returns (AccessManager);
modifier restricted() {
_checkRestricted(i_accessManager());
_;
}
modifier restrictedBy(AccessManager accessManager) {
_checkRestricted(accessManager);
_;
}
function _checkRestricted(AccessManager accessManager) internal view {
if (!accessManager.canCall(msg.sender, address(this), bytes4(msg.data[0:4]))) {
revert Errors.AccessManaged_Restricted();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {Ownable} from "./Ownable.sol";
/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/OwnableRoles.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract OwnableRoles is Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The `user`'s roles is updated to `roles`.
/// Each bit of `roles` represents whether the role is set.
event RolesUpdated(address indexed user, uint256 indexed roles);
/// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The role slot of `user` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
/// let roleSlot := keccak256(0x00, 0x20)
/// ```
/// This automatically ignores the upper bits of the `user` in case
/// they are not clean, as well as keep the `keccak256` under 32-bytes.
///
/// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Overwrite the roles directly without authorization guard.
function _setRoles(address user, uint256 roles) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Store the new value.
sstore(keccak256(0x0c, 0x20), roles)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
}
}
/// @dev Updates the roles directly without authorization guard.
/// If `on` is true, each set bit of `roles` will be turned on,
/// otherwise, each set bit of `roles` will be turned off.
function _updateRoles(address user, uint256 roles, bool on) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
let roleSlot := keccak256(0x0c, 0x20)
// Load the current value.
let current := sload(roleSlot)
// Compute the updated roles if `on` is true.
let updated := or(current, roles)
// Compute the updated roles if `on` is false.
// Use `and` to compute the intersection of `current` and `roles`,
// `xor` it with `current` to flip the bits in the intersection.
if iszero(on) { updated := xor(current, and(current, roles)) }
// Then, store the new value.
sstore(roleSlot, updated)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
}
}
/// @dev Grants the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn on.
function _grantRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, true);
}
/// @dev Removes the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn off.
function _removeRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, false);
}
/// @dev Throws if the sender does not have any of the `roles`.
function _checkRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Throws if the sender is not the owner,
/// and does not have any of the `roles`.
/// Checks for ownership first, then lazily checks for roles.
function _checkOwnerOrRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Throws if the sender does not have any of the `roles`,
/// and is not the owner.
/// Checks for roles first, then lazily checks for ownership.
function _checkRolesOrOwner(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
// We don't need to mask the values of `ordinals`, as Solidity
// cleans dirty upper bits when storing variables into memory.
roles := or(shl(mload(add(ordinals, i)), 1), roles)
}
}
}
/// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
/// @solidity memory-safe-assembly
assembly {
// Grab the pointer to the free memory.
ordinals := mload(0x40)
let ptr := add(ordinals, 0x20)
let o := 0
// The absence of lookup tables, De Bruijn, etc., here is intentional for
// smaller bytecode, as this function is not meant to be called on-chain.
for { let t := roles } 1 {} {
mstore(ptr, o)
// `shr` 5 is equivalent to multiplying by 0x20.
// Push back into the ordinals array if the bit is set.
ptr := add(ptr, shl(5, and(t, 1)))
o := add(o, 1)
t := shr(o, roles)
if iszero(t) { break }
}
// Store the length of `ordinals`.
mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
// Allocate the memory.
mstore(0x40, ptr)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to grant `user` `roles`.
/// If the `user` already has a role, then it will be an no-op for the role.
function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
_grantRoles(user, roles);
}
/// @dev Allows the owner to remove `user` `roles`.
/// If the `user` does not have a role, then it will be an no-op for the role.
function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
_removeRoles(user, roles);
}
/// @dev Allow the caller to remove their own roles.
/// If the caller does not have a role, then it will be an no-op for the role.
function renounceRoles(uint256 roles) public payable virtual {
_removeRoles(msg.sender, roles);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the roles of `user`.
function rolesOf(address user) public view virtual returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Load the stored value.
roles := sload(keccak256(0x0c, 0x20))
}
}
/// @dev Returns whether `user` has any of `roles`.
function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles != 0;
}
/// @dev Returns whether `user` has all of `roles`.
function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles == roles;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by an account with `roles`.
modifier onlyRoles(uint256 roles) virtual {
_checkRoles(roles);
_;
}
/// @dev Marks a function as only callable by the owner or by an account
/// with `roles`. Checks for ownership first, then lazily checks for roles.
modifier onlyOwnerOrRoles(uint256 roles) virtual {
_checkOwnerOrRoles(roles);
_;
}
/// @dev Marks a function as only callable by an account with `roles`
/// or the owner. Checks for roles first, then lazily checks for ownership.
modifier onlyRolesOrOwner(uint256 roles) virtual {
_checkRolesOrOwner(roles);
_;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ROLE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// IYKYK
uint256 internal constant _ROLE_0 = 1 << 0;
uint256 internal constant _ROLE_1 = 1 << 1;
uint256 internal constant _ROLE_2 = 1 << 2;
uint256 internal constant _ROLE_3 = 1 << 3;
uint256 internal constant _ROLE_4 = 1 << 4;
uint256 internal constant _ROLE_5 = 1 << 5;
uint256 internal constant _ROLE_6 = 1 << 6;
uint256 internal constant _ROLE_7 = 1 << 7;
uint256 internal constant _ROLE_8 = 1 << 8;
uint256 internal constant _ROLE_9 = 1 << 9;
uint256 internal constant _ROLE_10 = 1 << 10;
uint256 internal constant _ROLE_11 = 1 << 11;
uint256 internal constant _ROLE_12 = 1 << 12;
uint256 internal constant _ROLE_13 = 1 << 13;
uint256 internal constant _ROLE_14 = 1 << 14;
uint256 internal constant _ROLE_15 = 1 << 15;
uint256 internal constant _ROLE_16 = 1 << 16;
uint256 internal constant _ROLE_17 = 1 << 17;
uint256 internal constant _ROLE_18 = 1 << 18;
uint256 internal constant _ROLE_19 = 1 << 19;
uint256 internal constant _ROLE_20 = 1 << 20;
uint256 internal constant _ROLE_21 = 1 << 21;
uint256 internal constant _ROLE_22 = 1 << 22;
uint256 internal constant _ROLE_23 = 1 << 23;
uint256 internal constant _ROLE_24 = 1 << 24;
uint256 internal constant _ROLE_25 = 1 << 25;
uint256 internal constant _ROLE_26 = 1 << 26;
uint256 internal constant _ROLE_27 = 1 << 27;
uint256 internal constant _ROLE_28 = 1 << 28;
uint256 internal constant _ROLE_29 = 1 << 29;
uint256 internal constant _ROLE_30 = 1 << 30;
uint256 internal constant _ROLE_31 = 1 << 31;
uint256 internal constant _ROLE_32 = 1 << 32;
uint256 internal constant _ROLE_33 = 1 << 33;
uint256 internal constant _ROLE_34 = 1 << 34;
uint256 internal constant _ROLE_35 = 1 << 35;
uint256 internal constant _ROLE_36 = 1 << 36;
uint256 internal constant _ROLE_37 = 1 << 37;
uint256 internal constant _ROLE_38 = 1 << 38;
uint256 internal constant _ROLE_39 = 1 << 39;
uint256 internal constant _ROLE_40 = 1 << 40;
uint256 internal constant _ROLE_41 = 1 << 41;
uint256 internal constant _ROLE_42 = 1 << 42;
uint256 internal constant _ROLE_43 = 1 << 43;
uint256 internal constant _ROLE_44 = 1 << 44;
uint256 internal constant _ROLE_45 = 1 << 45;
uint256 internal constant _ROLE_46 = 1 << 46;
uint256 internal constant _ROLE_47 = 1 << 47;
uint256 internal constant _ROLE_48 = 1 << 48;
uint256 internal constant _ROLE_49 = 1 << 49;
uint256 internal constant _ROLE_50 = 1 << 50;
uint256 internal constant _ROLE_51 = 1 << 51;
uint256 internal constant _ROLE_52 = 1 << 52;
uint256 internal constant _ROLE_53 = 1 << 53;
uint256 internal constant _ROLE_54 = 1 << 54;
uint256 internal constant _ROLE_55 = 1 << 55;
uint256 internal constant _ROLE_56 = 1 << 56;
uint256 internal constant _ROLE_57 = 1 << 57;
uint256 internal constant _ROLE_58 = 1 << 58;
uint256 internal constant _ROLE_59 = 1 << 59;
uint256 internal constant _ROLE_60 = 1 << 60;
uint256 internal constant _ROLE_61 = 1 << 61;
uint256 internal constant _ROLE_62 = 1 << 62;
uint256 internal constant _ROLE_63 = 1 << 63;
uint256 internal constant _ROLE_64 = 1 << 64;
uint256 internal constant _ROLE_65 = 1 << 65;
uint256 internal constant _ROLE_66 = 1 << 66;
uint256 internal constant _ROLE_67 = 1 << 67;
uint256 internal constant _ROLE_68 = 1 << 68;
uint256 internal constant _ROLE_69 = 1 << 69;
uint256 internal constant _ROLE_70 = 1 << 70;
uint256 internal constant _ROLE_71 = 1 << 71;
uint256 internal constant _ROLE_72 = 1 << 72;
uint256 internal constant _ROLE_73 = 1 << 73;
uint256 internal constant _ROLE_74 = 1 << 74;
uint256 internal constant _ROLE_75 = 1 << 75;
uint256 internal constant _ROLE_76 = 1 << 76;
uint256 internal constant _ROLE_77 = 1 << 77;
uint256 internal constant _ROLE_78 = 1 << 78;
uint256 internal constant _ROLE_79 = 1 << 79;
uint256 internal constant _ROLE_80 = 1 << 80;
uint256 internal constant _ROLE_81 = 1 << 81;
uint256 internal constant _ROLE_82 = 1 << 82;
uint256 internal constant _ROLE_83 = 1 << 83;
uint256 internal constant _ROLE_84 = 1 << 84;
uint256 internal constant _ROLE_85 = 1 << 85;
uint256 internal constant _ROLE_86 = 1 << 86;
uint256 internal constant _ROLE_87 = 1 << 87;
uint256 internal constant _ROLE_88 = 1 << 88;
uint256 internal constant _ROLE_89 = 1 << 89;
uint256 internal constant _ROLE_90 = 1 << 90;
uint256 internal constant _ROLE_91 = 1 << 91;
uint256 internal constant _ROLE_92 = 1 << 92;
uint256 internal constant _ROLE_93 = 1 << 93;
uint256 internal constant _ROLE_94 = 1 << 94;
uint256 internal constant _ROLE_95 = 1 << 95;
uint256 internal constant _ROLE_96 = 1 << 96;
uint256 internal constant _ROLE_97 = 1 << 97;
uint256 internal constant _ROLE_98 = 1 << 98;
uint256 internal constant _ROLE_99 = 1 << 99;
uint256 internal constant _ROLE_100 = 1 << 100;
uint256 internal constant _ROLE_101 = 1 << 101;
uint256 internal constant _ROLE_102 = 1 << 102;
uint256 internal constant _ROLE_103 = 1 << 103;
uint256 internal constant _ROLE_104 = 1 << 104;
uint256 internal constant _ROLE_105 = 1 << 105;
uint256 internal constant _ROLE_106 = 1 << 106;
uint256 internal constant _ROLE_107 = 1 << 107;
uint256 internal constant _ROLE_108 = 1 << 108;
uint256 internal constant _ROLE_109 = 1 << 109;
uint256 internal constant _ROLE_110 = 1 << 110;
uint256 internal constant _ROLE_111 = 1 << 111;
uint256 internal constant _ROLE_112 = 1 << 112;
uint256 internal constant _ROLE_113 = 1 << 113;
uint256 internal constant _ROLE_114 = 1 << 114;
uint256 internal constant _ROLE_115 = 1 << 115;
uint256 internal constant _ROLE_116 = 1 << 116;
uint256 internal constant _ROLE_117 = 1 << 117;
uint256 internal constant _ROLE_118 = 1 << 118;
uint256 internal constant _ROLE_119 = 1 << 119;
uint256 internal constant _ROLE_120 = 1 << 120;
uint256 internal constant _ROLE_121 = 1 << 121;
uint256 internal constant _ROLE_122 = 1 << 122;
uint256 internal constant _ROLE_123 = 1 << 123;
uint256 internal constant _ROLE_124 = 1 << 124;
uint256 internal constant _ROLE_125 = 1 << 125;
uint256 internal constant _ROLE_126 = 1 << 126;
uint256 internal constant _ROLE_127 = 1 << 127;
uint256 internal constant _ROLE_128 = 1 << 128;
uint256 internal constant _ROLE_129 = 1 << 129;
uint256 internal constant _ROLE_130 = 1 << 130;
uint256 internal constant _ROLE_131 = 1 << 131;
uint256 internal constant _ROLE_132 = 1 << 132;
uint256 internal constant _ROLE_133 = 1 << 133;
uint256 internal constant _ROLE_134 = 1 << 134;
uint256 internal constant _ROLE_135 = 1 << 135;
uint256 internal constant _ROLE_136 = 1 << 136;
uint256 internal constant _ROLE_137 = 1 << 137;
uint256 internal constant _ROLE_138 = 1 << 138;
uint256 internal constant _ROLE_139 = 1 << 139;
uint256 internal constant _ROLE_140 = 1 << 140;
uint256 internal constant _ROLE_141 = 1 << 141;
uint256 internal constant _ROLE_142 = 1 << 142;
uint256 internal constant _ROLE_143 = 1 << 143;
uint256 internal constant _ROLE_144 = 1 << 144;
uint256 internal constant _ROLE_145 = 1 << 145;
uint256 internal constant _ROLE_146 = 1 << 146;
uint256 internal constant _ROLE_147 = 1 << 147;
uint256 internal constant _ROLE_148 = 1 << 148;
uint256 internal constant _ROLE_149 = 1 << 149;
uint256 internal constant _ROLE_150 = 1 << 150;
uint256 internal constant _ROLE_151 = 1 << 151;
uint256 internal constant _ROLE_152 = 1 << 152;
uint256 internal constant _ROLE_153 = 1 << 153;
uint256 internal constant _ROLE_154 = 1 << 154;
uint256 internal constant _ROLE_155 = 1 << 155;
uint256 internal constant _ROLE_156 = 1 << 156;
uint256 internal constant _ROLE_157 = 1 << 157;
uint256 internal constant _ROLE_158 = 1 << 158;
uint256 internal constant _ROLE_159 = 1 << 159;
uint256 internal constant _ROLE_160 = 1 << 160;
uint256 internal constant _ROLE_161 = 1 << 161;
uint256 internal constant _ROLE_162 = 1 << 162;
uint256 internal constant _ROLE_163 = 1 << 163;
uint256 internal constant _ROLE_164 = 1 << 164;
uint256 internal constant _ROLE_165 = 1 << 165;
uint256 internal constant _ROLE_166 = 1 << 166;
uint256 internal constant _ROLE_167 = 1 << 167;
uint256 internal constant _ROLE_168 = 1 << 168;
uint256 internal constant _ROLE_169 = 1 << 169;
uint256 internal constant _ROLE_170 = 1 << 170;
uint256 internal constant _ROLE_171 = 1 << 171;
uint256 internal constant _ROLE_172 = 1 << 172;
uint256 internal constant _ROLE_173 = 1 << 173;
uint256 internal constant _ROLE_174 = 1 << 174;
uint256 internal constant _ROLE_175 = 1 << 175;
uint256 internal constant _ROLE_176 = 1 << 176;
uint256 internal constant _ROLE_177 = 1 << 177;
uint256 internal constant _ROLE_178 = 1 << 178;
uint256 internal constant _ROLE_179 = 1 << 179;
uint256 internal constant _ROLE_180 = 1 << 180;
uint256 internal constant _ROLE_181 = 1 << 181;
uint256 internal constant _ROLE_182 = 1 << 182;
uint256 internal constant _ROLE_183 = 1 << 183;
uint256 internal constant _ROLE_184 = 1 << 184;
uint256 internal constant _ROLE_185 = 1 << 185;
uint256 internal constant _ROLE_186 = 1 << 186;
uint256 internal constant _ROLE_187 = 1 << 187;
uint256 internal constant _ROLE_188 = 1 << 188;
uint256 internal constant _ROLE_189 = 1 << 189;
uint256 internal constant _ROLE_190 = 1 << 190;
uint256 internal constant _ROLE_191 = 1 << 191;
uint256 internal constant _ROLE_192 = 1 << 192;
uint256 internal constant _ROLE_193 = 1 << 193;
uint256 internal constant _ROLE_194 = 1 << 194;
uint256 internal constant _ROLE_195 = 1 << 195;
uint256 internal constant _ROLE_196 = 1 << 196;
uint256 internal constant _ROLE_197 = 1 << 197;
uint256 internal constant _ROLE_198 = 1 << 198;
uint256 internal constant _ROLE_199 = 1 << 199;
uint256 internal constant _ROLE_200 = 1 << 200;
uint256 internal constant _ROLE_201 = 1 << 201;
uint256 internal constant _ROLE_202 = 1 << 202;
uint256 internal constant _ROLE_203 = 1 << 203;
uint256 internal constant _ROLE_204 = 1 << 204;
uint256 internal constant _ROLE_205 = 1 << 205;
uint256 internal constant _ROLE_206 = 1 << 206;
uint256 internal constant _ROLE_207 = 1 << 207;
uint256 internal constant _ROLE_208 = 1 << 208;
uint256 internal constant _ROLE_209 = 1 << 209;
uint256 internal constant _ROLE_210 = 1 << 210;
uint256 internal constant _ROLE_211 = 1 << 211;
uint256 internal constant _ROLE_212 = 1 << 212;
uint256 internal constant _ROLE_213 = 1 << 213;
uint256 internal constant _ROLE_214 = 1 << 214;
uint256 internal constant _ROLE_215 = 1 << 215;
uint256 internal constant _ROLE_216 = 1 << 216;
uint256 internal constant _ROLE_217 = 1 << 217;
uint256 internal constant _ROLE_218 = 1 << 218;
uint256 internal constant _ROLE_219 = 1 << 219;
uint256 internal constant _ROLE_220 = 1 << 220;
uint256 internal constant _ROLE_221 = 1 << 221;
uint256 internal constant _ROLE_222 = 1 << 222;
uint256 internal constant _ROLE_223 = 1 << 223;
uint256 internal constant _ROLE_224 = 1 << 224;
uint256 internal constant _ROLE_225 = 1 << 225;
uint256 internal constant _ROLE_226 = 1 << 226;
uint256 internal constant _ROLE_227 = 1 << 227;
uint256 internal constant _ROLE_228 = 1 << 228;
uint256 internal constant _ROLE_229 = 1 << 229;
uint256 internal constant _ROLE_230 = 1 << 230;
uint256 internal constant _ROLE_231 = 1 << 231;
uint256 internal constant _ROLE_232 = 1 << 232;
uint256 internal constant _ROLE_233 = 1 << 233;
uint256 internal constant _ROLE_234 = 1 << 234;
uint256 internal constant _ROLE_235 = 1 << 235;
uint256 internal constant _ROLE_236 = 1 << 236;
uint256 internal constant _ROLE_237 = 1 << 237;
uint256 internal constant _ROLE_238 = 1 << 238;
uint256 internal constant _ROLE_239 = 1 << 239;
uint256 internal constant _ROLE_240 = 1 << 240;
uint256 internal constant _ROLE_241 = 1 << 241;
uint256 internal constant _ROLE_242 = 1 << 242;
uint256 internal constant _ROLE_243 = 1 << 243;
uint256 internal constant _ROLE_244 = 1 << 244;
uint256 internal constant _ROLE_245 = 1 << 245;
uint256 internal constant _ROLE_246 = 1 << 246;
uint256 internal constant _ROLE_247 = 1 << 247;
uint256 internal constant _ROLE_248 = 1 << 248;
uint256 internal constant _ROLE_249 = 1 << 249;
uint256 internal constant _ROLE_250 = 1 << 250;
uint256 internal constant _ROLE_251 = 1 << 251;
uint256 internal constant _ROLE_252 = 1 << 252;
uint256 internal constant _ROLE_253 = 1 << 253;
uint256 internal constant _ROLE_254 = 1 << 254;
uint256 internal constant _ROLE_255 = 1 << 255;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Initializable mixin for the upgradeable contracts.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Initializable.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/proxy/utils/Initializable.sol)
abstract contract Initializable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The contract is already initialized.
error InvalidInitialization();
/// @dev The contract is not initializing.
error NotInitializing();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Triggered when the contract has been initialized.
event Initialized(uint64 version);
/// @dev `keccak256(bytes("Initialized(uint64)"))`.
bytes32 private constant _INTIALIZED_EVENT_SIGNATURE =
0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The default initializable slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_INITIALIZABLE_SLOT")))))`.
///
/// Bits Layout:
/// - [0] `initializing`
/// - [1..64] `initializedVersion`
bytes32 private constant _INITIALIZABLE_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf601132;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTRUCTOR */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
constructor() {
// Construction time check to ensure that `_initializableSlot()` is not
// overridden to zero. Will be optimized away if there is no revert.
require(_initializableSlot() != bytes32(0));
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return a non-zero custom storage slot if required.
function _initializableSlot() internal pure virtual returns (bytes32) {
return _INITIALIZABLE_SLOT;
}
/// @dev Guards an initializer function so that it can be invoked at most once.
///
/// You can guard a function with `onlyInitializing` such that it can be called
/// through a function guarded with `initializer`.
///
/// This is similar to `reinitializer(1)`, except that in the context of a constructor,
/// an `initializer` guarded function can be invoked multiple times.
/// This can be useful during testing and is not expected to be used in production.
///
/// Emits an {Initialized} event.
modifier initializer() virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
let i := sload(s)
// Set `initializing` to 1, `initializedVersion` to 1.
sstore(s, 3)
// If `!(initializing == 0 && initializedVersion == 0)`.
if i {
// If `!(address(this).code.length == 0 && initializedVersion == 1)`.
if iszero(lt(extcodesize(address()), eq(shr(1, i), 1))) {
mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`.
revert(0x1c, 0x04)
}
s := shl(shl(255, i), s) // Skip initializing if `initializing == 1`.
}
}
_;
/// @solidity memory-safe-assembly
assembly {
if s {
// Set `initializing` to 0, `initializedVersion` to 1.
sstore(s, 2)
// Emit the {Initialized} event.
mstore(0x20, 1)
log1(0x20, 0x20, _INTIALIZED_EVENT_SIGNATURE)
}
}
}
/// @dev Guards an reinitialzer function so that it can be invoked at most once.
///
/// You can guard a function with `onlyInitializing` such that it can be called
/// through a function guarded with `reinitializer`.
///
/// Emits an {Initialized} event.
modifier reinitializer(uint64 version) virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
// Clean upper bits, and shift left by 1 to make space for the initializing bit.
version := shl(1, and(version, 0xffffffffffffffff))
let i := sload(s)
// If `initializing == 1 || initializedVersion >= version`.
if iszero(lt(and(i, 1), lt(i, version))) {
mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`.
revert(0x1c, 0x04)
}
// Set `initializing` to 1, `initializedVersion` to `version`.
sstore(s, or(1, version))
}
_;
/// @solidity memory-safe-assembly
assembly {
// Set `initializing` to 0, `initializedVersion` to `version`.
sstore(s, version)
// Emit the {Initialized} event.
mstore(0x20, shr(1, version))
log1(0x20, 0x20, _INTIALIZED_EVENT_SIGNATURE)
}
}
/// @dev Guards a function such that it can only be called in the scope
/// of a function guarded with `initializer` or `reinitializer`.
modifier onlyInitializing() virtual {
_checkInitializing();
_;
}
/// @dev Reverts if the contract is not initializing.
function _checkInitializing() internal view virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
if iszero(and(1, sload(s))) {
mstore(0x00, 0xd7e6bcf8) // `NotInitializing()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Locks any future initializations by setting the initialized version to `2**64 - 1`.
///
/// Calling this in the constructor will prevent the contract from being initialized
/// or reinitialized. 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 called.
function _disableInitializers() internal virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
let i := sload(s)
if and(i, 1) {
mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`.
revert(0x1c, 0x04)
}
let uint64max := 0xffffffffffffffff
if iszero(eq(shr(1, i), uint64max)) {
// Set `initializing` to 0, `initializedVersion` to `2**64 - 1`.
sstore(s, shl(1, uint64max))
// Emit the {Initialized} event.
mstore(0x20, uint64max)
log1(0x20, 0x20, _INTIALIZED_EVENT_SIGNATURE)
}
}
}
/// @dev Returns the highest version that has been initialized.
function _getInitializedVersion() internal view virtual returns (uint64 version) {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
version := shr(1, sload(s))
}
}
/// @dev Returns whether the contract is currently initializing.
function _isInitializing() internal view virtual returns (bool result) {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
result := and(1, sload(s))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Contract that enables a single call to call multiple methods on itself.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Multicallable.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Multicallable.sol)
///
/// WARNING:
/// This implementation is NOT to be used with ERC2771 out-of-the-box.
/// https://blog.openzeppelin.com/arbitrary-address-spoofing-vulnerability-erc2771context-multicall-public-disclosure
/// This also applies to potentially other ERCs / patterns appending to the back of calldata.
///
/// We do NOT have a check for ERC2771, as we do not inherit from OpenZeppelin's context.
/// Moreover, it is infeasible and inefficient for us to add checks and mitigations
/// for all possible ERC / patterns appending to the back of calldata.
///
/// We would highly recommend using an alternative pattern such as
/// https://github.com/Vectorized/multicaller
/// which is more flexible, futureproof, and safer by default.
abstract contract Multicallable {
/// @dev Apply `delegatecall` with the current contract to each calldata in `data`,
/// and store the `abi.encode` formatted results of each `delegatecall` into `results`.
/// If any of the `delegatecall`s reverts, the entire context is reverted,
/// and the error is bubbled up.
///
/// By default, this function directly returns the results and terminates the call context.
/// If you need to add before and after actions to the multicall, please override this function.
function multicall(bytes[] calldata data) public payable virtual returns (bytes[] memory) {
// Revert if `msg.value` is non-zero by default to guard against double-spending.
// (See: https://www.paradigm.xyz/2021/08/two-rights-might-make-a-wrong)
//
// If you really need to pass in a `msg.value`, then you will have to
// override this function and add in any relevant before and after checks.
if (msg.value != 0) revert();
// `_multicallDirectReturn` returns the results directly and terminates the call context.
_multicallDirectReturn(_multicall(data));
}
/// @dev The inner logic of `multicall`.
/// This function is included so that you can override `multicall`
/// to add before and after actions, and use the `_multicallDirectReturn` function.
function _multicall(bytes[] calldata data) internal virtual returns (bytes32 results) {
/// @solidity memory-safe-assembly
assembly {
results := mload(0x40)
mstore(results, 0x20)
mstore(add(0x20, results), data.length)
let c := add(0x40, results)
let s := c
let end := shl(5, data.length)
calldatacopy(c, data.offset, end)
end := add(c, end)
let m := end
if data.length {
for {} 1 {} {
let o := add(data.offset, mload(c))
calldatacopy(m, add(o, 0x20), calldataload(o))
// forgefmt: disable-next-item
if iszero(delegatecall(gas(), address(), m, calldataload(o), codesize(), 0x00)) {
// Bubble up the revert if the delegatecall reverts.
returndatacopy(results, 0x00, returndatasize())
revert(results, returndatasize())
}
mstore(c, sub(m, s))
c := add(0x20, c)
// Append the `returndatasize()`, and the return data.
mstore(m, returndatasize())
let b := add(m, 0x20)
returndatacopy(b, 0x00, returndatasize())
// Advance `m` by `returndatasize() + 0x20`,
// rounded up to the next multiple of 32.
m := and(add(add(b, returndatasize()), 0x1f), 0xffffffffffffffe0)
mstore(add(b, returndatasize()), 0) // Zeroize the slot after the returndata.
if iszero(lt(c, end)) { break }
}
}
mstore(0x40, m) // Allocate memory.
results := or(shl(64, sub(m, results)), results) // Pack the bytes length into `results`.
}
}
/// @dev Decodes the `results` into an array of bytes.
/// This can be useful if you need to access the results or re-encode it.
function _multicallResultsToBytesArray(bytes32 results)
internal
pure
virtual
returns (bytes[] memory decoded)
{
/// @solidity memory-safe-assembly
assembly {
decoded := mload(0x40)
let c := and(0xffffffffffffffff, results) // Extract the offset.
mstore(decoded, mload(add(c, 0x20))) // Store the length.
let o := add(decoded, 0x20) // Start of elements in `decoded`.
let end := add(o, shl(5, mload(decoded)))
mstore(0x40, end) // Allocate memory.
let s := add(c, 0x40) // Start of elements in `results`.
let d := sub(s, o) // Difference between input and output pointers.
for {} iszero(eq(o, end)) { o := add(o, 0x20) } { mstore(o, add(mload(add(d, o)), s)) }
}
}
/// @dev Directly returns the `results` and terminates the current call context.
/// `results` must be from `_multicall`, else behavior is undefined.
function _multicallDirectReturn(bytes32 results) internal pure virtual {
/// @solidity memory-safe-assembly
assembly {
return(and(0xffffffffffffffff, results), shr(64, results))
}
}
}// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.10; uint256 constant BASIS_POINTS = 10_000; uint256 constant WAD = 1e18; address constant NATIVE_ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // Roles uint256 constant FEE_MANAGER_ROLE = 1 << 0; uint256 constant FEE_COLLECTOR_ROLE = 1 << 1; uint256 constant DEV_ROLE = 1 << 2; uint256 constant PAUSER_ROLE = 1 << 3; uint256 constant GOVERNANCE_ROLE = 1 << 4; uint256 constant CONNECTOR_REGISTRY_ROLE = 1 << 5; // TwoCrypto uint256 constant TARGET_INDEX = 0; uint256 constant PT_INDEX = 1; // Currency address constant WETH_ETHEREUM_MAINNET = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // Default fee split ratio (100% to Curator) uint16 constant DEFAULT_SPLIT_RATIO_BPS = uint16(BASIS_POINTS);
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;
library Errors {
error AccessManaged_Restricted();
error Expired();
error NotExpired();
error PrincipalToken_NotFactory();
error PrincipalToken_VerificationFailed(uint256 code);
error PrincipalToken_CollectRewardFailed();
error PrincipalToken_NotApprovedCollector();
error PrincipalToken_OnlyYieldToken();
error PrincipalToken_InsufficientSharesReceived();
error PrincipalToken_UnderlyingTokenBalanceChanged();
error PrincipalToken_Unstoppable();
error PrincipalToken_ProtectedToken();
error YieldToken_OnlyPrincipalToken();
// Module
error Module_CallFailed();
// FeeModule
error FeeModule_InvalidFeeParam();
error FeeModule_SplitFeeExceedsMaximum();
error FeeModule_SplitFeeMismatchDefault();
error FeeModule_SplitFeeTooLow();
error FeeModule_IssuanceFeeExceedsMaximum();
error FeeModule_PerformanceFeeExceedsMaximum();
error FeeModule_RedemptionFeeExceedsMaximum();
error FeeModule_PostSettlementFeeExceedsMaximum();
// RewardProxy
error RewardProxy_InconsistentRewardTokens();
error Factory_ModuleNotFound();
error Factory_InvalidExpiry();
error Factory_InvalidPoolDeployer();
error Factory_InvalidModule();
error Factory_FeeModuleRequired();
error Factory_PrincipalTokenNotFound();
error Factory_InvalidModuleType();
error Factory_InvalidAddress();
error Factory_InvalidSuite();
error Factory_CannotUpdateFeeModule();
error Factory_InvalidDecimals();
error PoolDeployer_FailedToDeployPool();
error Zap_LengthMismatch();
error Zap_TransactionTooOld();
error Zap_BadTwoCrypto();
error Zap_BadPrincipalToken();
error Zap_BadCallback();
error Zap_InconsistentETHReceived();
error Zap_InsufficientETH();
error Zap_InsufficientPrincipalOutput();
error Zap_InsufficientTokenOutput();
error Zap_InsufficientUnderlyingOutput();
error Zap_InsufficientYieldTokenOutput();
error Zap_InsufficientPrincipalTokenOutput();
error Zap_DebtExceedsUnderlyingReceived();
error Zap_PullYieldTokenGreaterThanInput();
error Zap_BadPoolDeployer();
// Resolver errors
error Resolver_ConversionFailed();
error Resolver_InvalidDecimals();
error Resolver_ZeroAddress();
// VaultConnectorRegistry errors
error VCRegistry_ConnectorNotFound();
// ERC4626Connector errors
error ERC4626Connector_InvalidToken();
error ERC4626Connector_InvalidETHAmount();
error ERC4626Connector_UnexpectedETH();
// WrapperConnector errors
error WrapperConnector_InvalidETHAmount();
error WrapperConnector_UnexpectedETH();
// WrapperFactory errors
error WrapperFactory_ImplementationNotSet();
// Quoter errors
error Quoter_ERC4626FallbackCallFailed();
error Quoter_ConnectorInvalidToken();
error Quoter_InsufficientUnderlyingOutput();
error Quoter_MaximumYtOutputReached();
// ConversionLib errors
error ConversionLib_NegativeYtPrice();
// AggregationRouter errors
error AggregationRouter_UnsupportedRouter();
error AggregationRouter_SwapFailed();
error AggregationRouter_ZeroReturn();
error AggregationRouter_InvalidMsgValue();
// DefaultConnectorFactory errors
error DefaultConnectorFactory_TargetNotERC4626();
error DefaultConnectorFactory_InvalidToken();
// Lens errors
error Lens_LengthMismatch();
// ERC4626Wrapper errors
error ERC4626Wrapper_TokenNotListed();
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
revert(0x1c, 0x04)
}
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(_OWNER_SLOT, newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(_OWNER_SLOT)
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}{
"remappings": [
"@openzeppelin/=node_modules/@openzeppelin/",
"forge-std/=node_modules/forge-std/",
"halmos-cheatcodes/=node_modules/halmos-cheatcodes/",
"solady/=node_modules/solady/"
],
"optimizer": {
"enabled": true,
"runs": 1
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"TargetFunctionRolesGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"TargetFunctionRolesRevoked","type":"event"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"canCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantTargetFunctionRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"curator","type":"address"}],"name":"initializeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeTargetFunctionRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
608060405234801561000f575f80fd5b50610b968061001d5f395ff3fe6080604052600436106100d8575f3560e01c8063183a4f6e146100dc5780631c10893f146100f15780631cd64df41461010457806325692962146101385780632de94807146101405780634655c7a61461016d5780634a4ee7b1146101805780634caa6c3014610193578063514e62fc146101a657806354d1f13d146101c5578063715018a6146101cd5780638c5f36bb146101d55780638da5cb5b146101f4578063ac9650d81461021f578063b70096131461023f578063f04e283e1461025e578063f2fde38b14610271578063fee81cf414610284575b5f80fd5b6100ef6100ea366004610884565b6102b5565b005b6100ef6100ff3660046108b6565b6102c2565b34801561010f575f80fd5b5061012361011e3660046108b6565b610317565b60405190151581526020015b60405180910390f35b6100ef61032e565b34801561014b575f80fd5b5061015f61015a3660046108de565b61037a565b60405190815260200161012f565b6100ef61017b366004610945565b610391565b6100ef61018e3660046108b6565b6103fb565b6100ef6101a1366004610945565b610424565b3480156101b1575f80fd5b506101236101c03660046108b6565b610486565b6100ef61049b565b6100ef6104d4565b3480156101e0575f80fd5b506100ef6101ef3660046108de565b6104e7565b3480156101ff575f80fd5b50638b78c6d819546040516001600160a01b03909116815260200161012f565b61023261022d36600461099a565b61055f565b60405161012f91906109d8565b34801561024a575f80fd5b50610123610259366004610a7c565b61057d565b6100ef61026c3660046108de565b6105bb565b6100ef61027f3660046108de565b6105f5565b34801561028f575f80fd5b5061015f61029e3660046108de565b63389a75e1600c9081525f91909152602090205490565b6102bf338261061b565b50565b305f908152602081905260408120610309916102e16004823681610abc565b6102ea91610ae3565b6001600160e01b031916815260208101919091526040015f2054610626565b6103138282610657565b5050565b5f81826103238561037a565b161490505b92915050565b5f6202a3006001600160401b03164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b638b78c6d8600c9081525f91909152602090205490565b305f9081526020819052604081206103b0916102e16004823681610abc565b815f5b8181146103f3576103eb868686848181106103d0576103d0610b13565b90506020020160208101906103e59190610b27565b85610663565b6001016103b3565b505050505050565b305f90815260208190526040812061041a916102e16004823681610abc565b610313828261061b565b305f908152602081905260408120610443916102e16004823681610abc565b815f5b8181146103f35761047e8686868481811061046357610463610b13565b90506020020160208101906104789190610b27565b856106c1565b600101610446565b5f816104918461037a565b1615159392505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b6104dc610720565b6104e55f61073a565b565b63409feecd19805460038255801561051d5760018160011c14303b106105145763f92ee8a95f526004601cfd5b818160ff1b1b91505b5061052782610764565b8015610313576002815560016020527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602080a15050565b6060341561056b575f80fd5b610328610578848461078c565b61081d565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091528120546105b3908590610486565b949350505050565b6105c3610720565b63389a75e1600c52805f526020600c2080544211156105e957636f5e88185f526004601cfd5b5f90556102bf8161073a565b6105fd610720565b8060601b61061257637448fbae5f526004601cfd5b6102bf8161073a565b61031382825f61082d565b638b78c6d8195433146102bf57638b78c6d8600c52335f52806020600c2054166102bf576382b429005f526004601cfd5b6103138282600161082d565b6001600160a01b0383165f818152602081815260408083206001600160e01b03198716808552925280832080548617905551849391927fd053bb6778e51c6660311c3c9a03f295747d133b13fa0e17a9774768f086014491a4505050565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855292528083208054861916905551849391927ff1c6d2aad12b25c08503bd37d7c2455b531095ee75dbdfc6b92aaa10e84f9c5591a4505050565b638b78c6d8195433146104e5576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182905f80516020610b418339815191525f80a355565b6001600160a01b0316638b78c6d819819055805f5f80516020610b418339815191528180a350565b5f60405190506020815281816020015280604001808360051b808684378201808515610805575b8351870180356020820183375f38823584305af46107d3573d5f873e3d86fd5b5082810384523d815260209384019381013d5f823e5f3d8201523d01601f016020600160401b031690508184106107b3575b806040528485820360401b1794505050505092915050565b8060401c816001600160401b0316f35b638b78c6d8600c52825f526020600c2080548381178361084e575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3505050505050565b5f60208284031215610894575f80fd5b5035919050565b80356001600160a01b03811681146108b1575f80fd5b919050565b5f80604083850312156108c7575f80fd5b6108d08361089b565b946020939093013593505050565b5f602082840312156108ee575f80fd5b6108f78261089b565b9392505050565b5f8083601f84011261090e575f80fd5b5081356001600160401b03811115610924575f80fd5b6020830191508360208260051b850101111561093e575f80fd5b9250929050565b5f805f8060608587031215610958575f80fd5b6109618561089b565b935060208501356001600160401b0381111561097b575f80fd5b610987878288016108fe565b9598909750949560400135949350505050565b5f80602083850312156109ab575f80fd5b82356001600160401b038111156109c0575f80fd5b6109cc858286016108fe565b90969095509350505050565b5f602080830181845280855180835260408601915060408160051b87010192508387015f5b82811015610a5857878503603f19018452815180518087525f5b81811015610a32578281018901518882018a01528801610a17565b505f878201890152601f01601f19169095018601945092850192908501906001016109fd565b5092979650505050505050565b80356001600160e01b0319811681146108b1575f80fd5b5f805f60608486031215610a8e575f80fd5b610a978461089b565b9250610aa56020850161089b565b9150610ab360408501610a65565b90509250925092565b5f8085851115610aca575f80fd5b83861115610ad6575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015610b0b5780818660040360031b1b83161692505b505092915050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610b37575f80fd5b6108f782610a6556fe8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a264697066735822122093e7d87507e82196c4552c23fffb2f3f884ce751cdad5c33a5e2720b8ba9a84664736f6c63430008180033
Deployed Bytecode
0x6080604052600436106100d8575f3560e01c8063183a4f6e146100dc5780631c10893f146100f15780631cd64df41461010457806325692962146101385780632de94807146101405780634655c7a61461016d5780634a4ee7b1146101805780634caa6c3014610193578063514e62fc146101a657806354d1f13d146101c5578063715018a6146101cd5780638c5f36bb146101d55780638da5cb5b146101f4578063ac9650d81461021f578063b70096131461023f578063f04e283e1461025e578063f2fde38b14610271578063fee81cf414610284575b5f80fd5b6100ef6100ea366004610884565b6102b5565b005b6100ef6100ff3660046108b6565b6102c2565b34801561010f575f80fd5b5061012361011e3660046108b6565b610317565b60405190151581526020015b60405180910390f35b6100ef61032e565b34801561014b575f80fd5b5061015f61015a3660046108de565b61037a565b60405190815260200161012f565b6100ef61017b366004610945565b610391565b6100ef61018e3660046108b6565b6103fb565b6100ef6101a1366004610945565b610424565b3480156101b1575f80fd5b506101236101c03660046108b6565b610486565b6100ef61049b565b6100ef6104d4565b3480156101e0575f80fd5b506100ef6101ef3660046108de565b6104e7565b3480156101ff575f80fd5b50638b78c6d819546040516001600160a01b03909116815260200161012f565b61023261022d36600461099a565b61055f565b60405161012f91906109d8565b34801561024a575f80fd5b50610123610259366004610a7c565b61057d565b6100ef61026c3660046108de565b6105bb565b6100ef61027f3660046108de565b6105f5565b34801561028f575f80fd5b5061015f61029e3660046108de565b63389a75e1600c9081525f91909152602090205490565b6102bf338261061b565b50565b305f908152602081905260408120610309916102e16004823681610abc565b6102ea91610ae3565b6001600160e01b031916815260208101919091526040015f2054610626565b6103138282610657565b5050565b5f81826103238561037a565b161490505b92915050565b5f6202a3006001600160401b03164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b638b78c6d8600c9081525f91909152602090205490565b305f9081526020819052604081206103b0916102e16004823681610abc565b815f5b8181146103f3576103eb868686848181106103d0576103d0610b13565b90506020020160208101906103e59190610b27565b85610663565b6001016103b3565b505050505050565b305f90815260208190526040812061041a916102e16004823681610abc565b610313828261061b565b305f908152602081905260408120610443916102e16004823681610abc565b815f5b8181146103f35761047e8686868481811061046357610463610b13565b90506020020160208101906104789190610b27565b856106c1565b600101610446565b5f816104918461037a565b1615159392505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b6104dc610720565b6104e55f61073a565b565b63409feecd19805460038255801561051d5760018160011c14303b106105145763f92ee8a95f526004601cfd5b818160ff1b1b91505b5061052782610764565b8015610313576002815560016020527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602080a15050565b6060341561056b575f80fd5b610328610578848461078c565b61081d565b6001600160a01b0382165f908152602081815260408083206001600160e01b0319851684529091528120546105b3908590610486565b949350505050565b6105c3610720565b63389a75e1600c52805f526020600c2080544211156105e957636f5e88185f526004601cfd5b5f90556102bf8161073a565b6105fd610720565b8060601b61061257637448fbae5f526004601cfd5b6102bf8161073a565b61031382825f61082d565b638b78c6d8195433146102bf57638b78c6d8600c52335f52806020600c2054166102bf576382b429005f526004601cfd5b6103138282600161082d565b6001600160a01b0383165f818152602081815260408083206001600160e01b03198716808552925280832080548617905551849391927fd053bb6778e51c6660311c3c9a03f295747d133b13fa0e17a9774768f086014491a4505050565b6001600160a01b0383165f818152602081815260408083206001600160e01b0319871680855292528083208054861916905551849391927ff1c6d2aad12b25c08503bd37d7c2455b531095ee75dbdfc6b92aaa10e84f9c5591a4505050565b638b78c6d8195433146104e5576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182905f80516020610b418339815191525f80a355565b6001600160a01b0316638b78c6d819819055805f5f80516020610b418339815191528180a350565b5f60405190506020815281816020015280604001808360051b808684378201808515610805575b8351870180356020820183375f38823584305af46107d3573d5f873e3d86fd5b5082810384523d815260209384019381013d5f823e5f3d8201523d01601f016020600160401b031690508184106107b3575b806040528485820360401b1794505050505092915050565b8060401c816001600160401b0316f35b638b78c6d8600c52825f526020600c2080548381178361084e575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3505050505050565b5f60208284031215610894575f80fd5b5035919050565b80356001600160a01b03811681146108b1575f80fd5b919050565b5f80604083850312156108c7575f80fd5b6108d08361089b565b946020939093013593505050565b5f602082840312156108ee575f80fd5b6108f78261089b565b9392505050565b5f8083601f84011261090e575f80fd5b5081356001600160401b03811115610924575f80fd5b6020830191508360208260051b850101111561093e575f80fd5b9250929050565b5f805f8060608587031215610958575f80fd5b6109618561089b565b935060208501356001600160401b0381111561097b575f80fd5b610987878288016108fe565b9598909750949560400135949350505050565b5f80602083850312156109ab575f80fd5b82356001600160401b038111156109c0575f80fd5b6109cc858286016108fe565b90969095509350505050565b5f602080830181845280855180835260408601915060408160051b87010192508387015f5b82811015610a5857878503603f19018452815180518087525f5b81811015610a32578281018901518882018a01528801610a17565b505f878201890152601f01601f19169095018601945092850192908501906001016109fd565b5092979650505050505050565b80356001600160e01b0319811681146108b1575f80fd5b5f805f60608486031215610a8e575f80fd5b610a978461089b565b9250610aa56020850161089b565b9150610ab360408501610a65565b90509250925092565b5f8085851115610aca575f80fd5b83861115610ad6575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015610b0b5780818660040360031b1b83161692505b505092915050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610b37575f80fd5b6108f782610a6556fe8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a264697066735822122093e7d87507e82196c4552c23fffb2f3f884ce751cdad5c33a5e2720b8ba9a84664736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.