Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 15998126 | 689 days ago | IN | 0 ETH | 0.02945334 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
OlympusTreasury
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 10 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.15; import {ERC20} from "solmate/tokens/ERC20.sol"; import {ReentrancyGuard} from "solmate/utils/ReentrancyGuard.sol"; import {TransferHelper} from "libraries/TransferHelper.sol"; import {TRSRYv1} from "src/modules/TRSRY/TRSRY.v1.sol"; import "src/Kernel.sol"; /// @notice Treasury holds all other assets under the control of the protocol. contract OlympusTreasury is TRSRYv1, ReentrancyGuard { using TransferHelper for ERC20; //============================================================================================// // MODULE SETUP // //============================================================================================// constructor(Kernel kernel_) Module(kernel_) { active = true; } /// @inheritdoc Module function KEYCODE() public pure override returns (Keycode) { return toKeycode("TRSRY"); } /// @inheritdoc Module function VERSION() external pure override returns (uint8 major, uint8 minor) { major = 1; minor = 0; } //============================================================================================// // CORE FUNCTIONS // //============================================================================================// /// @inheritdoc TRSRYv1 function increaseWithdrawApproval( address withdrawer_, ERC20 token_, uint256 amount_ ) external override permissioned { uint256 approval = withdrawApproval[withdrawer_][token_]; uint256 newAmount = type(uint256).max - approval <= amount_ ? type(uint256).max : approval + amount_; withdrawApproval[withdrawer_][token_] = newAmount; emit IncreaseWithdrawApproval(withdrawer_, token_, newAmount); } /// @inheritdoc TRSRYv1 function decreaseWithdrawApproval( address withdrawer_, ERC20 token_, uint256 amount_ ) external override permissioned { uint256 approval = withdrawApproval[withdrawer_][token_]; uint256 newAmount = approval <= amount_ ? 0 : approval - amount_; withdrawApproval[withdrawer_][token_] = newAmount; emit DecreaseWithdrawApproval(withdrawer_, token_, newAmount); } /// @inheritdoc TRSRYv1 function withdrawReserves( address to_, ERC20 token_, uint256 amount_ ) public override permissioned onlyWhileActive { withdrawApproval[msg.sender][token_] -= amount_; token_.safeTransfer(to_, amount_); emit Withdrawal(msg.sender, to_, token_, amount_); } // ========= DEBT FUNCTIONS ========= // /// @inheritdoc TRSRYv1 function increaseDebtorApproval( address debtor_, ERC20 token_, uint256 amount_ ) external override permissioned { uint256 newAmount = debtApproval[debtor_][token_] + amount_; debtApproval[debtor_][token_] = newAmount; emit IncreaseDebtorApproval(debtor_, token_, newAmount); } /// @inheritdoc TRSRYv1 function decreaseDebtorApproval( address debtor_, ERC20 token_, uint256 amount_ ) external override permissioned { uint256 newAmount = debtApproval[debtor_][token_] - amount_; debtApproval[debtor_][token_] = newAmount; emit DecreaseDebtorApproval(debtor_, token_, newAmount); } /// @inheritdoc TRSRYv1 function incurDebt(ERC20 token_, uint256 amount_) external override permissioned onlyWhileActive { debtApproval[msg.sender][token_] -= amount_; // Add debt to caller reserveDebt[token_][msg.sender] += amount_; totalDebt[token_] += amount_; token_.safeTransfer(msg.sender, amount_); emit DebtIncurred(token_, msg.sender, amount_); } /// @inheritdoc TRSRYv1 function repayDebt( address debtor_, ERC20 token_, uint256 amount_ ) external override permissioned nonReentrant { if (reserveDebt[token_][debtor_] == 0) revert TRSRY_NoDebtOutstanding(); // Deposit from caller first (to handle nonstandard token transfers) uint256 prevBalance = token_.balanceOf(address(this)); token_.safeTransferFrom(msg.sender, address(this), amount_); uint256 received = token_.balanceOf(address(this)) - prevBalance; // Choose minimum between passed-in amount and received amount if (received > amount_) received = amount_; // Subtract debt from debtor reserveDebt[token_][debtor_] -= received; totalDebt[token_] -= received; emit DebtRepaid(token_, debtor_, received); } /// @inheritdoc TRSRYv1 function setDebt( address debtor_, ERC20 token_, uint256 amount_ ) external override permissioned { uint256 oldDebt = reserveDebt[token_][debtor_]; reserveDebt[token_][debtor_] = amount_; if (oldDebt < amount_) totalDebt[token_] += amount_ - oldDebt; else totalDebt[token_] -= oldDebt - amount_; emit DebtSet(token_, debtor_, amount_); } /// @inheritdoc TRSRYv1 function deactivate() external override permissioned { active = false; } /// @inheritdoc TRSRYv1 function activate() external override permissioned { active = true; } //============================================================================================// // VIEW FUNCTIONS // //============================================================================================// /// @inheritdoc TRSRYv1 function getReserveBalance(ERC20 token_) external view override returns (uint256) { return token_.balanceOf(address(this)) + totalDebt[token_]; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private locked = 1; modifier nonReentrant() virtual { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.15; // ███████ █████ █████ █████ ██████ ██████ ███████████ █████ █████ █████████ // ███░░░░░███ ░░███ ░░███ ░░███ ░░██████ ██████ ░░███░░░░░███░░███ ░░███ ███░░░░░███ // ███ ░░███ ░███ ░░███ ███ ░███░█████░███ ░███ ░███ ░███ ░███ ░███ ░░░ // ░███ ░███ ░███ ░░█████ ░███░░███ ░███ ░██████████ ░███ ░███ ░░█████████ // ░███ ░███ ░███ ░░███ ░███ ░░░ ░███ ░███░░░░░░ ░███ ░███ ░░░░░░░░███ // ░░███ ███ ░███ █ ░███ ░███ ░███ ░███ ░███ ░███ ███ ░███ // ░░░███████░ ███████████ █████ █████ █████ █████ ░░████████ ░░█████████ // ░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░ ░░░░░░░░░ //============================================================================================// // GLOBAL TYPES // //============================================================================================// /// @notice Actions to trigger state changes in the kernel. Passed by the executor enum Actions { InstallModule, UpgradeModule, ActivatePolicy, DeactivatePolicy, ChangeExecutor, MigrateKernel } /// @notice Used by executor to select an action and a target contract for a kernel action struct Instruction { Actions action; address target; } /// @notice Used to define which module functions a policy needs access to struct Permissions { Keycode keycode; bytes4 funcSelector; } type Keycode is bytes5; //============================================================================================// // UTIL FUNCTIONS // //============================================================================================// error TargetNotAContract(address target_); error InvalidKeycode(Keycode keycode_); // solhint-disable-next-line func-visibility function toKeycode(bytes5 keycode_) pure returns (Keycode) { return Keycode.wrap(keycode_); } // solhint-disable-next-line func-visibility function fromKeycode(Keycode keycode_) pure returns (bytes5) { return Keycode.unwrap(keycode_); } // solhint-disable-next-line func-visibility function ensureContract(address target_) view { if (target_.code.length == 0) revert TargetNotAContract(target_); } // solhint-disable-next-line func-visibility function ensureValidKeycode(Keycode keycode_) pure { bytes5 unwrapped = Keycode.unwrap(keycode_); for (uint256 i = 0; i < 5; ) { bytes1 char = unwrapped[i]; if (char < 0x41 || char > 0x5A) revert InvalidKeycode(keycode_); // A-Z only unchecked { i++; } } } //============================================================================================// // COMPONENTS // //============================================================================================// /// @notice Generic adapter interface for kernel access in modules and policies. abstract contract KernelAdapter { error KernelAdapter_OnlyKernel(address caller_); Kernel public kernel; constructor(Kernel kernel_) { kernel = kernel_; } /// @notice Modifier to restrict functions to be called only by kernel. modifier onlyKernel() { if (msg.sender != address(kernel)) revert KernelAdapter_OnlyKernel(msg.sender); _; } /// @notice Function used by kernel when migrating to a new kernel. function changeKernel(Kernel newKernel_) external onlyKernel { kernel = newKernel_; } } /// @notice Base level extension of the kernel. Modules act as independent state components to be /// interacted with and mutated through policies. /// @dev Modules are installed and uninstalled via the executor. abstract contract Module is KernelAdapter { error Module_PolicyNotPermitted(address policy_); constructor(Kernel kernel_) KernelAdapter(kernel_) {} /// @notice Modifier to restrict which policies have access to module functions. modifier permissioned() { if (!kernel.modulePermissions(KEYCODE(), Policy(msg.sender), msg.sig)) revert Module_PolicyNotPermitted(msg.sender); _; } /// @notice 5 byte identifier for a module. function KEYCODE() public pure virtual returns (Keycode) {} /// @notice Returns which semantic version of a module is being implemented. /// @return major - Major version upgrade indicates breaking change to the interface. /// @return minor - Minor version change retains backward-compatible interface. function VERSION() external pure virtual returns (uint8 major, uint8 minor) {} /// @notice Initialization function for the module /// @dev This function is called when the module is installed or upgraded by the kernel. /// @dev MUST BE GATED BY onlyKernel. Used to encompass any initialization or upgrade logic. function INIT() external virtual onlyKernel {} } /// @notice Policies are application logic and external interface for the kernel and installed modules. /// @dev Policies are activated and deactivated in the kernel by the executor. /// @dev Module dependencies and function permissions must be defined in appropriate functions. abstract contract Policy is KernelAdapter { error Policy_ModuleDoesNotExist(Keycode keycode_); constructor(Kernel kernel_) KernelAdapter(kernel_) {} /// @notice Easily accessible indicator for if a policy is activated or not. function isActive() external view returns (bool) { return kernel.isPolicyActive(this); } /// @notice Function to grab module address from a given keycode. function getModuleAddress(Keycode keycode_) internal view returns (address) { address moduleForKeycode = address(kernel.getModuleForKeycode(keycode_)); if (moduleForKeycode == address(0)) revert Policy_ModuleDoesNotExist(keycode_); return moduleForKeycode; } /// @notice Define module dependencies for this policy. /// @return dependencies - Keycode array of module dependencies. function configureDependencies() external virtual returns (Keycode[] memory dependencies) {} /// @notice Function called by kernel to set module function permissions. /// @return requests - Array of keycodes and function selectors for requested permissions. function requestPermissions() external view virtual returns (Permissions[] memory requests) {} } /// @notice Main contract that acts as a central component registry for the protocol. /// @dev The kernel manages modules and policies. The kernel is mutated via predefined Actions, /// @dev which are input from any address assigned as the executor. The executor can be changed as needed. contract Kernel { // ========= EVENTS ========= // event PermissionsUpdated( Keycode indexed keycode_, Policy indexed policy_, bytes4 funcSelector_, bool granted_ ); event ActionExecuted(Actions indexed action_, address indexed target_); // ========= ERRORS ========= // error Kernel_OnlyExecutor(address caller_); error Kernel_ModuleAlreadyInstalled(Keycode module_); error Kernel_InvalidModuleUpgrade(Keycode module_); error Kernel_PolicyAlreadyActivated(address policy_); error Kernel_PolicyNotActivated(address policy_); // ========= PRIVILEGED ADDRESSES ========= // /// @notice Address that is able to initiate Actions in the kernel. Can be assigned to a multisig or governance contract. address public executor; // ========= MODULE MANAGEMENT ========= // /// @notice Array of all modules currently installed. Keycode[] public allKeycodes; /// @notice Mapping of module address to keycode. mapping(Keycode => Module) public getModuleForKeycode; /// @notice Mapping of keycode to module address. mapping(Module => Keycode) public getKeycodeForModule; /// @notice Mapping of a keycode to all of its policy dependents. Used to efficiently reconfigure policy dependencies. mapping(Keycode => Policy[]) public moduleDependents; /// @notice Helper for module dependent arrays. Prevents the need to loop through array. mapping(Keycode => mapping(Policy => uint256)) public getDependentIndex; /// @notice Module <> Policy Permissions. /// @dev Keycode -> Policy -> Function Selector -> bool for permission mapping(Keycode => mapping(Policy => mapping(bytes4 => bool))) public modulePermissions; // ========= POLICY MANAGEMENT ========= // /// @notice List of all active policies Policy[] public activePolicies; /// @notice Helper to get active policy quickly. Prevents need to loop through array. mapping(Policy => uint256) public getPolicyIndex; //============================================================================================// // CORE FUNCTIONS // //============================================================================================// constructor() { executor = msg.sender; } /// @notice Modifier to check if caller is the executor. modifier onlyExecutor() { if (msg.sender != executor) revert Kernel_OnlyExecutor(msg.sender); _; } function isPolicyActive(Policy policy_) public view returns (bool) { return activePolicies.length > 0 && activePolicies[getPolicyIndex[policy_]] == policy_; } /// @notice Main kernel function. Initiates state changes to kernel depending on Action passed in. function executeAction(Actions action_, address target_) external onlyExecutor { if (action_ == Actions.InstallModule) { ensureContract(target_); ensureValidKeycode(Module(target_).KEYCODE()); _installModule(Module(target_)); } else if (action_ == Actions.UpgradeModule) { ensureContract(target_); ensureValidKeycode(Module(target_).KEYCODE()); _upgradeModule(Module(target_)); } else if (action_ == Actions.ActivatePolicy) { ensureContract(target_); _activatePolicy(Policy(target_)); } else if (action_ == Actions.DeactivatePolicy) { ensureContract(target_); _deactivatePolicy(Policy(target_)); } else if (action_ == Actions.ChangeExecutor) { executor = target_; } else if (action_ == Actions.MigrateKernel) { ensureContract(target_); _migrateKernel(Kernel(target_)); } emit ActionExecuted(action_, target_); } function _installModule(Module newModule_) internal { Keycode keycode = newModule_.KEYCODE(); if (address(getModuleForKeycode[keycode]) != address(0)) revert Kernel_ModuleAlreadyInstalled(keycode); getModuleForKeycode[keycode] = newModule_; getKeycodeForModule[newModule_] = keycode; allKeycodes.push(keycode); newModule_.INIT(); } function _upgradeModule(Module newModule_) internal { Keycode keycode = newModule_.KEYCODE(); Module oldModule = getModuleForKeycode[keycode]; if (address(oldModule) == address(0) || oldModule == newModule_) revert Kernel_InvalidModuleUpgrade(keycode); getKeycodeForModule[oldModule] = Keycode.wrap(bytes5(0)); getKeycodeForModule[newModule_] = keycode; getModuleForKeycode[keycode] = newModule_; newModule_.INIT(); _reconfigurePolicies(keycode); } function _activatePolicy(Policy policy_) internal { if (isPolicyActive(policy_)) revert Kernel_PolicyAlreadyActivated(address(policy_)); // Add policy to list of active policies activePolicies.push(policy_); getPolicyIndex[policy_] = activePolicies.length - 1; // Record module dependencies Keycode[] memory dependencies = policy_.configureDependencies(); uint256 depLength = dependencies.length; for (uint256 i; i < depLength; ) { Keycode keycode = dependencies[i]; moduleDependents[keycode].push(policy_); getDependentIndex[keycode][policy_] = moduleDependents[keycode].length - 1; unchecked { ++i; } } // Grant permissions for policy to access restricted module functions Permissions[] memory requests = policy_.requestPermissions(); _setPolicyPermissions(policy_, requests, true); } function _deactivatePolicy(Policy policy_) internal { if (!isPolicyActive(policy_)) revert Kernel_PolicyNotActivated(address(policy_)); // Revoke permissions Permissions[] memory requests = policy_.requestPermissions(); _setPolicyPermissions(policy_, requests, false); // Remove policy from all policy data structures uint256 idx = getPolicyIndex[policy_]; Policy lastPolicy = activePolicies[activePolicies.length - 1]; activePolicies[idx] = lastPolicy; activePolicies.pop(); getPolicyIndex[lastPolicy] = idx; delete getPolicyIndex[policy_]; // Remove policy from module dependents _pruneFromDependents(policy_); } /// @notice All functionality will move to the new kernel. WARNING: ACTION WILL BRICK THIS KERNEL. /// @dev New kernel must add in all of the modules and policies via executeAction. /// @dev NOTE: Data does not get cleared from this kernel. function _migrateKernel(Kernel newKernel_) internal { uint256 keycodeLen = allKeycodes.length; for (uint256 i; i < keycodeLen; ) { Module module = Module(getModuleForKeycode[allKeycodes[i]]); module.changeKernel(newKernel_); unchecked { ++i; } } uint256 policiesLen = activePolicies.length; for (uint256 j; j < policiesLen; ) { Policy policy = activePolicies[j]; // Deactivate before changing kernel policy.changeKernel(newKernel_); unchecked { ++j; } } } function _reconfigurePolicies(Keycode keycode_) internal { Policy[] memory dependents = moduleDependents[keycode_]; uint256 depLength = dependents.length; for (uint256 i; i < depLength; ) { dependents[i].configureDependencies(); unchecked { ++i; } } } function _setPolicyPermissions( Policy policy_, Permissions[] memory requests_, bool grant_ ) internal { uint256 reqLength = requests_.length; for (uint256 i = 0; i < reqLength; ) { Permissions memory request = requests_[i]; modulePermissions[request.keycode][policy_][request.funcSelector] = grant_; emit PermissionsUpdated(request.keycode, policy_, request.funcSelector, grant_); unchecked { ++i; } } } function _pruneFromDependents(Policy policy_) internal { Keycode[] memory dependencies = policy_.configureDependencies(); uint256 depcLength = dependencies.length; for (uint256 i; i < depcLength; ) { Keycode keycode = dependencies[i]; Policy[] storage dependents = moduleDependents[keycode]; uint256 origIndex = getDependentIndex[keycode][policy_]; Policy lastPolicy = dependents[dependents.length - 1]; // Swap with last and pop dependents[origIndex] = lastPolicy; dependents.pop(); // Record new index and delete deactivated policy index getDependentIndex[keycode][lastPolicy] = origIndex; delete getDependentIndex[keycode][policy_]; unchecked { ++i; } } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; /// @notice Safe ERC20 and ETH transfer library that safely handles missing return values. /// @author Modified from Uniswap & old Solmate (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/libraries/TransferHelper.sol) library TransferHelper { function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(ERC20.transferFrom.selector, from, to, amount) ); require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(ERC20.transfer.selector, to, amount) ); require(success && (data.length == 0 || abi.decode(data, (bool))), "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(ERC20.approve.selector, to, amount) ); require(success && (data.length == 0 || abi.decode(data, (bool))), "APPROVE_FAILED"); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.15; import {ERC20} from "solmate/tokens/ERC20.sol"; import "src/Kernel.sol"; /// @notice Treasury holds all other assets under the control of the protocol. abstract contract TRSRYv1 is Module { // ========= EVENTS ========= // event IncreaseWithdrawApproval( address indexed withdrawer_, ERC20 indexed token_, uint256 newAmount_ ); event DecreaseWithdrawApproval( address indexed withdrawer_, ERC20 indexed token_, uint256 newAmount_ ); event Withdrawal( address indexed policy_, address indexed withdrawer_, ERC20 indexed token_, uint256 amount_ ); event IncreaseDebtorApproval(address indexed debtor_, ERC20 indexed token_, uint256 newAmount_); event DecreaseDebtorApproval(address indexed debtor_, ERC20 indexed token_, uint256 newAmount_); event DebtIncurred(ERC20 indexed token_, address indexed policy_, uint256 amount_); event DebtRepaid(ERC20 indexed token_, address indexed policy_, uint256 amount_); event DebtSet(ERC20 indexed token_, address indexed policy_, uint256 amount_); // ========= ERRORS ========= // error TRSRY_NoDebtOutstanding(); error TRSRY_NotActive(); // ========= STATE ========= // /// @notice Status of the treasury. If false, no withdrawals or debt can be incurred. bool public active; /// @notice Mapping of who is approved for withdrawal. /// @dev withdrawer -> token -> amount. Infinite approval is max(uint256). mapping(address => mapping(ERC20 => uint256)) public withdrawApproval; /// @notice Mapping of who is approved to incur debt. /// @dev debtor -> token -> amount. Infinite approval is max(uint256). mapping(address => mapping(ERC20 => uint256)) public debtApproval; /// @notice Total debt for token across all withdrawals. mapping(ERC20 => uint256) public totalDebt; /// @notice Debt for particular token and debtor address mapping(ERC20 => mapping(address => uint256)) public reserveDebt; // ========= FUNCTIONS ========= // modifier onlyWhileActive() { if (!active) revert TRSRY_NotActive(); _; } /// @notice Increase approval for specific withdrawer addresses function increaseWithdrawApproval( address withdrawer_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice Decrease approval for specific withdrawer addresses function decreaseWithdrawApproval( address withdrawer_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice Allow withdrawal of reserve funds from pre-approved addresses. function withdrawReserves( address to_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice Increase approval for someone to accrue debt in order to withdraw reserves. /// @dev Debt will generally be taken by contracts to allocate treasury funds in yield sources. function increaseDebtorApproval( address debtor_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice Decrease approval for someone to withdraw reserves as debt. function decreaseDebtorApproval( address debtor_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice Pre-approved policies can get a loan to perform operations with treasury assets. function incurDebt(ERC20 token_, uint256 amount_) external virtual; /// @notice Repay a debtor debt. /// @dev Only confirmed to safely handle standard and non-standard ERC20s. /// @dev Can have unforeseen consequences with ERC777. Be careful with ERC777 as reserve. function repayDebt( address debtor_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice An escape hatch for setting debt in special cases, like swapping reserves to another token. function setDebt( address debtor_, ERC20 token_, uint256 amount_ ) external virtual; /// @notice Get total balance of assets inside the treasury + any debt taken out against those assets. function getReserveBalance(ERC20 token_) external view virtual returns (uint256); /// @notice Emergency shutdown of withdrawals. function deactivate() external virtual; /// @notice Re-activate withdrawals after shutdown. function activate() external virtual; }
{ "remappings": [ "balancer-v2/=lib/balancer-v2/", "bonds/=lib/bonds/src/", "ds-test/=lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "interfaces/=src/interfaces/", "libraries/=src/libraries/", "modules/=src/modules/", "policies/=src/policies/", "solmate/=lib/solmate/src/", "test/=src/test/" ], "optimizer": { "enabled": true, "runs": 10 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract Kernel","name":"kernel_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller_","type":"address"}],"name":"KernelAdapter_OnlyKernel","type":"error"},{"inputs":[{"internalType":"address","name":"policy_","type":"address"}],"name":"Module_PolicyNotPermitted","type":"error"},{"inputs":[],"name":"TRSRY_NoDebtOutstanding","type":"error"},{"inputs":[],"name":"TRSRY_NotActive","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":true,"internalType":"address","name":"policy_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"DebtIncurred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":true,"internalType":"address","name":"policy_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"DebtRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":true,"internalType":"address","name":"policy_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"DebtSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor_","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":false,"internalType":"uint256","name":"newAmount_","type":"uint256"}],"name":"DecreaseDebtorApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer_","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":false,"internalType":"uint256","name":"newAmount_","type":"uint256"}],"name":"DecreaseWithdrawApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor_","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":false,"internalType":"uint256","name":"newAmount_","type":"uint256"}],"name":"IncreaseDebtorApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"withdrawer_","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":false,"internalType":"uint256","name":"newAmount_","type":"uint256"}],"name":"IncreaseWithdrawApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"policy_","type":"address"},{"indexed":true,"internalType":"address","name":"withdrawer_","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"INIT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"KEYCODE","outputs":[{"internalType":"Keycode","name":"","type":"bytes5"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint8","name":"major","type":"uint8"},{"internalType":"uint8","name":"minor","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Kernel","name":"newKernel_","type":"address"}],"name":"changeKernel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deactivate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract ERC20","name":"","type":"address"}],"name":"debtApproval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"debtor_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"decreaseDebtorApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"withdrawer_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"decreaseWithdrawApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"token_","type":"address"}],"name":"getReserveBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"debtor_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"increaseDebtorApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"withdrawer_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"increaseWithdrawApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"incurDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kernel","outputs":[{"internalType":"contract Kernel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"debtor_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"repayDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"reserveDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"debtor_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"setDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract ERC20","name":"","type":"address"}],"name":"withdrawApproval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"contract ERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdrawReserves","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600160055534801561001557600080fd5b506040516117753803806117758339810160408190526100349161005e565b600080546001600160a81b0319166001600160a01b0390921691909117600160a01b17905561008e565b60006020828403121561007057600080fd5b81516001600160a01b038116811461008757600080fd5b9392505050565b6116d88061009d6000396000f3fe608060405234801561001057600080fd5b50600436106101075760003560e01c806301a91e5c1461010c57806302fb0c5e146101215780630f15f4c01461014a57806315226b54146101525780631ae7ec2e146101735780631ff517ff1461019457806328a4ace5146101b45780632f42aef5146101df57806332b43ad2146101f25780634657b36c1461021d5780634aae164b1461023057806351b42b00146102435780635f0736a11461024b578063724000c1146102765780638b7f3fb914610289578063d4aae0c41461029c578063e6eb207a146102bc578063ea643914146102cf578063f5b92c73146102d7578063fb393f24146102ea578063ffa1ad74146102fd575b600080fd5b61011f61011a3660046114d4565b610312565b005b60005461013590600160a01b900460ff1681565b60405190151581526020015b60405180910390f35b61011f61045d565b610165610160366004611515565b610517565b604051908152602001610141565b61017b6105a6565b6040516001600160d81b03199091168152602001610141565b6101656101a2366004611515565b60036020526000908152604090205481565b6101656101c2366004611539565b600460209081526000928352604080842090915290825290205481565b61011f6101ed3660046114d4565b6105b2565b610165610200366004611539565b600260209081526000928352604080842090915290825290205481565b61011f61022b366004611515565b61072a565b61011f61023e3660046114d4565b610779565b61011f61090b565b610165610259366004611539565b600160209081526000928352604080842090915290825290205481565b61011f610284366004611572565b6109bf565b61011f6102973660046114d4565b610b84565b6000546102af906001600160a01b031681565b604051610141919061159e565b61011f6102ca3660046114d4565b610cd7565b61011f610e2b565b61011f6102e53660046114d4565b610e5a565b61011f6102f83660046114d4565b61115c565b60408051600181526000602082015201610141565b6000546001600160a01b031663f166d9eb61032b6105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610357939291906115b2565b602060405180830381865afa158015610374573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039891906115e7565b6103c057336040516311bf00c960e01b81526004016103b7919061159e565b60405180910390fd5b6001600160a01b0380841660009081526002602090815260408083209386168352929052908120546103f390839061161f565b6001600160a01b038581166000818152600260209081526040808320948916808452948252918290208590559051848152939450919290917f9afc1acde4b7ec0d84d924e5b530aecfb57d117a7122b80904cb9912badbff5991015b60405180910390a350505050565b6000546001600160a01b031663f166d9eb6104766105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016104a2939291906115b2565b602060405180830381865afa1580156104bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e391906115e7565b61050257336040516311bf00c960e01b81526004016103b7919061159e565b6000805460ff60a01b1916600160a01b179055565b6001600160a01b0381166000818152600360205260408082205490516370a0823160e01b8152919290916370a082319061055590309060040161159e565b602060405180830381865afa158015610572573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105969190611637565b6105a0919061161f565b92915050565b64545253525960d81b90565b6000546001600160a01b031663f166d9eb6105cb6105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016105f7939291906115b2565b602060405180830381865afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063891906115e7565b61065757336040516311bf00c960e01b81526004016103b7919061159e565b600054600160a01b900460ff166106815760405163473b682f60e11b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812080548392906106b4908490611650565b909155506106ce90506001600160a01b0383168483611294565b816001600160a01b0316836001600160a01b0316336001600160a01b03167f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e8460405161071d91815260200190565b60405180910390a4505050565b6000546001600160a01b03163314610757573360405163053e900f60e21b81526004016103b7919061159e565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031663f166d9eb6107926105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016107be939291906115b2565b602060405180830381865afa1580156107db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ff91906115e7565b61081e57336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b0382811660009081526004602090815260408083209387168352929052208054908290558181101561088e5761085b8183611650565b6001600160a01b0384166000908152600360205260408120805490919061088390849061161f565b909155506108c69050565b6108988282611650565b6001600160a01b038416600090815260036020526040812080549091906108c0908490611650565b90915550505b836001600160a01b0316836001600160a01b03167f4417d205f6349e66a581332b36195e74d10f878e80db907b4fd3a814aad4049d8460405161044f91815260200190565b6000546001600160a01b031663f166d9eb6109246105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610950939291906115b2565b602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099191906115e7565b6109b057336040516311bf00c960e01b81526004016103b7919061159e565b6000805460ff60a01b19169055565b6000546001600160a01b031663f166d9eb6109d86105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610a04939291906115b2565b602060405180830381865afa158015610a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4591906115e7565b610a6457336040516311bf00c960e01b81526004016103b7919061159e565b600054600160a01b900460ff16610a8e5760405163473b682f60e11b815260040160405180910390fd5b3360009081526002602090815260408083206001600160a01b038616845290915281208054839290610ac1908490611650565b90915550506001600160a01b038216600090815260046020908152604080832033845290915281208054839290610af990849061161f565b90915550506001600160a01b03821660009081526003602052604081208054839290610b2690849061161f565b90915550610b4090506001600160a01b0383163383611294565b60405181815233906001600160a01b038416907f7f04a714958851e1d87b504651ba77ab02f62bae8879f577bf3e07cf8567aba29060200160405180910390a35050565b6000546001600160a01b031663f166d9eb610b9d6105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610bc9939291906115b2565b602060405180830381865afa158015610be6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0a91906115e7565b610c2957336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b0380841660009081526001602090815260408083209386168352929052908120549082821115610c6957610c648383611650565b610c6c565b60005b6001600160a01b038681166000818152600160209081526040808320948a16808452948252918290208590559051848152939450919290917f40730d80659c76c95521f0340872d27fdc8b3c47befe2ca569d2c2eedc8a049e91015b60405180910390a35050505050565b6000546001600160a01b031663f166d9eb610cf06105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610d1c939291906115b2565b602060405180830381865afa158015610d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5d91906115e7565b610d7c57336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b0380841660009081526001602090815260408083209386168352929052908120549082610db283600019611650565b1115610dc757610dc2838361161f565b610dcb565b6000195b6001600160a01b038681166000818152600160209081526040808320948a16808452948252918290208590559051848152939450919290917f8bbc2784c9e4073e20f60d8c7218cbd211c43ca2ee041bc037f977693a0c8c1b9101610cc8565b6000546001600160a01b03163314610e58573360405163053e900f60e21b81526004016103b7919061159e565b565b6000546001600160a01b031663f166d9eb610e736105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610e9f939291906115b2565b602060405180830381865afa158015610ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee091906115e7565b610eff57336040516311bf00c960e01b81526004016103b7919061159e565b600554600114610f3e5760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b60448201526064016103b7565b60026005556001600160a01b0380831660009081526004602090815260408083209387168352929052908120549003610f8a5760405163a4255dc560e01b815260040160405180910390fd5b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190610fb990309060040161159e565b602060405180830381865afa158015610fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffa9190611637565b90506110116001600160a01b0384163330856113a1565b600081846001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611040919061159e565b602060405180830381865afa15801561105d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110819190611637565b61108b9190611650565b9050828111156110985750815b6001600160a01b038085166000908152600460209081526040808320938916835292905290812080548392906110cf908490611650565b90915550506001600160a01b038416600090815260036020526040812080548392906110fc908490611650565b92505081905550846001600160a01b0316846001600160a01b03167feef1a28252f7c3266ccea3202ee9693f0834485bc3551310a406e04829c7e2cf8360405161114891815260200190565b60405180910390a350506001600555505050565b6000546001600160a01b031663f166d9eb6111756105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016111a1939291906115b2565b602060405180830381865afa1580156111be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e291906115e7565b61120157336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b038084166000908152600260209081526040808320938616835292905290812054611234908390611650565b6001600160a01b038581166000818152600260209081526040808320948916808452948252918290208590559051848152939450919290917fbb8caa1e59333c99899b67ccacb2b942c5a5ebf1a2bff4932b50274da81fe8d5910161044f565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916112f09190611667565b6000604051808303816000865af19150503d806000811461132d576040519150601f19603f3d011682016040523d82523d6000602084013e611332565b606091505b509150915081801561135c57508051158061135c57508080602001905181019061135c91906115e7565b61139a5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016103b7565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916114059190611667565b6000604051808303816000865af19150503d8060008114611442576040519150601f19603f3d011682016040523d82523d6000602084013e611447565b606091505b509150915081801561147157508051158061147157508080602001905181019061147191906115e7565b6114b45760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016103b7565b505050505050565b6001600160a01b03811681146114d157600080fd5b50565b6000806000606084860312156114e957600080fd5b83356114f4816114bc565b92506020840135611504816114bc565b929592945050506040919091013590565b60006020828403121561152757600080fd5b8135611532816114bc565b9392505050565b6000806040838503121561154c57600080fd5b8235611557816114bc565b91506020830135611567816114bc565b809150509250929050565b6000806040838503121561158557600080fd5b8235611590816114bc565b946020939093013593505050565b6001600160a01b0391909116815260200190565b6001600160d81b03199390931683526001600160a01b039190911660208301526001600160e01b031916604082015260600190565b6000602082840312156115f957600080fd5b8151801515811461153257600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561163257611632611609565b500190565b60006020828403121561164957600080fd5b5051919050565b60008282101561166257611662611609565b500390565b6000825160005b81811015611688576020818601810151858301520161166e565b81811115611697576000828501525b50919091019291505056fea26469706673582212201278de3d795ae71bdd12fd402a0a04298e2a537701bf279a3c0fb166fa529f0a64736f6c634300080f00330000000000000000000000002286d7f9639e8158fad1169e76d1fbc38247f54b
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101075760003560e01c806301a91e5c1461010c57806302fb0c5e146101215780630f15f4c01461014a57806315226b54146101525780631ae7ec2e146101735780631ff517ff1461019457806328a4ace5146101b45780632f42aef5146101df57806332b43ad2146101f25780634657b36c1461021d5780634aae164b1461023057806351b42b00146102435780635f0736a11461024b578063724000c1146102765780638b7f3fb914610289578063d4aae0c41461029c578063e6eb207a146102bc578063ea643914146102cf578063f5b92c73146102d7578063fb393f24146102ea578063ffa1ad74146102fd575b600080fd5b61011f61011a3660046114d4565b610312565b005b60005461013590600160a01b900460ff1681565b60405190151581526020015b60405180910390f35b61011f61045d565b610165610160366004611515565b610517565b604051908152602001610141565b61017b6105a6565b6040516001600160d81b03199091168152602001610141565b6101656101a2366004611515565b60036020526000908152604090205481565b6101656101c2366004611539565b600460209081526000928352604080842090915290825290205481565b61011f6101ed3660046114d4565b6105b2565b610165610200366004611539565b600260209081526000928352604080842090915290825290205481565b61011f61022b366004611515565b61072a565b61011f61023e3660046114d4565b610779565b61011f61090b565b610165610259366004611539565b600160209081526000928352604080842090915290825290205481565b61011f610284366004611572565b6109bf565b61011f6102973660046114d4565b610b84565b6000546102af906001600160a01b031681565b604051610141919061159e565b61011f6102ca3660046114d4565b610cd7565b61011f610e2b565b61011f6102e53660046114d4565b610e5a565b61011f6102f83660046114d4565b61115c565b60408051600181526000602082015201610141565b6000546001600160a01b031663f166d9eb61032b6105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610357939291906115b2565b602060405180830381865afa158015610374573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039891906115e7565b6103c057336040516311bf00c960e01b81526004016103b7919061159e565b60405180910390fd5b6001600160a01b0380841660009081526002602090815260408083209386168352929052908120546103f390839061161f565b6001600160a01b038581166000818152600260209081526040808320948916808452948252918290208590559051848152939450919290917f9afc1acde4b7ec0d84d924e5b530aecfb57d117a7122b80904cb9912badbff5991015b60405180910390a350505050565b6000546001600160a01b031663f166d9eb6104766105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016104a2939291906115b2565b602060405180830381865afa1580156104bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e391906115e7565b61050257336040516311bf00c960e01b81526004016103b7919061159e565b6000805460ff60a01b1916600160a01b179055565b6001600160a01b0381166000818152600360205260408082205490516370a0823160e01b8152919290916370a082319061055590309060040161159e565b602060405180830381865afa158015610572573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105969190611637565b6105a0919061161f565b92915050565b64545253525960d81b90565b6000546001600160a01b031663f166d9eb6105cb6105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016105f7939291906115b2565b602060405180830381865afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063891906115e7565b61065757336040516311bf00c960e01b81526004016103b7919061159e565b600054600160a01b900460ff166106815760405163473b682f60e11b815260040160405180910390fd5b3360009081526001602090815260408083206001600160a01b0386168452909152812080548392906106b4908490611650565b909155506106ce90506001600160a01b0383168483611294565b816001600160a01b0316836001600160a01b0316336001600160a01b03167f342e7ff505a8a0364cd0dc2ff195c315e43bce86b204846ecd36913e117b109e8460405161071d91815260200190565b60405180910390a4505050565b6000546001600160a01b03163314610757573360405163053e900f60e21b81526004016103b7919061159e565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031663f166d9eb6107926105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016107be939291906115b2565b602060405180830381865afa1580156107db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ff91906115e7565b61081e57336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b0382811660009081526004602090815260408083209387168352929052208054908290558181101561088e5761085b8183611650565b6001600160a01b0384166000908152600360205260408120805490919061088390849061161f565b909155506108c69050565b6108988282611650565b6001600160a01b038416600090815260036020526040812080549091906108c0908490611650565b90915550505b836001600160a01b0316836001600160a01b03167f4417d205f6349e66a581332b36195e74d10f878e80db907b4fd3a814aad4049d8460405161044f91815260200190565b6000546001600160a01b031663f166d9eb6109246105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610950939291906115b2565b602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099191906115e7565b6109b057336040516311bf00c960e01b81526004016103b7919061159e565b6000805460ff60a01b19169055565b6000546001600160a01b031663f166d9eb6109d86105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610a04939291906115b2565b602060405180830381865afa158015610a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a4591906115e7565b610a6457336040516311bf00c960e01b81526004016103b7919061159e565b600054600160a01b900460ff16610a8e5760405163473b682f60e11b815260040160405180910390fd5b3360009081526002602090815260408083206001600160a01b038616845290915281208054839290610ac1908490611650565b90915550506001600160a01b038216600090815260046020908152604080832033845290915281208054839290610af990849061161f565b90915550506001600160a01b03821660009081526003602052604081208054839290610b2690849061161f565b90915550610b4090506001600160a01b0383163383611294565b60405181815233906001600160a01b038416907f7f04a714958851e1d87b504651ba77ab02f62bae8879f577bf3e07cf8567aba29060200160405180910390a35050565b6000546001600160a01b031663f166d9eb610b9d6105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610bc9939291906115b2565b602060405180830381865afa158015610be6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0a91906115e7565b610c2957336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b0380841660009081526001602090815260408083209386168352929052908120549082821115610c6957610c648383611650565b610c6c565b60005b6001600160a01b038681166000818152600160209081526040808320948a16808452948252918290208590559051848152939450919290917f40730d80659c76c95521f0340872d27fdc8b3c47befe2ca569d2c2eedc8a049e91015b60405180910390a35050505050565b6000546001600160a01b031663f166d9eb610cf06105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610d1c939291906115b2565b602060405180830381865afa158015610d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5d91906115e7565b610d7c57336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b0380841660009081526001602090815260408083209386168352929052908120549082610db283600019611650565b1115610dc757610dc2838361161f565b610dcb565b6000195b6001600160a01b038681166000818152600160209081526040808320948a16808452948252918290208590559051848152939450919290917f8bbc2784c9e4073e20f60d8c7218cbd211c43ca2ee041bc037f977693a0c8c1b9101610cc8565b6000546001600160a01b03163314610e58573360405163053e900f60e21b81526004016103b7919061159e565b565b6000546001600160a01b031663f166d9eb610e736105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b8152600401610e9f939291906115b2565b602060405180830381865afa158015610ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee091906115e7565b610eff57336040516311bf00c960e01b81526004016103b7919061159e565b600554600114610f3e5760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b60448201526064016103b7565b60026005556001600160a01b0380831660009081526004602090815260408083209387168352929052908120549003610f8a5760405163a4255dc560e01b815260040160405180910390fd5b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190610fb990309060040161159e565b602060405180830381865afa158015610fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ffa9190611637565b90506110116001600160a01b0384163330856113a1565b600081846001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611040919061159e565b602060405180830381865afa15801561105d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110819190611637565b61108b9190611650565b9050828111156110985750815b6001600160a01b038085166000908152600460209081526040808320938916835292905290812080548392906110cf908490611650565b90915550506001600160a01b038416600090815260036020526040812080548392906110fc908490611650565b92505081905550846001600160a01b0316846001600160a01b03167feef1a28252f7c3266ccea3202ee9693f0834485bc3551310a406e04829c7e2cf8360405161114891815260200190565b60405180910390a350506001600555505050565b6000546001600160a01b031663f166d9eb6111756105a6565b336000356001600160e01b0319166040518463ffffffff1660e01b81526004016111a1939291906115b2565b602060405180830381865afa1580156111be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e291906115e7565b61120157336040516311bf00c960e01b81526004016103b7919061159e565b6001600160a01b038084166000908152600260209081526040808320938616835292905290812054611234908390611650565b6001600160a01b038581166000818152600260209081526040808320948916808452948252918290208590559051848152939450919290917fbb8caa1e59333c99899b67ccacb2b942c5a5ebf1a2bff4932b50274da81fe8d5910161044f565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916112f09190611667565b6000604051808303816000865af19150503d806000811461132d576040519150601f19603f3d011682016040523d82523d6000602084013e611332565b606091505b509150915081801561135c57508051158061135c57508080602001905181019061135c91906115e7565b61139a5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016103b7565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916114059190611667565b6000604051808303816000865af19150503d8060008114611442576040519150601f19603f3d011682016040523d82523d6000602084013e611447565b606091505b509150915081801561147157508051158061147157508080602001905181019061147191906115e7565b6114b45760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016103b7565b505050505050565b6001600160a01b03811681146114d157600080fd5b50565b6000806000606084860312156114e957600080fd5b83356114f4816114bc565b92506020840135611504816114bc565b929592945050506040919091013590565b60006020828403121561152757600080fd5b8135611532816114bc565b9392505050565b6000806040838503121561154c57600080fd5b8235611557816114bc565b91506020830135611567816114bc565b809150509250929050565b6000806040838503121561158557600080fd5b8235611590816114bc565b946020939093013593505050565b6001600160a01b0391909116815260200190565b6001600160d81b03199390931683526001600160a01b039190911660208301526001600160e01b031916604082015260600190565b6000602082840312156115f957600080fd5b8151801515811461153257600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561163257611632611609565b500190565b60006020828403121561164957600080fd5b5051919050565b60008282101561166257611662611609565b500390565b6000825160005b81811015611688576020818601810151858301520161166e565b81811115611697576000828501525b50919091019291505056fea26469706673582212201278de3d795ae71bdd12fd402a0a04298e2a537701bf279a3c0fb166fa529f0a64736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002286d7f9639e8158fad1169e76d1fbc38247f54b
-----Decoded View---------------
Arg [0] : kernel_ (address): 0x2286d7f9639e8158FaD1169e76d1FbC38247f54b
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000002286d7f9639e8158fad1169e76d1fbc38247f54b
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.