Source Code
Latest 17 from a total of 17 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer To Cust... | 24346139 | 7 days ago | IN | 0 ETH | 0.0001559 | ||||
| Transfer To Cust... | 24124728 | 38 days ago | IN | 0 ETH | 0.00011991 | ||||
| Transfer To Cust... | 24124689 | 38 days ago | IN | 0 ETH | 0.0001559 | ||||
| Transfer To Cust... | 24124613 | 38 days ago | IN | 0 ETH | 0.00015292 | ||||
| Transfer Admin | 24038620 | 50 days ago | IN | 0 ETH | 0.0000016 | ||||
| Set Custodian | 24030735 | 51 days ago | IN | 0 ETH | 0.0000015 | ||||
| Set Custodian | 24030731 | 51 days ago | IN | 0 ETH | 0.00000081 | ||||
| Revoke Role | 24025669 | 52 days ago | IN | 0 ETH | 0.0000042 | ||||
| Grant Role | 24025005 | 52 days ago | IN | 0 ETH | 0.00000181 | ||||
| Set Custodian | 24025003 | 52 days ago | IN | 0 ETH | 0.00000153 | ||||
| Set Custodian | 24025002 | 52 days ago | IN | 0 ETH | 0.00000087 | ||||
| Transfer To Cust... | 23847436 | 77 days ago | IN | 0 ETH | 0.0006214 | ||||
| Transfer To Cust... | 23824720 | 80 days ago | IN | 0 ETH | 0.00013516 | ||||
| Transfer To Cust... | 23824698 | 80 days ago | IN | 0 ETH | 0.00016854 | ||||
| Set Router | 23618175 | 109 days ago | IN | 0 ETH | 0.00001121 | ||||
| Grant Role | 23618173 | 109 days ago | IN | 0 ETH | 0.00001072 | ||||
| Set Custodian | 23618171 | 109 days ago | IN | 0 ETH | 0.00001076 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AssetReserve
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 10000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {SingleAdminAccessControl} from "src/utils/SingleAdminAccessControl.sol";
/// @title AssetReserve - Multi-Role Asset Custody
/// @notice This contract serves as a reserve of assets custody solution with role-based access control,
/// providing liquidity buffer management for redemptions and authorized fund transfers to custodians.
contract AssetReserve is SingleAdminAccessControl {
using SafeERC20 for IERC20;
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error NotRouter();
error UnauthorizedCustodian();
error ZeroInput();
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event CustodianSet(address indexed custodian, bool isCustodian);
event RouterSet(address indexed router);
event TransferToCustodian(address indexed custodian, address indexed asset, uint256 amount);
event RedemptionProcessed(address indexed recipient, address indexed collateralAsset, uint256 amount);
/*//////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/
/// @notice The router contract
address public router;
/// @notice The role that is allowed to pull funds to a custodian
bytes32 public constant AUTHORIZED = keccak256("AUTHORIZED_ROLE");
/// @notice The mapping of custodians
mapping(address custodian => bool) public isCustodian;
/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/
constructor(address _admin) {
_grantRole(DEFAULT_ADMIN_ROLE, _admin);
}
/*//////////////////////////////////////////////////////////////
ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @notice Set a custodian
/// @param _custodian The address of the custodian
/// @param _isCustodian Whether the custodian is authorized
function setCustodian(address _custodian, bool _isCustodian) external onlyRole(DEFAULT_ADMIN_ROLE) {
_setCustodian(_custodian, _isCustodian);
}
function setRouter(address _router) external onlyRole(DEFAULT_ADMIN_ROLE) {
_setRouter(_router);
}
/*//////////////////////////////////////////////////////////////
AUTHORIZED FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @notice Transfer an asset to a custodian
/// @param _custodian The address of the custodian
/// @param _asset The address of the asset
/// @param _amount The amount of asset to transfer
function transferToCustodian(address _custodian, address _asset, uint256 _amount) external onlyRole(AUTHORIZED) {
if (!isCustodian[_custodian]) revert UnauthorizedCustodian();
IERC20(_asset).safeTransfer(_custodian, _amount);
emit TransferToCustodian(_custodian, _asset, _amount);
}
/*//////////////////////////////////////////////////////////////
ROUTER FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @notice Process a redemption
/// @param _recipient The address of the recipient
/// @param _collateralAsset The address of the collateral asset
/// @param _amount The amount of collateral to redeem
/// @dev This function is called by the router to process a redemption
function processRedemption(address _recipient, address _collateralAsset, uint256 _amount) external onlyRouter {
IERC20(_collateralAsset).safeTransfer(_recipient, _amount);
emit RedemptionProcessed(_recipient, _collateralAsset, _amount);
}
/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
modifier onlyRouter() {
if (msg.sender != router) revert NotRouter();
_;
}
/// @notice Internal function to set a custodian
/// @param _custodian The address of the custodian
/// @param _isCustodian Whether the custodian is authorized
function _setCustodian(address _custodian, bool _isCustodian) internal {
if (_custodian == address(0)) revert ZeroInput();
isCustodian[_custodian] = _isCustodian;
emit CustodianSet(_custodian, _isCustodian);
}
function _setRouter(address _router) internal {
if (_router == address(0)) revert ZeroInput();
router = _router;
emit RouterSet(_router);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.19 <0.9.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/interfaces/IERC5313.sol";
import "src/interfaces/ISingleAdminAccessControl.sol";
/**
* @title SingleAdminAccessControl
* @notice SingleAdminAccessControl is a contract that provides a single admin role
* @notice This contract is a simplified alternative to OpenZeppelin's AccessControlDefaultAdminRules
*/
abstract contract SingleAdminAccessControl is IERC5313, ISingleAdminAccessControl, AccessControl {
address private _currentDefaultAdmin;
address private _pendingDefaultAdmin;
modifier notAdmin(bytes32 role) {
if (role == DEFAULT_ADMIN_ROLE) revert InvalidAdminChange();
_;
}
/// @notice Transfer the admin role to a new address
/// @notice This can ONLY be executed by the current admin
/// @param newAdmin address
function transferAdmin(address newAdmin) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (newAdmin == msg.sender) revert InvalidAdminChange();
_pendingDefaultAdmin = newAdmin;
emit AdminTransferRequested(_currentDefaultAdmin, newAdmin);
}
function acceptAdmin() external {
if (msg.sender != _pendingDefaultAdmin) revert NotPendingAdmin();
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
/// @notice grant a role
/// @notice can only be executed by the current single admin
/// @notice admin role cannot be granted externally
/// @param role bytes32
/// @param account address
function grantRole(bytes32 role, address account) public override onlyRole(DEFAULT_ADMIN_ROLE) notAdmin(role) {
_grantRole(role, account);
}
/// @notice revoke a role
/// @notice can only be executed by the current admin
/// @notice admin role cannot be revoked
/// @param role bytes32
/// @param account address
function revokeRole(bytes32 role, address account) public override onlyRole(DEFAULT_ADMIN_ROLE) notAdmin(role) {
_revokeRole(role, account);
}
/// @notice renounce the role of msg.sender
/// @notice admin role cannot be renounced
/// @param role bytes32
/// @param account address
function renounceRole(bytes32 role, address account) public virtual override notAdmin(role) {
super.renounceRole(role, account);
}
/**
* @dev See {IERC5313-owner}.
*/
function owner() public view virtual returns (address) {
return _currentDefaultAdmin;
}
/**
* @notice no way to change admin without removing old admin first
*/
function _grantRole(bytes32 role, address account) internal override returns (bool) {
if (role == DEFAULT_ADMIN_ROLE) {
emit AdminTransferred(_currentDefaultAdmin, account);
_revokeRole(DEFAULT_ADMIN_ROLE, _currentDefaultAdmin);
_currentDefaultAdmin = account;
delete _pendingDefaultAdmin;
}
return super._grantRole(role, account);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5313.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface for the Light Contract Ownership Standard.
*
* A standardized minimal interface required to identify an account that controls a contract
*/
interface IERC5313 {
/**
* @dev Gets the address of the owner.
*/
function owner() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
interface ISingleAdminAccessControl {
error InvalidAdminChange();
error NotPendingAdmin();
event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);
event AdminTransferRequested(address indexed oldAdmin, address indexed newAdmin);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)
pragma solidity >=0.8.4;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted to signal this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"forge-std/=node_modules/forge-std/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "shanghai",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"InvalidAdminChange","type":"error"},{"inputs":[],"name":"NotPendingAdmin","type":"error"},{"inputs":[],"name":"NotRouter","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UnauthorizedCustodian","type":"error"},{"inputs":[],"name":"ZeroInput","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"custodian","type":"address"},{"indexed":false,"internalType":"bool","name":"isCustodian","type":"bool"}],"name":"CustodianSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"collateralAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RedemptionProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"router","type":"address"}],"name":"RouterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"custodian","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferToCustodian","type":"event"},{"inputs":[],"name":"AUTHORIZED","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"custodian","type":"address"}],"name":"isCustodian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_collateralAsset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"processRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_custodian","type":"address"},{"internalType":"bool","name":"_isCustodian","type":"bool"}],"name":"setCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_custodian","type":"address"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561000f575f5ffd5b5060405161117438038061117483398101604081905261002e916101f9565b6100385f8261003f565b5050610226565b5f826100be576001546040516001600160a01b038085169216907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec6905f90a3600154610095905f906001600160a01b03166100d1565b50600180546001600160a01b0384166001600160a01b0319918216179091556002805490911690555b6100c88383610159565b90505b92915050565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1615610152575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016100cb565b505f6100cb565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16610152575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101b13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016100cb565b5f60208284031215610209575f5ffd5b81516001600160a01b038116811461021f575f5ffd5b9392505050565b610f41806102335f395ff3fe608060405234801561000f575f5ffd5b5060043610610115575f3560e01c80633ea42ef4116100ad578063a217fddf1161007d578063d547741f11610063578063d547741f146102bf578063ed03caee146102d2578063f887ea40146102e5575f5ffd5b8063a217fddf146102a5578063c0d78655146102ac575f5ffd5b80633ea42ef4146101fd57806375829def146102105780638da5cb5b1461022357806391d1485414610262575f5ffd5b8063248a9ca3116100e8578063248a9ca3146101935780632f2ff15d146101b557806335c80c8c146101c857806336568abe146101ea575f5ffd5b806301ffc9a7146101195780630e18b681146101415780631f49d1f11461014b5780632360eb391461015e575b5f5ffd5b61012c610127366004610e01565b610305565b60405190151581526020015b60405180910390f35b61014961039d565b005b610149610159366004610e68565b6103fb565b6101857f0393b4c1b6519e8b53ae0efa1ab522060a3b9f8d86d09c8a22ca6d6eea735cf781565b604051908152602001610138565b6101856101a1366004610ea1565b5f9081526020819052604090206001015490565b6101496101c3366004610eb8565b610414565b61012c6101d6366004610ee2565b60046020525f908152604090205460ff1681565b6101496101f8366004610eb8565b610467565b61014961020b366004610efb565b6104a9565b61014961021e366004610ee2565b6105bf565b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610138565b61012c610270366004610eb8565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101855f81565b6101496102ba366004610ee2565b61068f565b6101496102cd366004610eb8565b6106a6565b6101496102e0366004610efb565b6106f2565b60035461023d9073ffffffffffffffffffffffffffffffffffffffff1681565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061039757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60025473ffffffffffffffffffffffffffffffffffffffff1633146103ee576040517f058d9a1b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103f85f336107d0565b50565b5f6104058161089f565b61040f83836108a9565b505050565b5f61041e8161089f565b8280610456576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61046084846107d0565b5050505050565b818061049f576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61040f838361097f565b7f0393b4c1b6519e8b53ae0efa1ab522060a3b9f8d86d09c8a22ca6d6eea735cf76104d38161089f565b73ffffffffffffffffffffffffffffffffffffffff84165f9081526004602052604090205460ff16610531576040517ff77cde6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61055273ffffffffffffffffffffffffffffffffffffffff841685846109d8565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f21026a2e5553c0254300d9681b3c308f64131341c39920e5f59527c06f6b2b98846040516105b191815260200190565b60405180910390a350505050565b5f6105c98161089f565b3373ffffffffffffffffffffffffffffffffffffffff831603610618576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255600154604051919216907fefdcbba819467e00b0262c12892dda980bac68580b72178e57a162368b808766905f90a35050565b5f6106998161089f565b6106a282610a65565b5050565b5f6106b08161089f565b82806106e8576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104608484610b20565b60035473ffffffffffffffffffffffffffffffffffffffff163314610743576040517f9165520100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61076473ffffffffffffffffffffffffffffffffffffffff831684836109d8565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ff49e80233e375da06733fc4d8595af0326472fea02b128c5712913b28e0406b6836040516107c391815260200190565b60405180910390a3505050565b5f8261088e5760015460405173ffffffffffffffffffffffffffffffffffffffff8085169216907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec6905f90a3600154610840905f9073ffffffffffffffffffffffffffffffffffffffff16610b20565b506001805473ffffffffffffffffffffffffffffffffffffffff84167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556002805490911690555b6108988383610be0565b9392505050565b6103f88133610cd2565b73ffffffffffffffffffffffffffffffffffffffff82166108f6576040517faf458c0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f8ba69cfc061bc5317ea26989000c52d230a731bb6a8ba331663b306aa0df20d8910160405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ce576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61040f8282610b20565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261040f908490610d5c565b73ffffffffffffffffffffffffffffffffffffffff8116610ab2576040517faf458c0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fc6b438e6a8a59579ce6a4406cbd203b740e0d47b458aae6596339bcd40c40d15905f90a250565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bd9575f8381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610397565b505f610397565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bd9575f8381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610c703390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610397565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166106a2576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602481018390526044015b60405180910390fd5b5f5f60205f8451602086015f885af180610d7b576040513d5f823e3d81fd5b50505f513d91508115610d92578060011415610dac565b73ffffffffffffffffffffffffffffffffffffffff84163b155b15610dfb576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610d53565b50505050565b5f60208284031215610e11575f5ffd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610898575f5ffd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610e63575f5ffd5b919050565b5f5f60408385031215610e79575f5ffd5b610e8283610e40565b915060208301358015158114610e96575f5ffd5b809150509250929050565b5f60208284031215610eb1575f5ffd5b5035919050565b5f5f60408385031215610ec9575f5ffd5b82359150610ed960208401610e40565b90509250929050565b5f60208284031215610ef2575f5ffd5b61089882610e40565b5f5f5f60608486031215610f0d575f5ffd5b610f1684610e40565b9250610f2460208501610e40565b915060408401359050925092509256fea164736f6c634300081e000a0000000000000000000000008c4fb5925b3607d68ff813545184815dbb88c545
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610115575f3560e01c80633ea42ef4116100ad578063a217fddf1161007d578063d547741f11610063578063d547741f146102bf578063ed03caee146102d2578063f887ea40146102e5575f5ffd5b8063a217fddf146102a5578063c0d78655146102ac575f5ffd5b80633ea42ef4146101fd57806375829def146102105780638da5cb5b1461022357806391d1485414610262575f5ffd5b8063248a9ca3116100e8578063248a9ca3146101935780632f2ff15d146101b557806335c80c8c146101c857806336568abe146101ea575f5ffd5b806301ffc9a7146101195780630e18b681146101415780631f49d1f11461014b5780632360eb391461015e575b5f5ffd5b61012c610127366004610e01565b610305565b60405190151581526020015b60405180910390f35b61014961039d565b005b610149610159366004610e68565b6103fb565b6101857f0393b4c1b6519e8b53ae0efa1ab522060a3b9f8d86d09c8a22ca6d6eea735cf781565b604051908152602001610138565b6101856101a1366004610ea1565b5f9081526020819052604090206001015490565b6101496101c3366004610eb8565b610414565b61012c6101d6366004610ee2565b60046020525f908152604090205460ff1681565b6101496101f8366004610eb8565b610467565b61014961020b366004610efb565b6104a9565b61014961021e366004610ee2565b6105bf565b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610138565b61012c610270366004610eb8565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101855f81565b6101496102ba366004610ee2565b61068f565b6101496102cd366004610eb8565b6106a6565b6101496102e0366004610efb565b6106f2565b60035461023d9073ffffffffffffffffffffffffffffffffffffffff1681565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061039757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60025473ffffffffffffffffffffffffffffffffffffffff1633146103ee576040517f058d9a1b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103f85f336107d0565b50565b5f6104058161089f565b61040f83836108a9565b505050565b5f61041e8161089f565b8280610456576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61046084846107d0565b5050505050565b818061049f576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61040f838361097f565b7f0393b4c1b6519e8b53ae0efa1ab522060a3b9f8d86d09c8a22ca6d6eea735cf76104d38161089f565b73ffffffffffffffffffffffffffffffffffffffff84165f9081526004602052604090205460ff16610531576040517ff77cde6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61055273ffffffffffffffffffffffffffffffffffffffff841685846109d8565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f21026a2e5553c0254300d9681b3c308f64131341c39920e5f59527c06f6b2b98846040516105b191815260200190565b60405180910390a350505050565b5f6105c98161089f565b3373ffffffffffffffffffffffffffffffffffffffff831603610618576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116918217909255600154604051919216907fefdcbba819467e00b0262c12892dda980bac68580b72178e57a162368b808766905f90a35050565b5f6106998161089f565b6106a282610a65565b5050565b5f6106b08161089f565b82806106e8576040517f6317a0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104608484610b20565b60035473ffffffffffffffffffffffffffffffffffffffff163314610743576040517f9165520100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61076473ffffffffffffffffffffffffffffffffffffffff831684836109d8565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167ff49e80233e375da06733fc4d8595af0326472fea02b128c5712913b28e0406b6836040516107c391815260200190565b60405180910390a3505050565b5f8261088e5760015460405173ffffffffffffffffffffffffffffffffffffffff8085169216907ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec6905f90a3600154610840905f9073ffffffffffffffffffffffffffffffffffffffff16610b20565b506001805473ffffffffffffffffffffffffffffffffffffffff84167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556002805490911690555b6108988383610be0565b9392505050565b6103f88133610cd2565b73ffffffffffffffffffffffffffffffffffffffff82166108f6576040517faf458c0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f8181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f8ba69cfc061bc5317ea26989000c52d230a731bb6a8ba331663b306aa0df20d8910160405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ce576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61040f8282610b20565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261040f908490610d5c565b73ffffffffffffffffffffffffffffffffffffffff8116610ab2576040517faf458c0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fc6b438e6a8a59579ce6a4406cbd203b740e0d47b458aae6596339bcd40c40d15905f90a250565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff1615610bd9575f8381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610397565b505f610397565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16610bd9575f8381526020818152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610c703390565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610397565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166106a2576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602481018390526044015b60405180910390fd5b5f5f60205f8451602086015f885af180610d7b576040513d5f823e3d81fd5b50505f513d91508115610d92578060011415610dac565b73ffffffffffffffffffffffffffffffffffffffff84163b155b15610dfb576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610d53565b50505050565b5f60208284031215610e11575f5ffd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610898575f5ffd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610e63575f5ffd5b919050565b5f5f60408385031215610e79575f5ffd5b610e8283610e40565b915060208301358015158114610e96575f5ffd5b809150509250929050565b5f60208284031215610eb1575f5ffd5b5035919050565b5f5f60408385031215610ec9575f5ffd5b82359150610ed960208401610e40565b90509250929050565b5f60208284031215610ef2575f5ffd5b61089882610e40565b5f5f5f60608486031215610f0d575f5ffd5b610f1684610e40565b9250610f2460208501610e40565b915060408401359050925092509256fea164736f6c634300081e000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000008c4fb5925b3607d68ff813545184815dbb88c545
-----Decoded View---------------
Arg [0] : _admin (address): 0x8c4Fb5925b3607D68FF813545184815dBb88c545
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000008c4fb5925b3607d68ff813545184815dbb88c545
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.