Description:
Decentralized Finance (DeFi) protocol contract providing Swap, Liquidity, Factory functionality.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/DACAuthority.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {IDACAuthority} from "./IDACAuthority.sol";
import {DACAccessManaged} from "./DACAccessManaged.sol";
// ================================================================
// │ ERRORS │
// ================================================================
/**
* @dev Thrown when the admin is not a valid admin account (e.g., `address(0)`).
* @param adminAccount The invalid admin account.
*/
error DACAuthority__InvalidAdmin(address adminAccount);
/**
* @dev Thrown when the Chronicles Agent is not a valid Chronicles Agent account (e.g., `address(0)`).
* @param chroniclesAgentAccount The invalid Chronicles Agent account.
*/
error DACAuthority__InvalidChroniclesAgent(address chroniclesAgentAccount);
/**
* @dev Thrown when the Liquidity Manager Agent is not a valid Liquidity Manager Agent account (e.g., `address(0)`).
* @param liquidityAgentAccount The invalid Liquidity Manager Agent account.
*/
error DACAuthority__InvalidLiquidityAgent(address liquidityAgentAccount);
/**
* @dev Thrown when the Treasurer Agent is not a valid Treasurer Agent account (e.g., `address(0)`).
* @param treasurerAgentAccount The invalid Treasurer Agent account.
*/
error DACAuthority__InvalidTreasurerAgent(address treasurerAgentAccount);
/**
* @dev Thrown when the treasury is not a valid treasury contract (e.g., `address(0)`).
* @param treasury The invalid treasury account.
*/
error DACAuthority__InvalidTreasury(address treasury);
/**
* @dev Thrown when trying to whitelist an invalid swapper account.
* @param swapper The invalid swapper account.
*/
error DACAuthority__InvalidSwapper(address swapper);
/**
* @dev Thrown when trying to whitelist a swapper that's already whitelisted.
* @param swapper The swapper account already whitelisted.
*/
error DACAuthority__SwapperAlreadyWhitelisted(address swapper);
/**
* @dev Thrown when trying to disable a swapper that's not whitelisted.
* @param swapper The swapper account not whitelisted.
*/
error DACAuthority__SwapperNotWhitelisted(address swapper);
/**
* @title DACAuthority
* @dev Manages roles and permissions for the DAC (Decentralized AI Chronicles) ecosystem.
* This contract serves as the central authority to manage access control across various
* components of the DAC ecosystem. It allows for role management
* and validation of permissions required by other contracts in the ecosystem.
*/
contract DACAuthority is IDACAuthority, DACAccessManaged {
// ================================================================
// │ CONSTANTS │
// ================================================================
// Time period for which a swapper is timelocked
uint256 public constant SWAPPER_TIMELOCK = 7 days;
// ================================================================
// │ State variables │
// ================================================================
address private s_admin;
address private s_chroniclesAgent;
address private s_liquidityAgent;
address private s_treasurerAgent;
address private s_treasury;
// Mapping from swapper address to activation timestamp
mapping(address => uint256) private s_swappers;
// Array to keep track of all swappers for enumeration
address[] private s_swapperList;
// ================================================================
// │ Constructor │
// ================================================================
constructor(
address initialAdmin,
address initialChroniclesAgent,
address initialLiquidityAgent,
address initialTreasurerAgent
) DACAccessManaged(IDACAuthority(address(this))) {
if (initialAdmin == address(0)) {
revert DACAuthority__InvalidAdmin(address(0));
}
if (initialChroniclesAgent == address(0)) {
revert DACAuthority__InvalidChroniclesAgent(address(0));
}
if (initialLiquidityAgent == address(0)) {
revert DACAuthority__InvalidLiquidityAgent(address(0));
}
if (initialTreasurerAgent == address(0)) {
revert DACAuthority__InvalidTreasurerAgent(address(0));
}
_setAdmin(initialAdmin);
_setChroniclesAgent(initialChroniclesAgent);
_setLiquidityAgent(initialLiquidityAgent);
_setTreasurerAgent(initialTreasurerAgent);
}
// ================================================================
// │ Functions │
// ================================================================
/**
* @dev Set the new DAC Admin.
* Can only be called by the current admin.
*/
function setAdmin(address newAdmin) external onlyAdmin {
if (newAdmin == address(0)) {
revert DACAuthority__InvalidAdmin(address(0));
}
_setAdmin(newAdmin);
}
/**
* @dev Set the new DAC Chronicles Agent.
* Can only be called by the current admin.
*/
function setChroniclesAgent(address newChroniclesAgent) external onlyAdmin {
if (newChroniclesAgent == address(0)) {
revert DACAuthority__InvalidChroniclesAgent(address(0));
}
_setChroniclesAgent(newChroniclesAgent);
}
/**
* @dev Set the new Liquidity Manager Agent.
* Can only be called by the current admin.
*/
function setLiquidityAgent(address newLiquidityAgent) external onlyAdmin {
if (newLiquidityAgent == address(0)) {
revert DACAuthority__InvalidLiquidityAgent(address(0));
}
_setLiquidityAgent(newLiquidityAgent);
}
/**
* @dev Set the new Treasurer Agent.
* Can only be called by the current admin.
*/
function setTreasurerAgent(address newTreasurerAgent) external onlyAdmin {
if (newTreasurerAgent == address(0)) {
revert DACAuthority__InvalidTreasurerAgent(address(0));
}
_setTreasurerAgent(newTreasurerAgent);
}
/**
* @dev Set the new DAC Treasury.
* Can only be called by the current admin.
*/
function setTreasury(address newTreasury) external onlyAdmin {
if (newTreasury == address(0)) {
revert DACAuthority__InvalidTreasury(address(0));
}
_setTreasury(newTreasury);
}
/**
* @inheritdoc IDACAuthority
*/
function admin() external view override returns (address) {
return s_admin;
}
/**
* @inheritdoc IDACAuthority
*/
function chroniclesAgent() external view override returns (address) {
return s_chroniclesAgent;
}
/**
* @inheritdoc IDACAuthority
*/
function liquidityManagerAgent() external view override returns (address) {
return s_liquidityAgent;
}
/**
* @inheritdoc IDACAuthority
*/
function treasurerAgent() external view override returns (address) {
return s_treasurerAgent;
}
/**
* @inheritdoc IDACAuthority
*/
function treasury() external view override returns (address) {
return s_treasury;
}
/**
* @inheritdoc IDACAuthority
*/
function isSwapper(address account) external view override returns (bool) {
uint256 activationTime = s_swappers[account];
return activationTime != 0 && block.timestamp >= activationTime;
}
/**
* @inheritdoc IDACAuthority
*/
function getSwappers() external view override returns (address[] memory) {
return s_swapperList;
}
/**
* @inheritdoc IDACAuthority
*/
function getSwapperActivationTime(address account) external view override returns (uint256) {
return s_swappers[account];
}
/**
* @dev Whitelists a new swapper with a 7-day activation timelock.
* Can only be called by the admin.
* @param swapper The address to be whitelisted as a swapper.
*/
function whitelistSwapper(address swapper) external onlyAdmin {
if (swapper == address(0)) {
revert DACAuthority__InvalidSwapper(swapper);
}
if (s_swappers[swapper] != 0) {
revert DACAuthority__SwapperAlreadyWhitelisted(swapper);
}
uint256 activationTime = block.timestamp + SWAPPER_TIMELOCK;
s_swappers[swapper] = activationTime;
s_swapperList.push(swapper);
emit SwapperWhitelisted(swapper, activationTime);
}
/**
* @dev Disables a swapper immediately.
* Can only be called by the admin.
* @param swapper The address of the swapper to disable.
*/
function disableSwapper(address swapper) external onlyAdmin {
if (s_swappers[swapper] == 0) {
revert DACAuthority__SwapperNotWhitelisted(swapper);
}
delete s_swappers[swapper];
// Remove from swapperList
for (uint256 i = 0; i < s_swapperList.length; i++) {
if (s_swapperList[i] == swapper) {
s_swapperList[i] = s_swapperList[s_swapperList.length - 1];
s_swapperList.pop();
break;
}
}
emit SwapperDisabled(swapper);
}
/**
* @dev Set the new DAChronicle Admin.
* Private function without access restriction.
*/
function _setAdmin(address newAdmin) private {
address oldAdmin = s_admin;
s_admin = newAdmin;
emit AdminSet(oldAdmin, newAdmin);
}
/**
* @dev Set the new DAC Chronicles Agent.
* Private function without access restriction.
*/
function _setChroniclesAgent(address newChroniclesAgent) private {
address oldChroniclesAgent = s_chroniclesAgent;
s_chroniclesAgent = newChroniclesAgent;
emit ChroniclesAgentSet(oldChroniclesAgent, newChroniclesAgent);
}
/**
* @dev Set the new DAC Liquidity Manager Agent.
* Private function without access restriction.
*/
function _setLiquidityAgent(address newLiquidityAgent) private {
address oldLiquidityAgent = s_liquidityAgent;
s_liquidityAgent = newLiquidityAgent;
emit LiquidityAgentSet(oldLiquidityAgent, newLiquidityAgent);
}
/**
* @dev Set the new DAC Treasurer Agent.
* Private function without access restriction.
*/
function _setTreasurerAgent(address newTreasurerAgent) private {
address oldTreasurerAgent = s_treasurerAgent;
s_treasurerAgent = newTreasurerAgent;
emit TreasurerAgentSet(oldTreasurerAgent, newTreasurerAgent);
}
/**
* @dev Set the new DAC Treasury.
* Private function without access restriction.
*/
function _setTreasury(address newTreasury) private {
address oldTreasury = s_treasury;
s_treasury = newTreasury;
emit TreasurySet(oldTreasury, newTreasury);
}
}
"
},
"src/IDACAuthority.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/**
* @title IDACAuthority
* @dev Interface for the DACAuthority contract, which defines events and functions
* that other contracts in the DAC (Decentralized AI Chronicles) ecosystem can interact with.
*/
interface IDACAuthority {
// ================================================================
// │ Events │
// ================================================================
/**
* @dev Emitted when the admin account is updated.
* @param previousAdmin The address of the previous admin.
* @param newAdmin The address of the new admin.
*/
event AdminSet(address indexed previousAdmin, address indexed newAdmin);
/**
* @dev Emitted when the chronicles agent account is updated.
* @param previousChroniclesAgent The address of the previous chronicles agent.
* @param newChroniclesAgent The address of the new chronicles agent.
*/
event ChroniclesAgentSet(address indexed previousChroniclesAgent, address indexed newChroniclesAgent);
/**
* @dev Emitted when the liquidity manager agent account is updated.
* @param previousLiquidityAgent The address of the previous liquidity manager agent.
* @param liquidityAgent The address of the new liquidity manager agent.
*/
event LiquidityAgentSet(address indexed previousLiquidityAgent, address indexed liquidityAgent);
/**
* @dev Emitted when the treasurer agent account is updated.
* @param previousTreasurerAgent The address of the previous treasurer agent.
* @param treasurerAgent The address of the new treasurer agent.
*/
event TreasurerAgentSet(address indexed previousTreasurerAgent, address indexed treasurerAgent);
/**
* @dev Emitted when the treasury contract is updated.
* @param previousTreasury The address of the previous treasury contract.
* @param newTreasury The address of the new treasury contract.
*/
event TreasurySet(address indexed previousTreasury, address indexed newTreasury);
/**
* @dev Emitted when a new swapper is proposed to be whitelisted.
* @param swapper The address of the swapper proposed to be whitelisted.
* @param activationTime The timestamp when the swapper becomes active.
*/
event SwapperWhitelisted(address indexed swapper, uint256 activationTime);
/**
* @dev Emitted when a swapper is disabled.
* @param swapper The address of the swapper that has been disabled.
*/
event SwapperDisabled(address indexed swapper);
// ================================================================
// │ Functions │
// ================================================================
/**
* @notice Returns the address of the admin account.
* @return The current admin address.
*/
function admin() external view returns (address);
/**
* @notice Returns the address of the chronicles agent account.
* @return The current chronicles agent address.
*/
function chroniclesAgent() external view returns (address);
/**
* @notice Returns the address of the liquidity manager agent account.
* @return The current liquidity manager agent address.
*/
function liquidityManagerAgent() external view returns (address);
/**
* @notice Returns the address of the treasurer agent account.
* @return The current treasurer agent address.
*/
function treasurerAgent() external view returns (address);
/**
* @notice Returns the address of the treasury contract.
* @return The current treasury contract address.
*/
function treasury() external view returns (address);
/**
* @notice Checks if an address is an active swapper.
* @param account The address to check.
* @return True if the address is an active swapper, false otherwise.
*/
function isSwapper(address account) external view returns (bool);
/**
* @notice Returns a list of all whitelisted swappers.
* @return An array of swapper addresses.
*/
function getSwappers() external view returns (address[] memory);
/**
* @notice Returns the activation timestamp of a swapper.
* @param account The swapper address.
* @return The timestamp when the swapper becomes active.
*/
function getSwapperActivationTime(address account) external view returns (uint256);
}
"
},
"src/DACAccessManaged.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {IDACAuthority} from "./IDACAuthority.sol";
// ================================================================
// │ ERRORS │
// ================================================================
/**
* @dev Thrown when the authority is not a authority contract (e.g., `address(0)`).
* @param authority The invalid authority contract.
*/
error DACAuthority__InvalidAuthority(address authority);
/**
* @dev Thrown when the caller is not authorized to perform an admin operation.
* @param account The address of the unauthorized caller.
*/
error DACAccessManaged__AdminUnauthorizedAccount(address account);
/**
* @dev Thrown when the caller is not authorized to perform a chronicles agent operation.
* @param account The address of the unauthorized caller.
*/
error DACAccessManaged__ChroniclesAgentUnauthorizedAccount(address account);
/**
* @dev Thrown when the caller is not authorized to perform a liquidity manager agent operation.
* @param account The address of the unauthorized caller.
*/
error DACAccessManaged__LiquidityAgentUnauthorizedAccount(address account);
/**
* @dev Thrown when the caller is not authorized to perform a treasurer agent operation.
* @param account The address of the unauthorized caller.
*/
error DACAccessManaged__TreasurerAgentUnauthorizedAccount(address account);
/**
* @dev Thrown when the caller is not authorized to perform a treasury operation.
* @param treasury The address of the unauthorized caller.
*/
error DACAccessManaged__TreasuryUnauthorizedAccount(address treasury);
/**
* @dev Thrown when the provided address is not authorized to perform a swapper operation.
* @param account The address of the unauthorized swapper.
*/
error DACAccessManaged__SwapperUnauthorizedAccount(address account);
/**
* @dev Thrown when a new authority is not yet proposed.
*/
error DACAuthority__NewAuthorityNotProposed();
/**
* @dev Thrown when trying to activate an authority before the timelock has passed.
* @param authority The authority address.
* @param activationTime The required activation time.
*/
error DACAuthority__AuthorityTimelockNotPassed(address authority, uint256 activationTime);
/**
* @title DACAccessManaged
* @dev Abstract contract that provides access control mechanisms for contracts
* in the DAC (Decentralized AI Chronicles) ecosystem. This contract acts as a
* base for managing access permissions for different roles such as admin, chronicles agent,
* liquidity manager agent, treasurer agent, treasury, and swapper.
*/
abstract contract DACAccessManaged {
// ================================================================
// │ CONSTANTS │
// ================================================================
// Time period for which a new authority is timelocked
uint256 public constant AUTHORITY_TIMELOCK = 7 days;
// ================================================================
// │ State variables │
// ================================================================
/**
* @dev The DACAuthority contract that manages roles and permissions for the DAC ecosystem.
*/
IDACAuthority private s_authority;
// Proposed authority change
IDACAuthority private s_proposedAuthority;
uint256 private s_authorityChangeExecutionTime;
// ================================================================
// │ Events │
// ================================================================
/**
* @dev Emitted when a proposed authority change is executed.
* @param previousAuthority The address of the previous DACAuthority contract.
* @param newAuthority The address of the new DACAuthority contract.
*/
event AuthorityChangeExecuted(address indexed previousAuthority, address indexed newAuthority);
/**
* @dev Emitted when a new authority change is proposed.
* @param proposedAuthority The address of the proposed new authority.
* @param executionTime The timestamp when the authority change can be executed.
*/
event AuthorityChangeProposed(address indexed proposedAuthority, uint256 executionTime);
// ================================================================
// │ Modifiers │
// ================================================================
/**
* @dev Modifier to restrict access to admin operations.
* Reverts if the caller is not authorized.
*/
modifier onlyAdmin() {
if (s_authority.admin() != msg.sender) {
revert DACAccessManaged__AdminUnauthorizedAccount(msg.sender);
}
_;
}
/**
* @dev Modifier to restrict access to chronicles agent operations.
* Reverts if the caller is not authorized.
*/
modifier onlyChroniclesAgent() {
if (s_authority.chroniclesAgent() != msg.sender) {
revert DACAccessManaged__ChroniclesAgentUnauthorizedAccount(msg.sender);
}
_;
}
/**
* @dev Modifier to restrict access to Liquidity Manager Agent operations.
* Reverts if the caller is not authorized.
*/
modifier onlyLiquidityAgent() {
if (s_authority.liquidityManagerAgent() != msg.sender) {
revert DACAccessManaged__LiquidityAgentUnauthorizedAccount(msg.sender);
}
_;
}
/**
* @dev Modifier to restrict access to Treasurer Agent operations.
* Reverts if the caller is not authorized.
*/
modifier onlyTreasurerAgent() {
if (s_authority.treasurerAgent() != msg.sender) {
revert DACAccessManaged__TreasurerAgentUnauthorizedAccount(msg.sender);
}
_;
}
/**
* @dev Modifier to restrict access to treasury operations.
* Reverts if the caller is not authorized.
*/
modifier onlyTreasury() {
if (s_authority.treasury() != msg.sender) {
revert DACAccessManaged__TreasuryUnauthorizedAccount(msg.sender);
}
_;
}
/**
* @dev Modifier to restrict access to swapper operations.
* @param swapper The address of the swapper to check.
* Reverts if the caller is not an active swapper.
*/
modifier onlySwapper(address swapper) {
if (!s_authority.isSwapper(swapper)) {
revert DACAccessManaged__SwapperUnauthorizedAccount(swapper);
}
_;
}
// ================================================================
// │ Constructor │
// ================================================================
/**
* @notice Initializes the contract with the specified DACAuthority instance.
* @param authority The address of the DACAuthority contract.
*/
constructor(IDACAuthority authority) {
if (address(authority) == address(0)) {
revert DACAuthority__InvalidAuthority(address(0));
}
s_authority = authority;
emit AuthorityChangeExecuted(address(0), address(authority));
}
// ================================================================
// │ Functions │
// ================================================================
/**
* @notice Returns the address of the current DACAuthority contract.
* @return The current DACAuthority contract.
*/
function getAuthority() public view returns (IDACAuthority) {
return s_authority;
}
/**
* @notice Proposes a new DACAuthority contract with a 7-day timelock.
* @dev Can only be called by the admin.
* Emits an {AuthorityChangeProposed} event.
* @param newAuthority The address of the new DACAuthority contract.
*/
function proposeAuthorityChange(IDACAuthority newAuthority) external onlyAdmin {
if (address(newAuthority) == address(0)) {
revert DACAuthority__InvalidAuthority(address(0));
}
s_proposedAuthority = newAuthority;
s_authorityChangeExecutionTime = block.timestamp + AUTHORITY_TIMELOCK;
emit AuthorityChangeProposed(address(newAuthority), s_authorityChangeExecutionTime);
}
/**
* @notice Executes the previously proposed authority change after the timelock.
* @dev Can only be called by the admin.
* Emits an {AuthorityChangeExecuted} event.
*/
function executeAuthorityChange() external onlyAdmin {
if (address(s_proposedAuthority) == address(0)) {
revert DACAuthority__NewAuthorityNotProposed();
}
if (block.timestamp < s_authorityChangeExecutionTime) {
revert DACAuthority__AuthorityTimelockNotPassed(
address(s_proposedAuthority), s_authorityChangeExecutionTime
);
}
address oldAuthority = address(s_authority);
s_authority = s_proposedAuthority;
s_proposedAuthority = IDACAuthority(address(0));
s_authorityChangeExecutionTime = 0;
emit AuthorityChangeExecuted(address(oldAuthority), address(s_authority));
}
/**
* @notice Returns the address of the proposed new authority.
* @return The proposed authority address.
*/
function getProposedAuthority() external view returns (address) {
return address(s_proposedAuthority);
}
/**
* @notice Returns the timestamp when the authority change can be executed.
* @return The execution timestamp.
*/
function getAuthorityChangeExecutionTime() external view returns (uint256) {
return s_authorityChangeExecutionTime;
}
}
"
}
},
"settings": {
"remappings": [
"@openzeppelin/=lib/openzeppelin-contracts/",
"@uniswap/=lib/v2-periphery/",
"@uniswapcore/=lib/v2-core/",
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"foundry-devops/=lib/foundry-devops/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"v2-core/=lib/v2-core/contracts/",
"v2-periphery/=lib/v2-periphery/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": false
}
}}
Submitted on: 2025-11-05 17:28:23
Comments
Log in to comment.
No comments yet.