Skip to main content

OneWay Lending Factory

warning

This is the LlamaLend v1 factory. For new LlamaLend v2 markets, use the LendFactory reference.

A one-way lending market is a non-rehypothecating market where one token is considered the collateral token and another token is the borrow token. This means the deposited collateral cannot be lent out but can only be used as collateral.

OneWayLendingFactory.vy

The source code for the OneWayLendingFactory.vy contract can be found on GitHub. The contract is written using Vyper version 0.3.10.

Later on, two-way lending markets will be established, allowing the collateral provided to be lent out and used as liquidity to borrow.


Creating Lending Markets​

A lending market must always include crvUSD, either as collateral or as the borrowable token.

There are two ways to create lending markets:

  • create: This method involves creating a vault and its accompanying contracts using an external user-supplied price oracle.
  • create_from_pool: This method involves creating a vault and its accompanying contracts using an existing oraclized Curve pool as a price oracle.
Finding Optimal Parameters

To find optimal values for the parameters, check out: https://github.com/curvefi/llamma-simulator.

Regarding rates: Minimum and maximum borrow rates for lending markets default to min_default_borrow_rate and max_default_borrow_rate if input values for min_borrow_rate and max_borrow_rate are set to zero. If custom values are used, they need to be within the range of MIN_RATE and MAX_RATE.

create​

OneWayLendingVaultFactory.create(borrowed_token: address, collateral_token: address, A: uint256, fee: uint256, loan_discount: uint256, liquidation_discount: uint256, price_oracle: address, name: String[64], min_borrow_rate: uint256 = 0, max_borrow_rate: uint256 = 0) -> Vault

Function to create a new vault using a user-supplied price oracle contract.

InputTypeDescription
borrowed_tokenaddressToken which is being borrowed.
collateral_tokenaddressToken used as collateral.
Auint256Amplification coefficient. Band size is ~1/A.
feeuint256Fee for swaps in the AMM.
loan_discountuint256Maximum discount. LTV = sqrt(((A - 1) / A) **4) - loan_discount.
liquidation_discountuint256Liquidation discount. LT = sqrt(((A - 1) / A) **4) - liquidation_discount
price_oracleaddressCustom price oracle contract.
nameString[64]Name of the vault.
min_borrow_rateuint256Custom minimum borrow rate; if not set will default to min_default_borrow_rate
max_borrow_rateuint256Custom maximum borrow rate; if not set will default to max_default_borrow_rate

Returns: vault (address).

Emits: NewVault event.

<>Source code▼
event NewVault:
id: indexed(uint256)
collateral_token: indexed(address)
borrowed_token: indexed(address)
vault: address
controller: address
amm: address
price_oracle: address
monetary_policy: address

@external
@nonreentrant('lock')
def create(
borrowed_token: address,
collateral_token: address,
A: uint256,
fee: uint256,
loan_discount: uint256,
liquidation_discount: uint256,
price_oracle: address,
name: String[64],
min_borrow_rate: uint256 = 0,
max_borrow_rate: uint256 = 0
) -> Vault:
"""
@notice Creation of the vault using user-supplied price oracle contract
@param borrowed_token Token which is being borrowed
@param collateral_token Token used for collateral
@param A Amplification coefficient: band size is ~1/A
@param fee Fee for swaps in AMM (for ETH markets found to be 0.6%)
@param loan_discount Maximum discount. LTV = sqrt(((A - 1) / A) **4) - loan_discount
@param liquidation_discount Liquidation discount. LT = sqrt(((A - 1) / A) **4) - liquidation_discount
@param price_oracle Custom price oracle contract
@param name Human-readable market name
@param min_borrow_rate Custom minimum borrow rate (otherwise min_default_borrow_rate)
@param max_borrow_rate Custom maximum borrow rate (otherwise max_default_borrow_rate)
"""
return self._create(borrowed_token, collateral_token, A, fee, loan_discount, liquidation_discount,
price_oracle, name, min_borrow_rate, max_borrow_rate)

@internal
def _create(
borrowed_token: address,
collateral_token: address,
A: uint256,
fee: uint256,
loan_discount: uint256,
liquidation_discount: uint256,
price_oracle: address,
name: String[64],
min_borrow_rate: uint256,
max_borrow_rate: uint256
) -> Vault:
"""
@notice Internal method for creation of the vault
"""
assert borrowed_token != collateral_token, "Same token"
assert borrowed_token == STABLECOIN or collateral_token == STABLECOIN
vault: Vault = Vault(create_minimal_proxy_to(self.vault_impl))

min_rate: uint256 = self.min_default_borrow_rate
max_rate: uint256 = self.max_default_borrow_rate
if min_borrow_rate > 0:
min_rate = min_borrow_rate
if max_borrow_rate > 0:
max_rate = max_borrow_rate
assert min_rate >= MIN_RATE and max_rate <= MAX_RATE and min_rate <= max_rate, "Wrong rates"
monetary_policy: address = create_from_blueprint(
self.monetary_policy_impl, borrowed_token, min_rate, max_rate, code_offset=3)

controller: address = empty(address)
amm: address = empty(address)
controller, amm = vault.initialize(
self.amm_impl, self.controller_impl,
borrowed_token, collateral_token,
A, fee,
price_oracle,
monetary_policy,
loan_discount, liquidation_discount
)

market_count: uint256 = self.market_count
log NewVault(market_count, collateral_token, borrowed_token, vault.address, controller, amm, price_oracle, monetary_policy)
self.vaults[market_count] = vault
self.amms[market_count] = AMM(amm)
self._vaults_index[vault] = market_count + 2**128
self.names[market_count] = name

self.market_count = market_count + 1

token: address = borrowed_token
if borrowed_token == STABLECOIN:
token = collateral_token
market_count = self.token_market_count[token]
self.token_to_vaults[token][market_count] = vault
self.token_market_count[token] = market_count + 1

ERC20(borrowed_token).approve(amm, max_value(uint256))
ERC20(collateral_token).approve(amm, max_value(uint256))

return vault
▶Example▼
>>> OneWayLendingVaultFactory.create(
"0xf939e0a03fb07f59a73314e73794be0e57ac1b4e", # borrowed_token
"0x8f22779662ad253844013d8e99eccb4d80e31417", # collateral_token
50, # A
6000000000000000, # fee
140000000000000000, # loan_discount
110000000000000000, # liquidation_discount
external price oracle, # price_oracle
"bobrCRV-long", # name
0, # min_borrow_rate
1) # max_borrow_rate

'0xE16D806c4198955534d4EB10E4861Ea94557602E' # returns address of the created vault

create_from_pool​

OneWayLendingVaultFactory.create_from_pool(borrowed_token: address, collateral_token: address, A: uint256, fee: uint256, loan_discount: uint256, liquidation_discount: uint256, pool: address, name: String[64], min_borrow_rate: uint256 = 0, max_borrow_rate: uint256 = 0) -> Vault
Valid Pool Oracles

Only oracles from stableswap-ng, twocrypto-ng, and tricrypto-ng pools are valid. Oracles from other pools may not be manipulation resistant and therefore should not be used.

Function to create a new vault using a existing oraclized Curve pool as the price oracle.

InputTypeDescription
borrowed_tokenaddressToken which is being borrowed.
collateral_tokenaddressToken used as collateral.
Auint256Amplification coefficient. Band size is ~1/A.
feeuint256Fee for swaps in the AMM.
loan_discountuint256Maximum discount. LTV = sqrt(((A - 1) / A) **4) - loan_discount.
liquidation_discountuint256Liquidation discount. LT = sqrt(((A - 1) / A) **4) - liquidation_discount
pooladdressCurve tricrypto-ng, twocrypto-ng or stableswap-ng pool which has non-manipulatable price_oracle(). Must contain both collateral_token and borrowed_token.
nameString[64]Name of the vault.
min_borrow_rateuint256Custom minimum borrow rate; if not set will default to min_default_borrow_rate
max_borrow_rateuint256Custom maximum borrow rate; if not set will default to max_default_borrow_rate

Returns: vault (address).

Emits: NewVault event.

<>Source code▼
event NewVault:
id: indexed(uint256)
collateral_token: indexed(address)
borrowed_token: indexed(address)
vault: address
controller: address
amm: address
price_oracle: address
monetary_policy: address

@external
@nonreentrant('lock')
def create_from_pool(
borrowed_token: address,
collateral_token: address,
A: uint256,
fee: uint256,
loan_discount: uint256,
liquidation_discount: uint256,
pool: address,
name: String[64],
min_borrow_rate: uint256 = 0,
max_borrow_rate: uint256 = 0
) -> Vault:
"""
@notice Creation of the vault using existing oraclized Curve pool as a price oracle
@param borrowed_token Token which is being borrowed
@param collateral_token Token used for collateral
@param A Amplification coefficient: band size is ~1/A
@param fee Fee for swaps in AMM (for ETH markets found to be 0.6%)
@param loan_discount Maximum discount. LTV = sqrt(((A - 1) / A) **4) - loan_discount
@param liquidation_discount Liquidation discount. LT = sqrt(((A - 1) / A) **4) - liquidation_discount
@param pool Curve tricrypto-ng, twocrypto-ng or stableswap-ng pool which has non-manipulatable price_oracle().
Must contain both collateral_token and borrowed_token.
@param name Human-readable market name
@param min_borrow_rate Custom minimum borrow rate (otherwise min_default_borrow_rate)
@param max_borrow_rate Custom maximum borrow rate (otherwise max_default_borrow_rate)
"""
# Find coins in the pool
borrowed_ix: uint256 = 100
collateral_ix: uint256 = 100
N: uint256 = 0
for i in range(10):
success: bool = False
res: Bytes[32] = empty(Bytes[32])
success, res = raw_call(
pool,
_abi_encode(i, method_id=method_id("coins(uint256)")),
max_outsize=32, is_static_call=True, revert_on_failure=False)
coin: address = convert(res, address)
if not success or coin == empty(address):
break
N += 1
if coin == borrowed_token:
borrowed_ix = i
elif coin == collateral_token:
collateral_ix = i
if collateral_ix == 100 or borrowed_ix == 100:
raise "Tokens not in pool"
price_oracle: address = create_from_blueprint(
self.pool_price_oracle_impl, pool, N, borrowed_ix, collateral_ix, code_offset=3)

return self._create(borrowed_token, collateral_token, A, fee, loan_discount, liquidation_discount,
price_oracle, name, min_borrow_rate, max_borrow_rate)

@internal
def _create(
borrowed_token: address,
collateral_token: address,
A: uint256,
fee: uint256,
loan_discount: uint256,
liquidation_discount: uint256,
price_oracle: address,
name: String[64],
min_borrow_rate: uint256,
max_borrow_rate: uint256
) -> Vault:
"""
@notice Internal method for creation of the vault
"""
assert borrowed_token != collateral_token, "Same token"
assert borrowed_token == STABLECOIN or collateral_token == STABLECOIN
vault: Vault = Vault(create_minimal_proxy_to(self.vault_impl))

min_rate: uint256 = self.min_default_borrow_rate
max_rate: uint256 = self.max_default_borrow_rate
if min_borrow_rate > 0:
min_rate = min_borrow_rate
if max_borrow_rate > 0:
max_rate = max_borrow_rate
assert min_rate >= MIN_RATE and max_rate <= MAX_RATE and min_rate <= max_rate, "Wrong rates"
monetary_policy: address = create_from_blueprint(
self.monetary_policy_impl, borrowed_token, min_rate, max_rate, code_offset=3)

controller: address = empty(address)
amm: address = empty(address)
controller, amm = vault.initialize(
self.amm_impl, self.controller_impl,
borrowed_token, collateral_token,
A, fee,
price_oracle,
monetary_policy,
loan_discount, liquidation_discount
)

market_count: uint256 = self.market_count
log NewVault(market_count, collateral_token, borrowed_token, vault.address, controller, amm, price_oracle, monetary_policy)
self.vaults[market_count] = vault
self.amms[market_count] = AMM(amm)
self._vaults_index[vault] = market_count + 2**128
self.names[market_count] = name

self.market_count = market_count + 1

token: address = borrowed_token
if borrowed_token == STABLECOIN:
token = collateral_token
market_count = self.token_market_count[token]
self.token_to_vaults[token][market_count] = vault
self.token_market_count[token] = market_count + 1

ERC20(borrowed_token).approve(amm, max_value(uint256))
ERC20(collateral_token).approve(amm, max_value(uint256))

return vault
▶Example▼
>>> OneWayLendingVaultFactory.create_from_pool(
"0xf939e0a03fb07f59a73314e73794be0e57ac1b4e", # borrowed_token
"0x8f22779662ad253844013d8e99eccb4d80e31417", # collateral_token
50, # A
6000000000000000, # fee
140000000000000016, # loan_discount
110000000000000000, # liquidation_discount
"0x9fee65d5a627e73212989c8bbedc5fa5cae3821f", # pool to use oracle from
"bobrCRV-long", # name
0, # min_borrow_rate
1) # max_borrow_rate

'0xE16D806c4198955534d4EB10E4861Ea94557602E' # returns address of the created vault

Deploying Gauges​

Just like pools, vaults can have liquidity gauges. Once they are added to the GaugeController by the DAO, they are eligible to receive CRV emissions.

deploy_gauge​

OneWayLendingVaultFactory.deploy_gauge(_vault: Vault) -> address

Function to deploy a liquidity gauge for a vault.

InputTypeDescription
_vaultaddressVault address to deploy the gauge for.

Returns: gauge (address).

Emits: LiquidityGaugeDeployed event.

<>Source code▼
event LiquidityGaugeDeployed:
vault: address
gauge: address

@external
def deploy_gauge(_vault: Vault) -> address:
"""
@notice Deploy a liquidity gauge for a vault
@param _vault Vault address to deploy a gauge for
@return Address of the deployed gauge
"""
ix: uint256 = self._vaults_index[_vault]
assert ix != 0, "Unknown vault"
ix -= 2**128
assert self.gauges[ix] == empty(address), "Gauge already deployed"
implementation: address = self.gauge_impl
assert implementation != empty(address), "Gauge implementation not set"

gauge: address = create_from_blueprint(implementation, _vault, code_offset=3)
self.gauges[ix] = gauge

log LiquidityGaugeDeployed(_vault.address, gauge)
return gauge
▶Example▼
In  [1]: OneWayLendingVaultFactory.deploy_gauge("0xE16D806c4198955534d4EB10E4861Ea94557602E")
Out [1]: '0xACEBA186aDF691245dfb20365B48DB87DEA7b98F' # returns address of deployed gauge

Rates​

The Factory has a MIN_RATE and MAX_RATE. These variables are constants and can not be changed. The minimum rate is 0.1%, the maximum rate is 1000%.

Additionally, the Factory has two variables, min_default_borrow_rate and max_default_borrow_rate, which are used as default values when creating new lending markets.
If no value is given when deploying a new market, the default rates are applied. Default rates can be changed by the admin via the set_default_rates method.

Rates are denominated in seconds and have a base unit of 1e18.

To get the annualized value, do:

Annualized Rate=rate×86400×365\text{Annualized Rate} = \text{rate} \times 86400 \times 365

Google Colab Notebook

A notebook on how to change default borrow rates and how to calculate annualized rates can be found here: https://colab.research.google.com/drive/1mQV5yDyBqZrVSIOweP2g1Qu3WWjsgZtv?usp=sharing.

MIN_RATE​

OneWayLendingVaultFactory.MIN_RATE() -> uint256: view

Getter for the minimum rate a one-way lending vault can have. This variable is a constant and can therefore not be changed.

Returns: minimum rate (uint256).

<>Source code▼
MIN_RATE: public(constant(uint256)) = 10**15 / (365 * 86400)  # 0.1%
▶Example▼
In  [1]:  OneWayLendingVaultFactory.MIN_RATE()
Out [1]: 31709791 # 0.1%

MAX_RATE​

OneWayLendingVaultFactory.MAX_RATE() -> uint256: view

Getter for the maximum rate a one-way lending vault can have. This variable is a constant and can therefore not be changed.

Returns: maximum rate (uint256).

<>Source code▼
MAX_RATE: public(constant(uint256)) = 10**19 / (365 * 86400)  # 1000%
▶Example▼
In  [1]:  OneWayLendingVaultFactory.MAX_RATE()
Out [1]: 317097919837 # 1000%

min_default_borrow_rate​

OneWayLendingVaultFactory.min_default_borrow_rate() -> uint256: view

Getter for the minimum default borrow rate which is used when creating a new vault. The minimum borrow rate is charged when the utilization is 0. This parameter can be changed via the set_default_rates function.

Returns: minimum default borrow rate (uint256).

<>Source code▼
min_default_borrow_rate: public(uint256)

@external
@nonreentrant('lock')
def set_default_rates(min_rate: uint256, max_rate: uint256):
"""
@notice Change min and max default borrow rates for creating new markets
@param min_rate Minimal borrow rate (0 utilization)
@param max_rate Maxumum borrow rate (100% utilization)
"""
assert msg.sender == self.admin

assert min_rate >= MIN_RATE
assert max_rate <= MAX_RATE
assert max_rate >= min_rate

self.min_default_borrow_rate = min_rate
self.max_default_borrow_rate = max_rate

log SetDefaultRates(min_rate, max_rate)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.min_default_borrow_rate()
Out [1]: 158548959 # 0.5%

max_default_borrow_rate​

OneWayLendingVaultFactory.max_default_borrow_rate() -> uint256: view

Getter for the maximum default borrow rate which is used when creating a new vault. The maximum borrow rate is charged when the utilization is 100%. This parameter can be changed via the set_default_rates function.

Returns: maximum default borrow rate (uint256).

<>Source code▼
max_default_borrow_rate: public(uint256)

@external
@nonreentrant('lock')
def set_default_rates(min_rate: uint256, max_rate: uint256):
"""
@notice Change min and max default borrow rates for creating new markets
@param min_rate Minimal borrow rate (0 utilization)
@param max_rate Maxumum borrow rate (100% utilization)
"""
assert msg.sender == self.admin

assert min_rate >= MIN_RATE
assert max_rate <= MAX_RATE
assert max_rate >= min_rate

self.min_default_borrow_rate = min_rate
self.max_default_borrow_rate = max_rate

log SetDefaultRates(min_rate, max_rate)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.max_default_borrow_rate()
Out [1]: 15854895991 # 50%

set_default_rates​

OneWayLendingVaultFactory.set_default_rates(min_rate: uint256, max_rate: uint256)
Guarded Method

This function is only callable by the admin of the contract.

Function to set new values for the maximum (max_default_borrow_rate) and minimum (min_default_borrow_rate) default borrow rates.

InputTypeDescription
min_rateuint256New minimum default borrow rate.
max_rateuint256New maximum default borrow rate.

Emits: SetDefaultRates event.

<>Source code▼
event SetDefaultRates:
min_rate: uint256
max_rate: uint256

min_default_borrow_rate: public(uint256)
max_default_borrow_rate: public(uint256)

@external
@nonreentrant('lock')
def set_default_rates(min_rate: uint256, max_rate: uint256):
"""
@notice Change min and max default borrow rates for creating new markets
@param min_rate Minimal borrow rate (0 utilization)
@param max_rate Maxumum borrow rate (100% utilization)
"""
assert msg.sender == self.admin

assert min_rate >= MIN_RATE
assert max_rate <= MAX_RATE
assert max_rate >= min_rate

self.min_default_borrow_rate = min_rate
self.max_default_borrow_rate = max_rate

log SetDefaultRates(min_rate, max_rate)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.min_default_borrow_rate()
Out [1]: 158548959

In [2]: OneWayLendingVaultFactory.max_default_borrow_rate()
Out [2]: 15854895991

In [3]: OneWayLendingVaultFactory.set_default_rates(168548959, 16854895991)

In [4]: OneWayLendingVaultFactory.min_default_borrow_rate()
Out [4]: 168548959

In [5]: OneWayLendingVaultFactory.max_default_borrow_rate()
Out [5]: 16854895991

Implementations​

The implementations of the Factory can be upgraded by the admin, which is the Curve DAO.

Google Colab Notebook

A notebook on how to change implementations using the set_implementations function can be found here: https://colab.research.google.com/drive/1r3Vhb28Wy8iX_YRBNpfnwjzS4dKuMADf?usp=sharing

controller_impl​

OneWayLendingVaultFactory.controller_impl() -> address: view

Getter for the controller implementation.

Returns: controller implementation (address).

<>Source code▼
controller_impl: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.controller_impl()
Out [1]: '0x5473B1BcBbC45d38d8fBb50a18a73aFb8B0637A7'

amm_impl​

OneWayLendingVaultFactory.amm_impl() -> address: view

Getter for the amm implementation.

Returns: amm implementation (address).

<>Source code▼
amm_impl: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.amm_impl()
Out [1]: '0x4f37395BdFbE3A0dca124ad3C9DbFe6A6cbc31D6'

vault_imp​

OneWayLendingVaultFactory.vault_imp() -> address: view

Getter for the vault implementation.

Returns: vault implementation (address).

<>Source code▼
vault_impl: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.vault_imp()
Out [1]: '0x596F8E49acE6fC8e09B561972360DC216f1c2A1f'

pool_price_oracle_impl​

OneWayLendingVaultFactory.pool_price_oracle_impl() -> address: view

Getter for the price oracle implementation when creating lending markets from pools.

Returns: pool price oracle implementation (address).

<>Source code▼
pool_price_oracle_impl: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.pool_price_oracle_impl()
Out [1]: '0x9164e210d123e6566DaF113136a73684C4AB01e2'

monetary_policy_impl​

OneWayLendingVaultFactory.monetary_policy_impl() -> address: view

Getter for the monetary policy implementation.

Returns: monetary policy implementation (address).

<>Source code▼
monetary_policy_impl: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.monetary_policy_impl()
Out [1]: '0xa7E98815c0193E01165720C3abea43B885ae67FD'

gauge_impl​

OneWayLendingVaultFactory.gauge_impl() -> address: view

Getter for the gauge implementation.

Returns: gauge implementation (address).

<>Source code▼
gauge_impl: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.gauge_impl()
Out [1]: '0x00B71A425Db7C8B65a46CF39c23A188e10A2DE99'

set_implementations​

OneWayLendingVaultFactory.set_implementations(controller: address, amm: address, vault: address, pool_price_oracle: address, monetary_policy: address, gauge: address)
Guarded Method

This function is only callable by the admin of the contract.

Function to set new implementations. If a certain implementation should not be changed, ZERO_ADDRESS can be used as a placeholder.

Emits: SetImplementations event.

InputTypeDescription
controlleraddressNew controller implementation.
ammaddressNew amm implementation.
vaultaddressNew vault implementation.
pool_price_oracleaddressNew pool price oracle implementation.
monetary_policyaddressNew monetary policy implementation.
gaugeaddressNew gauge implementation.
<>Source code▼
event SetImplementations:
amm: address
controller: address
vault: address
price_oracle: address
monetary_policy: address
gauge: address

# Implementations which can be changed by governance
amm_impl: public(address)
controller_impl: public(address)
vault_impl: public(address)
pool_price_oracle_impl: public(address)
monetary_policy_impl: public(address)
gauge_impl: public(address)

@external
@nonreentrant('lock')
def set_implementations(controller: address, amm: address, vault: address,
pool_price_oracle: address, monetary_policy: address, gauge: address):
"""
@notice Set new implementations (blueprints) for controller, amm, vault, pool price oracle and monetary polcy.
Doesn't change existing ones
@param controller Address of the controller blueprint
@param amm Address of the AMM blueprint
@param vault Address of the Vault template
@param pool_price_oracle Address of the pool price oracle blueprint
@param monetary_policy Address of the monetary policy blueprint
@param gauge Address for gauge implementation blueprint
"""
assert msg.sender == self.admin

if controller != empty(address):
self.controller_impl = controller
if amm != empty(address):
self.amm_impl = amm
if vault != empty(address):
self.vault_impl = vault
if pool_price_oracle != empty(address):
self.pool_price_oracle_impl = pool_price_oracle
if monetary_policy != empty(address):
self.monetary_policy_impl = monetary_policy
if gauge != empty(address):
self.gauge_impl = gauge

log SetImplementations(amm, controller, vault, pool_price_oracle, monetary_policy, gauge)
▶Example▼
>>> soon

Contract Ownership​

The Factory contract is owned by the DAO (CurveOwnershipAdmin). Ownership can be transferred using the set_admin function.

admin​

OneWayLendingVaultFactory.admin -> address: view

Getter for the admin of the Factory.

Returns: admin (address).

<>Source code▼
admin: public(address)
▶Example▼
In  [1]:  OneWayLendingVaultFactory.admin()
Out [1]: '0x40907540d8a6C65c637785e8f8B742ae6b0b9968'

set_admin​

OneWayLendingVaultFactory.set_admin(admin: address)
Guarded Method

This function is only callable by the admin of the contract.

Function to change the contract ownership by setting a new admin.

InputTypeDescription
adminaddressNew admin address.

Emits: SetAdmin event.

<>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▼
In  [1]:  OneWayLendingVaultFactory.admin()
Out [1]: '0x40907540d8a6C65c637785e8f8B742ae6b0b9968'

In [2]: OneWayLendingVaultFactory.set_admin("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")

In [3]: OneWayLendingVaultFactory.admin()
Out [3]: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'

Contract Info Methods​

Most information is queried based on vault indices. The first deployed vault is vault index 0, second one index 1, etc.

To get the index of a certain vault:

>>> OneWayLendingVaultFactory.vaults_index("0x67A18c18709C09D48000B321c6E1cb09F7181211")
1

vaults_index​

OneWayLendingVaultFactory.vaults_index(vault: Vault) -> uint256: view

Getter for the vault index within the factory by using the vault address.

Returns: vault index (uint256).

InputTypeDescription
vaultaddressVault address to get the index for.
<>Source code▼
_vaults_index: HashMap[Vault, uint256]

@view
@external
def vaults_index(vault: Vault) -> uint256:
return self._vaults_index[vault] - 2**128
▶Example▼
In  [1]:  OneWayLendingVaultFactory.vaults_index('0x67A18c18709C09D48000B321c6E1cb09F7181211')
Out [1]: 1

vaults​

OneWayLendingVaultFactory.vaults(arg0: uint256) -> address: view

Getter for the vault at index arg0.

Returns: vault (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
vaults: public(Vault[10**18])
▶Example▼
In  [1]:  OneWayLendingVaultFactory.vaults(0)
Out [1]: '0xE21C518a09b26Bf65B16767B97249385f12780d9'

In [2]: OneWayLendingVaultFactory.vaults(0)
Out [2]: '0x67A18c18709C09D48000B321c6E1cb09F7181211'

controllers​

OneWayLendingVaultFactory.controllers(n: uint256) -> address: view

Getter for the controller of the vault at index n. This variable holds all controllers of vaults deployed through this factory.

Returns: controller (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
interface Vault:
def amm() -> address: view

vaults: public(Vault[10**18])

@view
@external
def controllers(n: uint256) -> address:
return self.vaults[n].controller()
▶Example▼
In  [1]:  OneWayLendingVaultFactory.controllers(0)
Out [1]: '0x5E657c5227A596a860621C5551c9735d8f4A8BE3'

In [2]: OneWayLendingVaultFactory.controllers(1)
Out [2]: '0x7443944962D04720f8c220C0D25f56F869d6EfD4'

amms​

OneWayLendingVaultFactory.amms(n: uint256) -> address: view

Getter for the AMM of the vault at index n. This variable holds all AMMs of vaults deployed through this factory.

Returns: AMM (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
amms: public(AMM[10**18])
▶Example▼
In  [1]:  OneWayLendingVaultFactory.amms(0)
Out [1]: '0x0167B8a9A3959E698A3e3BCaFe829878FfB709e3'

In [2]: OneWayLendingVaultFactory.amms(1)
Out [2]: '0xafC1ab86045Cb2a07C23399dbE64b56D1B8B3239'

borrowed_tokens​

OneWayLendingVaultFactory.borrowed_tokens(n: uint256) -> address: view

Getter for the borrow token for the vault at index n. This variable holds all borrowable tokens of vaults deployed through this factory.

Returns: borrowable token (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
interface Vault:
def borrowed_token() -> address: view

vaults: public(Vault[10**18])

@view
@external
def borrowed_tokens(n: uint256) -> address:
return self.vaults[n].borrowed_token()
▶Example▼
In  [1]:  OneWayLendingVaultFactory.borrowed_tokens(0)
Out [1]: '0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E'

In [2]: OneWayLendingVaultFactory.borrowed_tokens(2)
Out [2]: '0xD533a949740bb3306d119CC777fa900bA034cd52'

collateral_tokens​

OneWayLendingVaultFactory.collateral_tokens(n: uint256) -> address: view

Getter for the collateral token for the vault at index n. This variable holds all collateral tokens of vaults deployed through this factory.

Returns: collateral token (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
interface Vault:
def collateral_token() -> address: view

vaults: public(Vault[10**18])

@view
@external
def collateral_tokens(n: uint256) -> address:
return self.vaults[n].collateral_token()
▶Example▼
In  [1]:  OneWayLendingVaultFactory.collateral_tokens(0)
Out [1]: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'

In [2]: OneWayLendingVaultFactory.collateral_tokens(1)
Out [2]: '0xD533a949740bb3306d119CC777fa900bA034cd52'

price_oracles​

OneWayLendingVaultFactory.price_oracles(n: uint256) -> address: view

Getter for the price oracle contracts for the vault at index n. This variable holds all price oracles of vaults deployed through this factory.

Returns: price oracle (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
interface Vault:
def price_oracle() -> address: view

vaults: public(Vault[10**18])

@view
@external
def price_oracles(n: uint256) -> address:
return self.vaults[n].price_oracle()
▶Example▼
In  [1]:  OneWayLendingVaultFactory.price_oracles(0)
Out [1]: '0xDf1B41413EafcCfC6E98BB905feaeB271d307aF3'

In [2]: OneWayLendingVaultFactory.price_oracles(1)
Out [2]: '0xc17B0451E6d8C0f71297d0f174590632BE81163c'

monetary_policies​

OneWayLendingVaultFactory.monetary_policies(n: uint256) -> address: view

Getter for the monetary policy contracts for the vault at index n. This variable holds all monetary policies of vaults deployed through this factory.

Returns: monetary policy (address).

InputTypeDescription
nuint256Vault index.
<>Source code▼
interface Vault:
def controller() -> address: view

interface Controller:
def monetary_policy() -> address: view

vaults: public(Vault[10**18])

@view
@external
def monetary_policies(n: uint256) -> address:
return Controller(self.vaults[n].controller()).monetary_policy()
▶Example▼
In  [1]:  OneWayLendingVaultFactory.monetary_policies(0)
Out [1]: '0xfd8eF79883815D6771FC986D43E3Dce60ea33726'

In [2]: OneWayLendingVaultFactory.monetary_policies(1)
Out [2]: '0x5c79C4cFE9D77B3d2385E119fADb4F8ff8c08294'

gauge_for_vault​

OneWayLendingVaultFactory.gauge_for_vault(_vault: Vault) -> address: view

Getter for the liquidity gauge of vault.

Returns: gauge (address).

InputTypeDescription
_vaultaddressVault address to get the gauge for.
<>Source code▼
_vaults_index: HashMap[Vault, uint256]

gauges: public(address[10**18])

@view
@external
def gauge_for_vault(_vault: Vault) -> address:
return self.gauges[self._vaults_index[_vault] - 2**128]
▶Example▼
In  [1]:  OneWayLendingVaultFactory.gauge_for_vault("0x67A18c18709C09D48000B321c6E1cb09F7181211")
Out [1]: '0xAA90BE8bd52aeA49314dFc6e385e21A4e9c4ea0c'

coins​

OneWayLendingVaultFactory.coins(vault_id: uint256) -> address[2]: view

Getter for the borrow and collateral token of vault_id.

Returns: borrow and collateral token (address[2]).

InputTypeDescription
vault_iduint256Vault index.
<>Source code▼
interface Vault:
def borrowed_token() -> address: view
def collateral_token() -> address: view

vaults: public(Vault[10**18])

@external
@view
def coins(vault_id: uint256) -> address[2]:
vault: Vault = self.vaults[vault_id]
return [vault.borrowed_token(), vault.collateral_token()]
▶Example▼
In  [1]:  OneWayLendingVaultFactory.coins(1)
Out [1]: [Address('0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E'),
Address('0xD533a949740bb3306d119CC777fa900bA034cd52')]

STABLECOIN​

OneWayLendingVaultFactory.STABLECOIN() -> address: view

Getter for the crvUSD token. Only crvUSD-containing lending vaults are possible.

Returns: crvUSD (address).

<>Source code▼
STABLECOIN: public(immutable(address))

@external
def __init__(
stablecoin: address,
amm: address,
controller: address,
vault: address,
pool_price_oracle: address,
monetary_policy: address,
gauge: address,
admin: address):
"""
@notice Factory which creates one-way lending vaults (e.g. collateral is non-borrowable)
@param stablecoin Address of crvUSD. Only crvUSD-containing markets are allowed
@param amm Address of AMM implementation
@param controller Address of Controller implementation
@param pool_price_oracle Address of implementation for price oracle factory (prices from pools)
@param monetary_policy Address for implementation of monetary policy
@param gauge Address for gauge implementation
@param admin Admin address (DAO)
"""
STABLECOIN = stablecoin
...
▶Example▼
In  [1]:  OneWayLendingVaultFactory.STABLECOIN()
Out [1]: '0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E'

market_count​

OneWayLendingVaultFactory.():

Getter for the total market count. This value represents the total number of lending vaults created through this factory. This value is incremented by 1 whenever the internal _create function is called.

Returns: market count (uint256).

<>Source code▼
market_count: public(uint256)

@internal
def _create(
borrowed_token: address,
collateral_token: address,
A: uint256,
fee: uint256,
loan_discount: uint256,
liquidation_discount: uint256,
price_oracle: address,
name: String[64],
min_borrow_rate: uint256,
max_borrow_rate: uint256
) -> Vault:
"""
@notice Internal method for creation of the vault
"""
...
market_count: uint256 = self.market_count
self.market_count = market_count + 1
...
▶Example▼
In  [1]:  OneWayLendingVaultFactory.market_count()
Out [1]: 3

token_to_vaults​

OneWayLendingVaultFactory.token_to_vaults(arg0: address, arg1: uint256) -> address: view

Getter for the vault at index arg1 which includes coin arg0.

Returns: vault (address).

InputTypeDescription
arg0addressToken address.
arg1uint256Vault index.
<>Source code▼
token_to_vaults: public(HashMap[address, Vault[10**18]])
▶Example▼
In  [1]:  OneWayLendingVaultFactory.token_to_vaults("0xD533a949740bb3306d119CC777fa900bA034cd52", 0)
Out [1]: '0x67A18c18709C09D48000B321c6E1cb09F7181211'

In [2]: OneWayLendingVaultFactory.token_to_vaults("0xD533a949740bb3306d119CC777fa900bA034cd52", 1)
Out [2]: '0x044aC5160e5A04E09EBAE06D786fc151F2BA5ceD'

token_market_count​

OneWayLendingVaultFactory.token_market_count(arg0: address) -> uint256: view

Getter for the amount of markets coin arg0 is in.

Returns: number of markets (uint256).

InputTypeDescription
arg0addressToken address.
<>Source code▼
token_market_count: public(HashMap[address, uint256])

@internal
def _create(
borrowed_token: address,
collateral_token: address,
A: uint256,
fee: uint256,
loan_discount: uint256,
liquidation_discount: uint256,
price_oracle: address,
name: String[64],
min_borrow_rate: uint256,
max_borrow_rate: uint256
) -> Vault:
"""
@notice Internal method for creation of the vault
"""
...
token: address = borrowed_token
if borrowed_token == STABLECOIN:
token = collateral_token
market_count = self.token_market_count[token]
self.token_to_vaults[token][market_count] = vault
self.token_market_count[token] = market_count + 1
...
▶Example▼
In  [1]:  OneWayLendingVaultFactory.token_market_count("0xD533a949740bb3306d119CC777fa900bA034cd52")
Out [1]: 2

In [2]: OneWayLendingVaultFactory.token_market_count("0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E")
Out [2]: 0 # market count of crvusd will always return 0, because the token is included in every vault (market)

gauges​

OneWayLendingVaultFactory.gauges(arg0: uint256) -> address: view

Getter for the gauge of the vault at index arg0.

Returns: gauge (address).

InputTypeDescription
arg0uint256Vault index.
<>Source code▼
gauges: public(address[10**18])
▶Example▼
In  [1]:  OneWayLendingVaultFactory.gauges(0)
Out [1]: '0x3742aCa9ad8655d2d3eab5569eF1BdB4C5d52e5D'

names​

OneWayLendingVaultFactory.names(arg0: uint256) -> String[64]: view

Getter for the name of the vault at index arg0.

Returns: name (String[64]).

InputTypeDescription
arg0uint256Vault index.
<>Source code▼
names: public(HashMap[uint256, String[64]])
▶Example▼
In  [1]:  OneWayLendingVaultFactory.names(0)
Out [1]: 'wstETH-long'

In [2]: OneWayLendingVaultFactory.names(1)
Out [2]: 'CRV-long'