Factory
The crvUSD Factory enables the creation of new marketsand adjustments, including setting a new fee receiver, modifying the debt ceilingof an existing market, or updating blueprint implementations.
Other than the pool factory, this factory does not allow permissionless deployment of new markets. Only its admin, the CurveOwnershipAgent, can call to add a market. Therefore, adding a new market requires a successfully passed DAO vote.
crvUSD Market Factorycontract is deployed to the Ethereum mainnet at: 0xC9332fdCB1C491Dcc683bAe86Fe3cb70360738BC. Source code available on Github.
Adding Markets
A new crvUSD market can be added by the CurveOwnershipAgent. Therefore, adding a new market requires a successfully passed DAO vote.
add_market
ControllerFactory.add_market(token: address, A: uint256, fee: uint256, admin_fee: uint256, _price_oracle_contract: address, monetary_policy: address, loan_discount: uint256, liquidation_discount: uint256, debt_ceiling: uint256) -> address[2]:This function is only callable by the admin of the contract.
Function to add a new market and automatically deploy a new AMM and a Controller from the implementation contracts (see Implementations). Additionally, when initializing a new market, **rate_write()**from the MonetaryPolicy contract is called to check if it has a correct ABI.
Returns: AMM and Controller contracts (address).
Emits: AddNewMarket
| Input | Type | Description |
|---|---|---|
token | address | Collateral token address |
A | uint256 | Amplification coefficient. One band size is 1/n |
fee | uint256 | AMM fee in the market's AMM |
admin_fee | uint256 | AMM admin fee |
_price_oracle_contract | address | Address of the price oracle contract for the market |
monetary_policy | address | Monetary policy for the market |
loan_discount | uint256 | Loan Discount: allowed to borrow only up to x_down * (1 - loan_discount) |
liquidation_discount | uint256 | Discount defining a bad liquidation threshold |
debt_ceiling | uint256 | Debt ceiling for the market |
There are some limitation values for adding new markets regarding fee, A and liquidation_discount.
<>Source code▼
# Limits
MIN_A: constant(uint256) = 2
MAX_A: constant(uint256) = 10000
MIN_FEE: constant(uint256) = 10**6 # 1e-12, still needs to be above 0
MAX_FEE: constant(uint256) = 10**17 # 10%
MAX_ADMIN_FEE: constant(uint256) = 10**18 # 100%
MAX_LOAN_DISCOUNT: constant(uint256) = 5 * 10**17
MIN_LIQUIDATION_DISCOUNT: constant(uint256) = 10**16
@external
@nonreentrant('lock')
def add_market(token: address, A: uint256, fee: uint256, admin_fee: uint256,
_price_oracle_contract: address,
monetary_policy: address, loan_discount: uint256, liquidation_discount: uint256,
debt_ceiling: uint256) -> address[2]:
"""
@notice Add a new market, creating an AMM and a Controller from a blueprint
@param token Collateral token address
@param A Amplification coefficient; one band size is 1/A
@param fee AMM fee in the market's AMM
@param admin_fee AMM admin fee
@param _price_oracle_contract Address of price oracle contract for this market
@param monetary_policy Monetary policy for this market
@param loan_discount Loan discount: allowed to borrow only up to x_down * (1 - loan_discount)
@param liquidation_discount Discount which defines a bad liquidation threshold
@param debt_ceiling Debt ceiling for this market
@return (Controller, AMM)
"""
assert msg.sender == self.admin, "Only admin"
assert A >= MIN_A and A <= MAX_A, "Wrong A"
assert fee <= MAX_FEE, "Fee too high"
assert fee >= MIN_FEE, "Fee too low"
assert admin_fee < MAX_ADMIN_FEE, "Admin fee too high"
assert liquidation_discount >= MIN_LIQUIDATION_DISCOUNT, "Liquidation discount too low"
assert loan_discount <= MAX_LOAN_DISCOUNT, "Loan discount too high"
assert loan_discount > liquidation_discount, "need loan_discount>liquidation_discount"
MonetaryPolicy(monetary_policy).rate_write() # Test that MonetaryPolicy has correct ABI
p: uint256 = PriceOracle(_price_oracle_contract).price() # This also validates price oracle ABI
assert p > 0
assert PriceOracle(_price_oracle_contract).price_w() == p
A_ratio: uint256 = 10**18 * A / (A - 1)
amm: address = create_from_blueprint(
self.amm_implementation,
STABLECOIN.address, 10**(18 - STABLECOIN.decimals()),
token, 10**(18 - ERC20(token).decimals()), # <- This validates ERC20 ABI
A, isqrt(A_ratio * 10**18), self.ln_int(A_ratio),
p, fee, admin_fee, _price_oracle_contract,
code_offset=3)
controller: address = create_from_blueprint(
self.controller_implementation,
token, monetary_policy, loan_discount, liquidation_discount, amm,
code_offset=3)
AMM(amm).set_admin(controller)
self._set_debt_ceiling(controller, debt_ceiling, True)
N: uint256 = self.n_collaterals
self.collaterals[N] = token
for i in range(1000):
if self.collaterals_index[token][i] == 0:
self.collaterals_index[token][i] = 2**128 + N
break
assert i != 999, "Too many controllers for same collateral"
self.controllers[N] = controller
self.amms[N] = amm
self.n_collaterals = N + 1
log AddMarket(token, controller, amm, monetary_policy, N)
return [controller, amm]
@internal
@view
def calculate_rate() -> uint256:
sigma: int256 = self.sigma
target_debt_fraction: uint256 = self.target_debt_fraction
p: int256 = convert(PRICE_ORACLE.price(), int256)
pk_debt: uint256 = 0
for pk in self.peg_keepers:
if pk.address == empty(address):
break
pk_debt += pk.debt()
power: int256 = (10**18 - p) * 10**18 / sigma # high price -> negative pow -> low rate
if pk_debt > 0:
total_debt: uint256 = CONTROLLER_FACTORY.total_debt()
if total_debt == 0:
return 0
else:
power -= convert(pk_debt * 10**18 / total_debt * 10**18 / target_debt_fraction, int256)
return self.rate0 * min(self.exp(power), MAX_EXP) / 10**18
@external
def rate_write() -> uint256:
# Not needed here but useful for more automated policies
# which change rate0 - for example rate0 targeting some fraction pl_debt/total_debt
return self.calculate_rate()
@external
@view
def price() -> uint256:
n: uint256 = self.n_price_pairs
prices: uint256[MAX_PAIRS] = empty(uint256[MAX_PAIRS])
D: uint256[MAX_PAIRS] = empty(uint256[MAX_PAIRS])
Dsum: uint256 = 0
DPsum: uint256 = 0
for i in range(MAX_PAIRS):
if i == n:
break
price_pair: PricePair = self.price_pairs[i]
pool_supply: uint256 = price_pair.pool.totalSupply()
if pool_supply >= MIN_LIQUIDITY:
p: uint256 = price_pair.pool.price_oracle()
if price_pair.is_inverse:
p = 10**36 / p
prices[i] = p
_D: uint256 = price_pair.pool.get_virtual_price() * pool_supply / 10**18
D[i] = _D
Dsum += _D
DPsum += _D * p
if Dsum == 0:
return 10**18 # Placeholder for no active pools
p_avg: uint256 = DPsum / Dsum
e: uint256[MAX_PAIRS] = empty(uint256[MAX_PAIRS])
e_min: uint256 = max_value(uint256)
for i in range(MAX_PAIRS):
if i == n:
break
p: uint256 = prices[i]
e[i] = (max(p, p_avg) - min(p, p_avg))**2 / (SIGMA**2 / 10**18)
e_min = min(e[i], e_min)
wp_sum: uint256 = 0
w_sum: uint256 = 0
for i in range(MAX_PAIRS):
if i == n:
break
w: uint256 = D[i] * self.exp(-convert(e[i] - e_min, int256)) / 10**18
w_sum += w
wp_sum += w * prices[i]
return wp_sum / w_sum
@external
def set_admin(_admin: address):
"""
@notice Set admin of the AMM. Typically it's a controller (unless it's tests)
@param _admin Admin address
"""
assert self.admin == empty(address)
self.admin = _admin
self.approve_max(BORROWED_TOKEN, _admin)
self.approve_max(COLLATERAL_TOKEN, _admin)
▶Example▼
>>> ControllerFactory.add_market("0xae78736cd615f374d3085123a210448e74fc6393",
100,
6000000000000000,
0,
"price oracle contract",
"monetary policy contract",
90000000000000000,
60000000000000000,
10000000000000000000000000):
"returns AMM and Controller contract"
Debt Ceilings
debt_ceiling
ControllerFactory.debt_ceiling(agr0: address) -> uint256: viewGetter for the current debt ceiling of a market.
Returns: debt ceiling (uint256).
| Input | Type | Description |
|---|---|---|
arg0 | address | Address of the controller |
<>Source code▼
debt_ceiling: public(HashMap[address, uint256])
▶Example▼
>>> ControllerFactory.debt_ceiling("0x8472A9A7632b173c8Cf3a86D3afec50c35548e76")
10000000000000000000000000
debt_ceiling_residual
ControllerFactory.debt_ceiling_residual(arg0: address) -> uint256: viewGetter for the residual debt ceiling for a market.
Returns: debt ceiling residual (uint256).
| Input | Type | Description |
|---|---|---|
arg0 | address | Address of the controller |
<>Source code▼
debt_ceiling: public(HashMap[address, uint256])
▶Example▼
>>> ControllerFactory.debt_ceiling("0x8472A9A7632b173c8Cf3a86D3afec50c35548e76")
10000000000000000000000000
rug_debt_ceiling
ControllerFactory.rug_debt_ceiling(_to: address):Function to remove stablecoins above the debt seiling from a controller and burn them. This function is used to burn residual crvUSD when the debt ceiling was lowered.
| Input | Type | Description |
|---|---|---|
_to | address | Address of the controller to remove stablecoins from |
<>Source code▼
@external
@nonreentrant('lock')
def rug_debt_ceiling(_to: address):
"""
@notice Remove stablecoins above the debt ceiling from the address and burn them
@param _to Address to remove stablecoins from
"""
self._set_debt_ceiling(_to, self.debt_ceiling[_to], False)
@internal
def _set_debt_ceiling(addr: address, debt_ceiling: uint256, update: bool):
"""
@notice Set debt ceiling for a market
@param addr Controller address
@param debt_ceiling Value for stablecoin debt ceiling
@param update Whether to actually update the debt ceiling (False is used for burning the residuals)
"""
old_debt_residual: uint256 = self.debt_ceiling_residual[addr]
if debt_ceiling > old_debt_residual:
to_mint: uint256 = debt_ceiling - old_debt_residual
STABLECOIN.mint(addr, to_mint)
self.debt_ceiling_residual[addr] = debt_ceiling
log MintForMarket(addr, to_mint)
if debt_ceiling < old_debt_residual:
diff: uint256 = min(old_debt_residual - debt_ceiling, STABLECOIN.balanceOf(addr))
STABLECOIN.burnFrom(addr, diff)
self.debt_ceiling_residual[addr] = old_debt_residual - diff
log RemoveFromMarket(addr, diff)
if update:
self.debt_ceiling[addr] = debt_ceiling
log SetDebtCeiling(addr, debt_ceiling)
▶Example▼
>>> ControllerFactory.rug_debt_ceiling("controller address")
set_debt_ceiling
ControllerFactory.set_debt_ceiling(_to: address, debt_ceiling: uint256):This function is only callable by the admin of the contract.
Function to set the debt ceiling of a market and mint the token amount given for it.
Returns: debt ceiling (uint256).
Emits: MintForMarket or RemoveFromMarket or SetDebtCeiling
| Input | Type | Description |
|---|---|---|
_to | address | Address to set debt ceiling for |
debt_ceiling | uint256 | Maximum to be allowed to mint |
<>Source code▼
event SetDebtCeiling:
addr: indexed(address)
debt_ceiling: uint256
event MintForMarket:
addr: indexed(address)
amount: uint256
event RemoveFromMarket:
addr: indexed(address)
amount: uint256
@internal
def _set_debt_ceiling(addr: address, debt_ceiling: uint256, update: bool):
"""
@notice Set debt ceiling for a market
@param addr Controller address
@param debt_ceiling Value for stablecoin debt ceiling
@param update Whether to actually update the debt ceiling (False is used for burning the residuals)
"""
old_debt_residual: uint256 = self.debt_ceiling_residual[addr]
if debt_ceiling > old_debt_residual:
to_mint: uint256 = debt_ceiling - old_debt_residual
STABLECOIN.mint(addr, to_mint)
self.debt_ceiling_residual[addr] = debt_ceiling
log MintForMarket(addr, to_mint)
if debt_ceiling < old_debt_residual:
diff: uint256 = min(old_debt_residual - debt_ceiling, STABLECOIN.balanceOf(addr))
STABLECOIN.burnFrom(addr, diff)
self.debt_ceiling_residual[addr] = old_debt_residual - diff
log RemoveFromMarket(addr, diff)
if update:
self.debt_ceiling[addr] = debt_ceiling
log SetDebtCeiling(addr, debt_ceiling)
@external
@nonreentrant('lock')
def set_debt_ceiling(_to: address, debt_ceiling: uint256):
"""
@notice Set debt ceiling of the address - mint the token amount given for it
@param _to Address to allow borrowing for
@param debt_ceiling Maximum allowed to be allowed to mint for it
"""
assert msg.sender == self.admin
self._set_debt_ceiling(_to, debt_ceiling, True)
@external
def mint(_to: address, _value: uint256) -> bool:
"""
@notice Mint `_value` amount of tokens to `_to`.
@dev Only callable by an account with minter privileges.
@param _to The account newly minted tokens are credited to.
@param _value The amount of tokens to mint.
"""
assert msg.sender == self.minter
assert _to not in [self, empty(address)]
self.balanceOf[_to] += _value
self.totalSupply += _value
log Transfer(empty(address), _to, _value)
return True
@external
def burn(_value: uint256) -> bool:
"""
@notice Burn `_value` amount of tokens.
@param _value The amount of tokens to burn.
"""
self._burn(msg.sender, _value)
return True
▶Example▼
>>> ControllerFactory.set_debt_ceiling(20000000000000000000000000)
Fee Receiver
The fee receiver is the address that receives the claimed fees when calling collect_fees() on the Controller.
A new receiver can be set by the admin of the contract, which is the CurveOwnershipAgent.
fee_receiver
ControllerFactory.fee_receiver() -> address: viewGetter for the fee receiver address.
Returns: address of fee receiver.
<>Source code▼
fee_receiver: public(address)
@external
def __init__(stablecoin: ERC20,
admin: address,
fee_receiver: address,
weth: address):
"""
@notice Factory which creates both controllers and AMMs from blueprints
@param stablecoin Stablecoin address
@param admin Admin of the factory (ideally DAO)
@param fee_receiver Receiver of interest and admin fees
@param weth Address of WETH contract address
"""
STABLECOIN = stablecoin
self.admin = admin
self.fee_receiver = fee_receiver
WETH = weth
▶Example▼
>>> ControllerFactory.fee_receiver()
'0xeCb456EA5365865EbAb8a2661B0c503410e9B347'
set_fee_receiver
ControllerFactory.set_fee_receiver(fee_receiver: address):This function is only callable by the admin of the contract.
Function to set the fee receiver address.
Emits: SetFeeReceiver
| Input | Type | Description |
|---|---|---|
fee_receiver | address | Address of the receiver |
<>Source code▼
event SetFeeReceiver:
fee_receiver: address
fee_receiver: public(address)
@external
@nonreentrant('lock')
def set_fee_receiver(fee_receiver: address):
"""
@notice Set fee receiver who earns interest (DAO)
@param fee_receiver Address of the receiver
"""
assert msg.sender == self.admin
assert fee_receiver != empty(address)
self.fee_receiver = fee_receiver
log SetFeeReceiver(fee_receiver)
▶Example▼
>>> ControllerFactory.set_fee_receiver("0xeCb456EA5365865EbAb8a2661B0c503410e9B347")
collect_fees_above_ceiling
ControllerFactory.collect_fees_above_ceiling(_to: address):This function is only callable by the admin of the contract.
Function to claim fees above the debt ceiling. This function will automatically increase the debt ceiling if there is not enough to claim admin fees.
| Input | Type | Description |
|---|---|---|
_to | address | Address of the controller |
<>Source code▼
@external
@nonreentrant('lock')
def collect_fees_above_ceiling(_to: address):
"""
@notice If the receiver is the controller - increase the debt ceiling if it's not enough to claim admin fees
and claim them
@param _to Address of the controller
"""
assert msg.sender == self.admin
old_debt_residual: uint256 = self.debt_ceiling_residual[_to]
assert self.debt_ceiling[_to] > 0 or old_debt_residual > 0
admin_fees: uint256 = Controller(_to).total_debt() + Controller(_to).redeemed() - Controller(_to).minted()
b: uint256 = STABLECOIN.balanceOf(_to)
if admin_fees > b:
to_mint: uint256 = admin_fees - b
STABLECOIN.mint(_to, to_mint)
self.debt_ceiling_residual[_to] = old_debt_residual + to_mint
Controller(_to).collect_fees()
▶Example▼
>>> ControllerFactory.collect_fees_above_ceiling("0x100dAa78fC509Db39Ef7D04DE0c1ABD299f4C6CE")
Implementations
Implementations are blueprint contracts used to deploy new markets. When calling add_market, Controller and AMM are created from the current implementations.
controller_implementation
ControllerFactory.controller_implementation() -> address: viewGetter for controller implementation address.
Returns: implementation (address).
<>Source code▼
collaterals: public(address[MAX_CONTROLLERS])
▶Example▼
>>> ControllerFactory.controller_implementation()
'0x6340678b2bab22a37d781Cd8da958a3cD1d97cdD'
amm_implementation
ControllerFactory.amm_implementation() -> address: viewGetter for amm implementation address.
Returns: implementation (address).
<>Source code▼
amm_implementation: public(address)
▶Example▼
>>> ControllerFactory.amm_implementation()
'0x3da7fF6C15C0c97D9C2dF4AF82a9910384b372FD'
set_implementations
ControllerFactory.set_implementations(controller: address, amm: address):This function is only callable by the admin of the contract.
Function to set new implementations (blueprints) for Controller and AMM. Setting new implementations for Controller and AMM does not affect the existing ones.
Emits: SetImplementations
| Input | Type | Description |
|---|---|---|
controller | Address | Address of the controller blueprint |
amm | Address | Address of the amm blueprint |
<>Source code▼
event SetImplementations:
amm: address
controller: address
controller_implementation: public(address)
amm_implementation: public(address)
@external
@nonreentrant('lock')
def set_implementations(controller: address, amm: address):
"""
@notice Set new implementations (blueprints) for controller and amm. Doesn't change existing ones
@param controller Address of the controller blueprint
@param amm Address of the AMM blueprint
"""
assert msg.sender == self.admin
assert controller != empty(address)
assert amm != empty(address)
self.controller_implementation = controller
self.amm_implementation = amm
log SetImplementations(amm, controller)
▶Example▼
>>> ControllerFactory.set_implementation("new controller implementation, new amm implementation")
Contract Info Methods
stablecoin
ControllerFactory.stablecoin() -> address: viewGetter for the stablecoin address.
Returns: stablecoin (address).
<>Source code▼
STABLECOIN: immutable(ERC20)
@external
def __init__(stablecoin: ERC20,
admin: address,
fee_receiver: address,
weth: address):
"""
@notice Factory which creates both controllers and AMMs from blueprints
@param stablecoin Stablecoin address
@param admin Admin of the factory (ideally DAO)
@param fee_receiver Receiver of interest and admin fees
@param weth Address of WETH contract address
"""
STABLECOIN = stablecoin
self.admin = admin
self.fee_receiver = fee_receiver
WETH = weth
▶Example▼
>>> ControllerFactory.stablecoin()
'0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E'
total_debt
ControllerFactory.total_debt() -> uint256: viewGetter for the sum of all debts across the controllers.
Returns: total amount of debt (uint256).
<>Source code▼
@external
@view
def total_debt() -> uint256:
"""
@notice Sum of all debts across controllers
"""
total: uint256 = 0
n_collaterals: uint256 = self.n_collaterals
for i in range(MAX_CONTROLLERS):
if i == n_collaterals:
break
total += Controller(self.controllers[i]).total_debt()
return total
▶Example▼
>>> ControllerFactory.total_debt()
37565735180665889485176526
get_controller
ControllerFactory.get_controller(collateral: address, i: uint256 = 0) -> address:Getter for the controller address for collateral.
Returns: controller address.
| Input | Type | Description |
|---|---|---|
collateral | address | Address of collateral token |
i | uint256 | Index to iterate over several controller for the same collateral if needed |
<>Source code▼
@external
@view
def get_controller(collateral: address, i: uint256 = 0) -> address:
"""
@notice Get controller address for collateral
@param collateral Address of collateral token
@param i Iterate over several controllers for collateral if needed
"""
return self.controllers[self.collaterals_index[collateral][i] - 2**128]
▶Example▼
>>> ControllerFactory.get_controller("0xac3E018457B222d93114458476f3E3416Abbe38F", 0)
'0x8472A9A7632b173c8Cf3a86D3afec50c35548e76'
get_amm
ControllerFactory.get_amm(collateral: address, i: uint256 = 0) -> address:Getter for the amm address for collateral.
Returns: amm address.
| Input | Type | Description |
|---|---|---|
collateral | address | Address of collateral token |
i | uint256 | Index to iterate over several amms for the same collateral if needed |
<>Source code▼
@external
@view
def get_amm(collateral: address, i: uint256 = 0) -> address:
"""
@notice Get AMM address for collateral
@param collateral Address of collateral token
@param i Iterate over several AMMs for collateral if needed
"""
return self.amms[self.collaterals_index[collateral][i] - 2**128]
▶Example▼
>>> ControllerFactory.get_amm("0xac3E018457B222d93114458476f3E3416Abbe38F", 0)
'0x136e783846ef68C8Bd00a3369F787dF8d683a696'
controllers
ControllerFactory.controllers(arg0: uint256) -> address:Getter for the controller address at index arg0.
Returns: controller address at specific index.
| Input | Type | Description |
|---|---|---|
arg0 | uint256 | Index |
<>Source code▼
MAX_CONTROLLERS: constant(uint256) = 50000
controllers: public(address[MAX_CONTROLLERS])
▶Example▼
>>> ControllerFactory.controllers(0)
'0x8472A9A7632b173c8Cf3a86D3afec50c35548e76'
amms
ControllerFactory.amms(arg0: uint256) -> address:Getter for the amm address at index arg0.
Returns: AMM address at specific index.
| Input | Type | Description |
|---|---|---|
arg0 | uint256 | Index |
<>Source code▼
amms: public(address[MAX_CONTROLLERS])
▶Example▼
>>> ControllerFactory.amms(0)
'0x136e783846ef68C8Bd00a3369F787dF8d683a696'
n_collaterals
ControllerFactory.n_collaterals() -> uint256: viewGetter for the number of collaterals.
Returns: number of collaterals (uint256).
<>Source code▼
n_collaterals: public(uint256)
▶Example▼
>>> ControllerFactory.n_collaterals()
2
collaterals
ControllerFactory.collaterals(arg0: uint256) -> address: viewGetter for the collateral addresses at index arg0.
Returns: address of collateral.
| Input | Type | Description |
|---|---|---|
arg0 | uint256 | Index |
<>Source code▼
collaterals: public(address[MAX_CONTROLLERS])
▶Example▼
>>> ControllerFactory.collaterals(0)
'0xac3E018457B222d93114458476f3E3416Abbe38F'
collaterals_index
ControllerFactory.collaterals(arg0: address, arg1: uint256) -> uint256: viewGetter for the index of a controller for arg0.
Returns: index (uint256).
The returned value is + index.
| Input | Type | Description |
|---|---|---|
arg0 | address | Address of collateral |
arg0 | uint256 | Index |
<>Source code▼
collaterals_index: public(HashMap[address, uint256[1000]])
▶Example▼
>>> ControllerFactory.collaterals(0xac3E018457B222d93114458476f3E3416Abbe38F, 0)
340282366920938463463374607431768211456
WETH
ControllerFactory.WETH() -> address: viewGetter for WETH address.
Returns: address of WETH.
<>Source code▼
WETH: public(immutable(address))
@external
def __init__(stablecoin: ERC20,
admin: address,
fee_receiver: address,
weth: address):
"""
@notice Factory which creates both controllers and AMMs from blueprints
@param stablecoin Stablecoin address
@param admin Admin of the factory (ideally DAO)
@param fee_receiver Receiver of interest and admin fees
@param weth Address of WETH contract address
"""
STABLECOIN = stablecoin
self.admin = admin
self.fee_receiver = fee_receiver
WETH = weth
▶Example▼
>>> ControllerFactory.WETH()
'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
Admin Ownership
admin
ControllerFactory.admin() -> address: viewGetter for the admin of the contract.
Returns: admin (address).
<>Source code▼
admin: public(address)
@external
def __init__(stablecoin: ERC20,
admin: address,
fee_receiver: address,
weth: address):
"""
@notice Factory which creates both controllers and AMMs from blueprints
@param stablecoin Stablecoin address
@param admin Admin of the factory (ideally DAO)
@param fee_receiver Receiver of interest and admin fees
@param weth Address of WETH contract address
"""
STABLECOIN = stablecoin
self.admin = admin
self.fee_receiver = fee_receiver
WETH = weth
▶Example▼
>>> ControllerFactory.admin()
'0x40907540d8a6C65c637785e8f8B742ae6b0b9968'
set_admin
ControllerFactory.set_admin(admin: address):This function is only callable by the admin of the contract.
Function to set the admin of the contract.
Emits: SetAdmin
| Input | Type | Description |
|---|---|---|
admin | address | New admin |
<>Source code▼
event SetAdmin:
admin: address
admin: public(address)
@external
@nonreentrant('lock')
def set_admin(admin: address):
"""
@notice Set admin of the factory (should end up with DAO)
@param admin Address of the admin
"""
assert msg.sender == self.admin
self.admin = admin
log SetAdmin(admin)
▶Example▼
>>> ControllerFactory.set_admin("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")