Agents
The Curve DAO has a total of three Aragon Agent ownership addresses, which are governed by two independent DAOs:
Community DAO¶
The Community DAO (or just “the DAO”) governs the day-to-day operation of the protocol.
Voting is based on a user’s holdings of “Vote-Escrowed CRV” (veCRV). veCRV is obtained by locking CRV for up to 4 years, with 1 veCRV equal to 1 CRV locked for 4 years. As the lock time decreases, an account’s veCRV balance decreases linearly as the time remaining until unlock decreases. veCRV is non-transferrable.
An account must have a minimum balance of 2500 veCRV to make a DAO vote. Each vote lasts for one week. Votes cannot be executed after the they successfully passed.
Contract Source & Deployment
CurveOwnershipAgent contract is deployed to the Ethereum mainnet at: 0x40907540d8a6C65c637785e8f8B742ae6b0b9968.
 CurveParameterAgent contract is deployed to the Ethereum mainnet at: 0x4EEb3bA4f221cA16ed4A0cC7254E2E32DF948c5f.
-  
Ownership Admin¶
The ownership admin controls most functionality within the protocol. Performing an action via the ownership admin requires a 30% quorum with 51% support.
 -  
Parameter Admin¶
The parameter admin has authority to modify parameters on pools, such as adjusting the amplification co-efficient. Performing an action via the paramater admin requries a 15% quorum with 30% support.
 
Emergency DAO¶
The EmergencyDAO has limited authority to kill non-factory pools and gauges during extraordinary circumstances.
Contract Source & Deployment
EmergencyDAO contract is deployed to the Ethereum mainnet at: 0x467947EE34aF926cF1DCac093870f613C96B1E0c.
This DAO consists of nine members, comprised of a mix of the Curve team and prominent figures within the DeFi community. Each member has one vote. Any member may propose a vote.
All members of the EmergencyDAO may propose new votes. A vote lasts for 24 hours and can be executed immediately once it receives 66% support.
| Name | Details - Telegram | |
|---|---|---|
banteg |  Yearn, @banteg |  @banteg | 
Calvin |  @calchulus |  @calchulus | 
C2tP |  Convex, @c2tp_eth |  @C2tP | 
Darly Lau |  @Daryllautk |  @Daryllautk | 
Ga3b_node |  @ga3b_node |  |
Naga King |  @nagakingg |  @nagakingg | 
Peter MM |  @PeterMm |  |
Addison |  @addisonthunderhead |  @0xaddi | 
Quentin Milne |  StakeDAO, @Kii_iu |  
Tip
To obtain the current members' addresses, query getOwners within the EmergencyDAO contract.
Killing Pools¶
Non-Factory liquidity pools can be killed by calling the kill_me() function of the pool. The function can only be called within the first 2 months after deploying the pool.
Guarded Method
This function is only callable by the owner/admin of the pools.
Calling kill_me() sets the is_killed variable of the pool to True. By doing this, the contract prevents users from performing actions such as exchange, add_liquidity, remove_liquidity_imbalance and remove_liquidity_one_coin. Users can only remove funds by calling remove_liquidity.
In general, a pool can be "unkilled" again by calling the function unkill_me(). This reverts the changes made when it was killed."
Source code
is_killed: bool
kill_deadline: uint256
KILL_DEADLINE_DT: constant(uint256) = 2 * 30 * 86400
@external
def kill_me():
    assert msg.sender == self.owner  # dev: only owner
    assert self.kill_deadline > block.timestamp  # dev: deadline has passed
    self.is_killed = True
@external
def unkill_me():
    assert msg.sender == self.owner  # dev: only owner
    self.is_killed = False    
Killing Gauges¶
Gauges can be killed by calling the set_killed() function on the corresponding gauge, thereby setting the is_killed variable to True.
 By doing this, the rate of the gauge is set to 0, effectively stopping all the $CRV emissions.
Source code
is_killed: public(bool)
@external
def set_killed(_is_killed: bool):
    """
    @notice Set the killed status for this contract
    @dev When killed, the gauge always yields a rate of 0 and so cannot mint CRV
    @param _is_killed Killed status to set
    """
    assert msg.sender == self.admin
    self.is_killed = _is_killed
@internal
def _checkpoint(addr: address):
    """
    @notice Checkpoint for a user
    @param addr User address
    """
    _period: int128 = self.period
    _period_time: uint256 = self.period_timestamp[_period]
    _integrate_inv_supply: uint256 = self.integrate_inv_supply[_period]
    rate: uint256 = self.inflation_rate
    new_rate: uint256 = rate
    prev_future_epoch: uint256 = self.future_epoch_time
    if prev_future_epoch >= _period_time:
        self.future_epoch_time = CRV20(CRV).future_epoch_time_write()
        new_rate = CRV20(CRV).rate()
        self.inflation_rate = new_rate
    if self.is_killed:
        # Stop distributing inflation as soon as killed
        rate = 0
    # Update integral of 1/supply
    if block.timestamp > _period_time:
        _working_supply: uint256 = self.working_supply
        Controller(GAUGE_CONTROLLER).checkpoint_gauge(self)
        prev_week_time: uint256 = _period_time
        week_time: uint256 = min((_period_time + WEEK) / WEEK * WEEK, block.timestamp)
        for i in range(500):
            dt: uint256 = week_time - prev_week_time
            w: uint256 = Controller(GAUGE_CONTROLLER).gauge_relative_weight(self, prev_week_time / WEEK * WEEK)
            if _working_supply > 0:
                if prev_future_epoch >= prev_week_time and prev_future_epoch < week_time:
                    # If we went across one or multiple epochs, apply the rate
                    # of the first epoch until it ends, and then the rate of
                    # the last epoch.
                    # If more than one epoch is crossed - the gauge gets less,
                    # but that'd meen it wasn't called for more than 1 year
                    _integrate_inv_supply += rate * w * (prev_future_epoch - prev_week_time) / _working_supply
                    rate = new_rate
                    _integrate_inv_supply += rate * w * (week_time - prev_future_epoch) / _working_supply
                else:
                    _integrate_inv_supply += rate * w * dt / _working_supply
                # On precisions of the calculation
                # rate ~= 10e18
                # last_weight > 0.01 * 1e18 = 1e16 (if pool weight is 1%)
                # _working_supply ~= TVL * 1e18 ~= 1e26 ($100M for example)
                # The largest loss is at dt = 1
                # Loss is 1e-9 - acceptable
            if week_time == block.timestamp:
                break
            prev_week_time = week_time
            week_time = min(week_time + WEEK, block.timestamp)
    _period += 1
    self.period = _period
    self.period_timestamp[_period] = block.timestamp
    self.integrate_inv_supply[_period] = _integrate_inv_supply
    # Update user-specific integrals
    _working_balance: uint256 = self.working_balances[addr]
    self.integrate_fraction[addr] += _working_balance * (_integrate_inv_supply - self.integrate_inv_supply_of[addr]) / 10 ** 18
    self.integrate_inv_supply_of[addr] = _integrate_inv_supply
    self.integrate_checkpoint_of[addr] = block.timestamp