Treasury

0xba690293226322f899e5cdd69c3f992134729f91

Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
2,858 bytes
ABI entries
32
7 read · 8 write
License
none

Contract information

Address
0xba690293226322f899e5cdd69c3f992134729f91
Chain
Robinhood Chain (4663)
Compiler
v0.8.24+commit.e11b9ed9
Optimization
Enabled
Creation tx
0xb1e9426931…5c68e952fc

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (7)

MAX_DELAY()uint64
isKeeper(address)bool
nonce()uint256
owner()address
pendingOwner()address
withdrawDelay()uint64
withdrawals(bytes32)address, address, uint256, uint64, bool, bool

Events (7)

KeeperSetOwnershipTransferStartedOwnershipTransferredWithdrawDelaySetWithdrawalCanceledWithdrawalExecutedWithdrawalQueued

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "initialOwner",
        "type": "address"
      },
      {
        "internalType": "uint64",
        "name": "withdrawDelay_",
        "type": "uint64"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "AlreadyFinalized",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "BadDelay",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotKeeper",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      }
    ],
    "name": "SafeERC20FailedOperation",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "TooEarly",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "UnknownWithdrawal",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ZeroAddress",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "keeper",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "enabled",
        "type": "bool"
      }
    ],
    "name": "KeeperSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferStarted",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint64",
        "name": "delay",
        "type": "uint64"
      }
    ],
    "name": "WithdrawDelaySet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "bytes32",
        "name": "id",
        "type": "bytes32"
      }
    ],
    "name": "WithdrawalCanceled",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "bytes32",
        "name": "id",
        "type": "bytes32"
      }
    ],
    "name": "WithdrawalExecuted",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "bytes32",
        "name": "id",
        "type": "bytes32"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint64",
        "name": "eta",
        "type": "uint64"
      }
    ],
    "name": "WithdrawalQueued",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "MAX_DELAY",
    "outputs": [
      {
        "internalType": "uint64",
        "name": "",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "acceptOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "id",
        "type": "bytes32"
      }
    ],
    "name": "cancelWithdrawal",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "id",
        "type": "bytes32"
      }
    ],
    "name": "executeWithdrawal",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "isKeeper",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "nonce",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "pendingOwner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "queueWithdrawal",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "id",
        "type": "bytes32"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "keeper",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "enabled",
        "type": "bool"
      }
    ],
    "name": "setKeeper",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint64",
        "name": "delay",
        "type": "uint64"
      }
    ],
    "name": "setWithdrawDelay",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "withdrawDelay",
    "outputs": [
      {
        "internalType": "uint64",
        "name": "",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "name": "withdrawals",
    "outputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      },
      {
        "internalType": "uint64",
        "name": "eta",
        "type": "uint64"
      },
      {
        "internalType": "bool",
        "name": "executed",
        "type": "bool"
      },
      {
        "internalType": "bool",
        "name": "canceled",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Governed} from "./access/Governed.sol";

/// @title  Treasury
/// @notice Timelocked custody of the protocol's WETH reserve, bought-back $MEMEDEX, and skimmed memecoins.
///         Every outflow must be queued and then executed only after `withdrawDelay` elapses, so a single
///         compromised owner key cannot instantly drain the treasury. Recommended owner: a multisig.
contract Treasury is Governed {
    using SafeERC20 for IERC20;

    struct Withdrawal {
        address token;
        address to;
        uint256 amount;
        uint64 eta; // earliest execution time
        bool executed;
        bool canceled;
    }

    uint64 public constant MAX_DELAY = 30 days;

    uint64 public withdrawDelay;
    uint256 public nonce;
    mapping(bytes32 => Withdrawal) public withdrawals;

    event WithdrawDelaySet(uint64 delay);
    event WithdrawalQueued(bytes32 indexed id, address indexed token, address indexed to, uint256 amount, uint64 eta);
    event WithdrawalExecuted(bytes32 indexed id);
    event WithdrawalCanceled(bytes32 indexed id);

    error ZeroAddress();
    error BadDelay();
    error UnknownWithdrawal();
    error AlreadyFinalized();
    error TooEarly();

    constructor(address initialOwner, uint64 withdrawDelay_) Governed(initialOwner) {
        if (withdrawDelay_ > MAX_DELAY) revert BadDelay();
        withdrawDelay = withdrawDelay_;
    }

    /// @dev Delay can be changed but is bounded; lowering it still cannot fast-track already-queued items.
    function setWithdrawDelay(uint64 delay) external onlyOwner {
        if (delay > MAX_DELAY) revert BadDelay();
        withdrawDelay = delay;
        emit WithdrawDelaySet(delay);
    }

    function queueWithdrawal(address token, address to, uint256 amount)
        external
        onlyOwner
        returns (bytes32 id)
    {
        if (token == address(0) || to == address(0)) revert ZeroAddress();
        uint64 eta = uint64(block.timestamp) + withdrawDelay;
        id = keccak256(abi.encode(token, to, amount, nonce++));
        withdrawals[id] =
            Withdrawal({token: token, to: to, amount: amount, eta: eta, executed: false, canceled: false});
        emit WithdrawalQueued(id, token, to, amount, eta);
    }

    function executeWithdrawal(bytes32 id) external onlyOwner {
        Withdrawal storage w = withdrawals[id];
        if (w.eta == 0) revert UnknownWithdrawal();
        if (w.executed || w.canceled) revert AlreadyFinalized();
        if (block.timestamp < w.eta) revert TooEarly();
        w.executed = true;
        IERC20(w.token).safeTransfer(w.to, w.amount);
        emit WithdrawalExecuted(id);
    }

    function cancelWithdrawal(bytes32 id) external onlyOwner {
        Withdrawal storage w = withdrawals[id];
        if (w.eta == 0) revert UnknownWithdrawal();
        if (w.executed || w.canceled) revert AlreadyFinalized();
        w.canceled = true;
        emit WithdrawalCanceled(id);
    }
}
Chain explorer1765msChain node88ms