LP Token Methods
LP Token and liquidity pool share the same smart contract.
Contract Source
Source code available on Github.
Info Methods¶
name¶
 LPToken.name() -> String[64]: view
Getter for the name of the LP token.
Returns: name (String[64]).
Source code
name: public(immutable(String[64]))
@external
def __init__(
    _name: String[64],
    _symbol: String[32],
    _coins: address[N_COINS],
    _math: address,
    _weth: address,
    _salt: bytes32,
    packed_precisions: uint256,
    packed_A_gamma: uint256,
    packed_fee_params: uint256,
    packed_rebalancing_params: uint256,
    packed_prices: uint256,
):
    WETH20 = _weth
    MATH = Math(_math)
    self.factory = msg.sender
    name = _name
    symbol = _symbol
    coins = _coins
    self.packed_precisions = packed_precisions  # <------- Precisions of coins
    #                            are calculated as 10**(18 - coin.decimals()).
    self.initial_A_gamma = packed_A_gamma  # <------------------- A and gamma.
    self.future_A_gamma = packed_A_gamma
    self.packed_rebalancing_params = packed_rebalancing_params  # <-- Contains
    #               rebalancing params: allowed_extra_profit, adjustment_step,
    #                                                         and ma_exp_time.
    self.packed_fee_params = packed_fee_params  # <-------------- Contains Fee
    #                                  params: mid_fee, out_fee and fee_gamma.
    self.price_scale_packed = packed_prices
    self.price_oracle_packed = packed_prices
    self.last_prices_packed = packed_prices
    self.last_prices_timestamp = block.timestamp
    self.xcp_profit_a = 10**18
    #         Cache DOMAIN_SEPARATOR. If chain.id is not CACHED_CHAIN_ID, then
    #     DOMAIN_SEPARATOR will be re-calculated each time `permit` is called.
    #                   Otherwise, it will always use CACHED_DOMAIN_SEPARATOR.
    #                       see: `_domain_separator()` for its implementation.
    NAME_HASH = keccak256(name)
    salt = _salt
    CACHED_CHAIN_ID = chain.id
    CACHED_DOMAIN_SEPARATOR = keccak256(
        _abi_encode(
            EIP712_TYPEHASH,
            NAME_HASH,
            VERSION_HASH,
            chain.id,
            self,
            salt,
        )
    )
    log Transfer(empty(address), self, 0)  # <------- Fire empty transfer from
    #                                       0x0 to self for indexers to catch.
symbol¶
 LPToken.symbol() -> String[32]: view
Getter for the symbol of the LP token.
Returns: symbol (String[32]).
Source code
symbol: public(immutable(String[32]))
@external
def __init__(
    _name: String[64],
    _symbol: String[32],
    _coins: address[N_COINS],
    _math: address,
    _weth: address,
    _salt: bytes32,
    packed_precisions: uint256,
    packed_A_gamma: uint256,
    packed_fee_params: uint256,
    packed_rebalancing_params: uint256,
    packed_prices: uint256,
):
    WETH20 = _weth
    MATH = Math(_math)
    self.factory = msg.sender
    name = _name
    symbol = _symbol
    coins = _coins
    self.packed_precisions = packed_precisions  # <------- Precisions of coins
    #                            are calculated as 10**(18 - coin.decimals()).
    self.initial_A_gamma = packed_A_gamma  # <------------------- A and gamma.
    self.future_A_gamma = packed_A_gamma
    self.packed_rebalancing_params = packed_rebalancing_params  # <-- Contains
    #               rebalancing params: allowed_extra_profit, adjustment_step,
    #                                                         and ma_exp_time.
    self.packed_fee_params = packed_fee_params  # <-------------- Contains Fee
    #                                  params: mid_fee, out_fee and fee_gamma.
    self.price_scale_packed = packed_prices
    self.price_oracle_packed = packed_prices
    self.last_prices_packed = packed_prices
    self.last_prices_timestamp = block.timestamp
    self.xcp_profit_a = 10**18
    #         Cache DOMAIN_SEPARATOR. If chain.id is not CACHED_CHAIN_ID, then
    #     DOMAIN_SEPARATOR will be re-calculated each time `permit` is called.
    #                   Otherwise, it will always use CACHED_DOMAIN_SEPARATOR.
    #                       see: `_domain_separator()` for its implementation.
    NAME_HASH = keccak256(name)
    salt = _salt
    CACHED_CHAIN_ID = chain.id
    CACHED_DOMAIN_SEPARATOR = keccak256(
        _abi_encode(
            EIP712_TYPEHASH,
            NAME_HASH,
            VERSION_HASH,
            chain.id,
            self,
            salt,
        )
    )
    log Transfer(empty(address), self, 0)  # <------- Fire empty transfer from
    #                                       0x0 to self for indexers to catch.
decimals¶
 LPToken.name() -> uint8: view
Getter for the decimals of the LP token.
Returns: decimals (uint8).
Note
decimals is a constant variable which is set to 18.
version¶
 LPToken.version() -> String[8]: view
Getter for the version of the LP token.
Returns: version (String[8]).
| Input | Type | Description | 
|---|---|---|
input |  type |  Contract input | 
balanceOf¶
 LPToken.balanceOf(arg0: address) -> uint256: view
Getter for the LP token balance of an address.
Returns: token balance (uint256).
| Input | Type | Description | 
|---|---|---|
arg0 |  address |  Address to get the balance of | 
totalSupply¶
 LPToken.totalSupply() -> uint256: view
Getter for the total supply of the LP token.
Returns: total supply (uint256).
Allowance and Transfer Methods¶
transfer¶
 LPToken.transfer(_to: address, _value: uin256) -> bool:
Function to transfer _value token from msg.sender to _to.
Returns: True (bool).
Emits: Transfer
| Input | Type | Description | 
|---|---|---|
_to |  address |  Address to transfer to | 
_value |  uint256 |  Amount to transfer | 
Source code
event Transfer:
    sender: indexed(address)
    receiver: indexed(address)
    value: uint256
@external
def transfer(_to: address, _value: uint256) -> bool:
    """
    @dev Transfer token for a specified address
    @param _to The address to transfer to.
    @param _value The amount to be transferred.
    @return bool True on successful transfer. Reverts otherwise.
    """
    self._transfer(msg.sender, _to, _value)
    return True
@internal
def _transfer(_from: address, _to: address, _value: uint256):
    assert _to not in [self, empty(address)]
    self.balanceOf[_from] -= _value
    self.balanceOf[_to] += _value
    log Transfer(_from, _to, _value)
transferFrom¶
 LPToken.transferFrom(_from: address, _to: address, _value: uint256) -> bool:
Function to transfer _value token from msg.sender to _to. Needs allowance to successfully transfer on behalf of someone else.
Returns: True (bool).
Emits: Transfer
| Input | Type | Description | 
|---|---|---|
_from |  address |  Address to transfer from | 
_to |  address |  Address to transfer to | 
_value |  uint256 |  Amount of tokens to transfer | 
Source code
event Transfer:
    sender: indexed(address)
    receiver: indexed(address)
    value: uint256
@external
def transferFrom(_from: address, _to: address, _value: uint256) -> bool:
    """
    @dev Transfer tokens from one address to another.
    @param _from address The address which you want to send tokens from
    @param _to address The address which you want to transfer to
    @param _value uint256 the amount of tokens to be transferred
    @return bool True on successul transfer. Reverts otherwise.
    """
    _allowance: uint256 = self.allowance[_from][msg.sender]
    if _allowance != max_value(uint256):
        self._approve(_from, msg.sender, _allowance - _value)
    self._transfer(_from, _to, _value)
    return True
@internal
def _transfer(_from: address, _to: address, _value: uint256):
    assert _to not in [self, empty(address)]
    self.balanceOf[_from] -= _value
    self.balanceOf[_to] += _value
    log Transfer(_from, _to, _value)
approve¶
 LPToken.approve(_spender: address, _value: uint256) -> bool:
Function to approve _to to transfer _value on behalf of msg.sender.
Returns: True (bool).
| Input | Type | Description | 
|---|---|---|
_spender |  address |  Address approved to spend funds | 
_value |  uint256 |  Amount of tokens allowed to spend | 
Source code
event Approval:
    owner: indexed(address)
    spender: indexed(address)
    value: uint256
@external
def approve(_spender: address, _value: uint256) -> bool:
    """
    @notice Allow `_spender` to transfer up to `_value` amount
            of tokens from the caller's account.
    @dev Non-zero to non-zero approvals are allowed, but should
        be used cautiously. The methods increaseAllowance + decreaseAllowance
        are available to prevent any front-running that may occur.
    @param _spender The account permitted to spend up to `_value` amount of
                    caller's funds.
    @param _value The amount of tokens `_spender` is allowed to spend.
    @return bool Success
    """
    self._approve(msg.sender, _spender, _value)
    return True
@internal
def _approve(_owner: address, _spender: address, _value: uint256):
    self.allowance[_owner][_spender] = _value
    log Approval(_owner, _spender, _value)
allowance¶
 LPToken.allowance(arg0: address, arg1: address) -> uint256: view
Getter method to check the allowance of arg0 for funds of arg1.
Returns: allowed amount (uint256).
| Input | Type | Description | 
|---|---|---|
arg0 |  address |  Address of the spender | 
arg1 |  address |  Address to the token owner | 
increaseAllowance¶
 LPToken.increaseAllowance(_spender: address, _add_value: uint256) -> bool:
Function to increase the allowance granted to _spender.
Returns: True (bool).
Emits: Approval
| Input | Type | Description | 
|---|---|---|
_spender |  address |  Address to increase the allowance of | 
_add_value |  uint256 |  Amount ot increase the allowance by | 
Source code
event Approval:
    owner: indexed(address)
    spender: indexed(address)
    value: uint256
allowance: public(HashMap[address, HashMap[address, uint256]])
@external
def increaseAllowance(_spender: address, _add_value: uint256) -> bool:
    """
    @notice Increase the allowance granted to `_spender`.
    @dev This function will never overflow, and instead will bound
        allowance to max_value(uint256). This has the potential to grant an
        infinite approval.
    @param _spender The account to increase the allowance of.
    @param _add_value The amount to increase the allowance by.
    @return bool Success
    """
    cached_allowance: uint256 = self.allowance[msg.sender][_spender]
    allowance: uint256 = unsafe_add(cached_allowance, _add_value)
    if allowance < cached_allowance:  # <-------------- Check for an overflow.
        allowance = max_value(uint256)
    if allowance != cached_allowance:
        self._approve(msg.sender, _spender, allowance)
    return True    
@internal
def _approve(_owner: address, _spender: address, _value: uint256):
    self.allowance[_owner][_spender] = _value
    log Approval(_owner, _spender, _value)
decreaseAllowance¶
 LPToken.decreaseAllowance(_spender: address, _sub_value: uint256) -> bool
Function to decrease the allowance granted to _spender.
Returns: True (bool).
Emits: Approval
| Input | Type | Description | 
|---|---|---|
_spender |  address |  Address to decrease the allowance of | 
_sub_value |  uint256 |  Amount ot decrease the allowance by | 
Source code
event Approval:
    owner: indexed(address)
    spender: indexed(address)
    value: uint256
allowance: public(HashMap[address, HashMap[address, uint256]])
@external
def decreaseAllowance(_spender: address, _sub_value: uint256) -> bool:
    """
    @notice Decrease the allowance granted to `_spender`.
    @dev This function will never underflow, and instead will bound
        allowance to 0.
    @param _spender The account to decrease the allowance of.
    @param _sub_value The amount to decrease the allowance by.
    @return bool Success.
    """
    cached_allowance: uint256 = self.allowance[msg.sender][_spender]
    allowance: uint256 = unsafe_sub(cached_allowance, _sub_value)
    if cached_allowance < allowance:  # <------------- Check for an underflow.
        allowance = 0
    if allowance != cached_allowance:
        self._approve(msg.sender, _spender, allowance)
    return True    
@internal
def _approve(_owner: address, _spender: address, _value: uint256):
    self.allowance[_owner][_spender] = _value
    log Approval(_owner, _spender, _value)
permit¶
 LPToken.permit( _owner: address, _spender: address, _value: uint256, _deadline: uint256, _v: uint8, _r: bytes32, _s: bytes32) -> bool:
Function to permit spender to spend up to _value amount of _owner's tokens via a signature.
Returns: True (bool).
| Input | Type | Description | 
|---|---|---|
_owner |  address |  Account which generated the signature and is granting an allowance | 
_spender |  address |  Account which will be granted an allowance | 
_value |  uint256 |  Amount to approve | 
_deadline |  uint256 |  Deadline by which signature must be submitted | 
_v |  uint8 |  The last byte of the ECDSA signature | 
_r |  bytes32 |  The first 32 bytes of the ECDSA signature | 
_s |  bytes32 |  The second 32 bytes of the ECDSA signature | 
Source code
event Approval:
    owner: indexed(address)
    spender: indexed(address)
    value: uint256
@external
def permit(
    _owner: address,
    _spender: address,
    _value: uint256,
    _deadline: uint256,
    _v: uint8,
    _r: bytes32,
    _s: bytes32,
) -> bool:
    """
    @notice Permit `_spender` to spend up to `_value` amount of `_owner`'s
            tokens via a signature.
    @dev In the event of a chain fork, replay attacks are prevented as
        domain separator is recalculated. However, this is only if the
        resulting chains update their chainId.
    @param _owner The account which generated the signature and is granting an
                allowance.
    @param _spender The account which will be granted an allowance.
    @param _value The approval amount.
    @param _deadline The deadline by which the signature must be submitted.
    @param _v The last byte of the ECDSA signature.
    @param _r The first 32 bytes of the ECDSA signature.
    @param _s The second 32 bytes of the ECDSA signature.
    @return bool Success.
    """
    assert _owner != empty(address)  # dev: invalid owner
    assert block.timestamp <= _deadline  # dev: permit expired
    nonce: uint256 = self.nonces[_owner]
    digest: bytes32 = keccak256(
        concat(
            b"\x19\x01",
            self._domain_separator(),
            keccak256(
                _abi_encode(
                    EIP2612_TYPEHASH, _owner, _spender, _value, nonce, _deadline
                )
            ),
        )
    )
    assert ecrecover(digest, _v, _r, _s) == _owner  # dev: invalid signature
    self.nonces[_owner] = unsafe_add(nonce, 1)  # <-- Unsafe add is safe here.
    self._approve(_owner, _spender, _value)
    return True  
@internal
def _approve(_owner: address, _spender: address, _value: uint256):
    self.allowance[_owner][_spender] = _value
    log Approval(_owner, _spender, _value)