ETH Price: $3,084.90 (-2.74%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
209251722024-10-09 2:53:59112 days ago1728442439  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xfd8eF798...60ea33726
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
SemiLog monetary policy

Compiler Version
vyper:0.3.10

Optimization Enabled:
N/A

Other Settings:
default evmVersion, None license

Contract Source Code (Vyper language format)

# @version 0.3.10
"""
@title SemiLog monetary policy
@notice Monetary policy to calculate borrow rates in lending markets depending on utilization.
        Unlike "core" policies, it does not depend on crvUSD price.
        Calculated as:
        log(rate) = utilization * (log(rate_max) - log(rate_min)) + log(rate_min)
        e.g.
        rate = rate_min * (rate_max / rate_min)**utilization
@author Curve.fi
@license Copyright (c) Curve.Fi, 2020-2024 - all rights reserved
"""
from vyper.interfaces import ERC20


interface Controller:
    def total_debt() -> uint256: view

interface Factory:
    def admin() -> address: view


event SetRates:
    min_rate: uint256
    max_rate: uint256


MAX_EXP: constant(uint256) = 1000 * 10**18
MIN_RATE: public(constant(uint256)) = 10**15 / (365 * 86400)  # 0.1%
MAX_RATE: public(constant(uint256)) = 10**19 / (365 * 86400)  # 1000%

BORROWED_TOKEN: public(immutable(ERC20))
FACTORY: public(immutable(Factory))

min_rate: public(uint256)
max_rate: public(uint256)
log_min_rate: public(int256)
log_max_rate: public(int256)


@external
def __init__(borrowed_token: ERC20, min_rate: uint256, max_rate: uint256):
    assert min_rate >= MIN_RATE and max_rate <= MAX_RATE and min_rate <= max_rate, "Wrong rates"

    BORROWED_TOKEN = borrowed_token
    self.min_rate = min_rate
    self.max_rate = max_rate
    self.log_min_rate = self.ln_int(min_rate)
    self.log_max_rate = self.ln_int(max_rate)

    FACTORY = Factory(msg.sender)


### MATH ###
@internal
@pure
def exp(power: int256) -> uint256:
    if power <= -41446531673892821376:
        return 0

    if power >= 135305999368893231589:
        # Return MAX_EXP when we are in overflow mode
        return MAX_EXP

    x: int256 = unsafe_div(unsafe_mul(power, 2**96), 10**18)

    k: int256 = unsafe_div(
        unsafe_add(
            unsafe_div(unsafe_mul(x, 2**96), 54916777467707473351141471128),
            2**95),
        2**96)
    x = unsafe_sub(x, unsafe_mul(k, 54916777467707473351141471128))

    y: int256 = unsafe_add(x, 1346386616545796478920950773328)
    y = unsafe_add(unsafe_div(unsafe_mul(y, x), 2**96), 57155421227552351082224309758442)
    p: int256 = unsafe_sub(unsafe_add(y, x), 94201549194550492254356042504812)
    p = unsafe_add(unsafe_div(unsafe_mul(p, y), 2**96), 28719021644029726153956944680412240)
    p = unsafe_add(unsafe_mul(p, x), (4385272521454847904659076985693276 * 2**96))

    q: int256 = x - 2855989394907223263936484059900
    q = unsafe_add(unsafe_div(unsafe_mul(q, x), 2**96), 50020603652535783019961831881945)
    q = unsafe_sub(unsafe_div(unsafe_mul(q, x), 2**96), 533845033583426703283633433725380)
    q = unsafe_add(unsafe_div(unsafe_mul(q, x), 2**96), 3604857256930695427073651918091429)
    q = unsafe_sub(unsafe_div(unsafe_mul(q, x), 2**96), 14423608567350463180887372962807573)
    q = unsafe_add(unsafe_div(unsafe_mul(q, x), 2**96), 26449188498355588339934803723976023)

    return shift(
        unsafe_mul(convert(unsafe_div(p, q), uint256), 3822833074963236453042738258902158003155416615667),
        unsafe_sub(k, 195))


@internal
@pure
def ln_int(_x: uint256) -> int256:
    """
    @notice Logarithm ln() function based on log2. Not very gas-efficient but brief
    """
    # adapted from: https://medium.com/coinmonks/9aef8515136e
    # and vyper log implementation
    # This can be much more optimal but that's not important here
    x: uint256 = _x
    if _x < 10**18:
        x = 10**36 / _x
    res: uint256 = 0
    for i in range(8):
        t: uint256 = 2**(7 - i)
        p: uint256 = 2**t
        if x >= p * 10**18:
            x /= p
            res += t * 10**18
    d: uint256 = 10**18
    for i in range(59):  # 18 decimals: math.log2(10**18) == 59.7
        if (x >= 2 * 10**18):
            res += d
            x /= 2
        x = x * x / 10**18
        d /= 2
    # Now res = log2(x)
    # ln(x) = log2(x) / log2(e)
    result: int256 = convert(res * 10**18 / 1442695040888963328, int256)
    if _x >= 10**18:
        return result
    else:
        return -result
### END MATH ###


@internal
@view
def calculate_rate(_for: address, d_reserves: int256, d_debt: int256) -> uint256:
    total_debt: int256 = convert(Controller(_for).total_debt(), int256)
    total_reserves: int256 = convert(BORROWED_TOKEN.balanceOf(_for), int256) + total_debt + d_reserves
    total_debt += d_debt
    assert total_debt >= 0, "Negative debt"
    assert total_reserves >= total_debt, "Reserves too small"
    if total_debt == 0:
        return self.min_rate
    else:
        log_min_rate: int256 = self.log_min_rate
        log_max_rate: int256 = self.log_max_rate
        return self.exp(total_debt * (log_max_rate - log_min_rate) / total_reserves + log_min_rate)


@view
@external
def rate(_for: address = msg.sender) -> uint256:
    return self.calculate_rate(_for, 0, 0)


@external
def rate_write(_for: address = msg.sender) -> uint256:
    return self.calculate_rate(_for, 0, 0)


@external
def set_rates(min_rate: uint256, max_rate: uint256):
    assert msg.sender == FACTORY.admin()

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

    if min_rate != self.min_rate:
        self.log_min_rate = self.ln_int(min_rate)
    if max_rate != self.max_rate:
        self.log_max_rate = self.ln_int(max_rate)
    self.min_rate = min_rate
    self.max_rate = max_rate

    log SetRates(min_rate, max_rate)


@view
@external
def future_rate(_for: address, d_reserves: int256, d_debt: int256) -> uint256:
    return self.calculate_rate(_for, d_reserves, d_debt)

Contract Security Audit

Contract ABI

[{"name":"SetRates","inputs":[{"name":"min_rate","type":"uint256","indexed":false},{"name":"max_rate","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"borrowed_token","type":"address"},{"name":"min_rate","type":"uint256"},{"name":"max_rate","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"rate","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"rate","inputs":[{"name":"_for","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"rate_write","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"rate_write","inputs":[{"name":"_for","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"set_rates","inputs":[{"name":"min_rate","type":"uint256"},{"name":"max_rate","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"future_rate","inputs":[{"name":"_for","type":"address"},{"name":"d_reserves","type":"int256"},{"name":"d_debt","type":"int256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"MIN_RATE","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"MAX_RATE","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"BORROWED_TOKEN","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"FACTORY","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"min_rate","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"max_rate","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"log_min_rate","inputs":[],"outputs":[{"name":"","type":"int256"}]},{"stateMutability":"view","type":"function","name":"log_max_rate","inputs":[],"outputs":[{"name":"","type":"int256"}]}]

Deployed Bytecode

0x5f3560e01c6002600b820660011b610a7701601e395f51565b63d819bfef81186100365734610a73576301e3da5f60405260206040f35b632dd31000811460033611161561005a5734610a73576020610aad60403960206040f35b63bdb09f2e811861033557602436103417610a73576004358060a01c610a7357610200525b602061020051610100526040366101203761009b610220610803565b610220f3610335565b63c24dbebd81186103355734610a73576449d482455d60405260206040f3610335565b6382f75cee81186100e55734610a73576020610a8d60403960206040f35b63ecc92c1881186103355734610a735760025460405260206040f3610335565b635d78640181186101205734610a73575f5460405260206040f35b63536e4ec481186103355734610a735760015460405260206040f3610335565b638f24c6b6811861015c5734610a735760035460405260206040f35b63e91f2f4c81186101765734610a7357336102005261007f565b63532da88b811861033557604436103417610a73576020610aad5f395f5163f851a440610100526020610100600461011c845afa6101b6573d5f5f3e3d5ffd5b60203d10610a7357610100518060a01c610a7357610140526101409050513318610a735760043560243510610a73576301e3da5f60043510610a73576449d482455d60243511610a73575f54600435146102235760043560405261021b610100610339565b610100516002555b600154602435146102475760243560405261023f610100610339565b610100516003555b6004355f556024356001557f43abda41e7975fc65795be1b59318ab34e5bfc3072a1dff0904fbb0a13dd9b5c60406004610100376040610100a100610335565b632c4e722e81186103355734610a735733610200526102ca56610335565b630ba9d8ca811861033557602436103417610a73576004358060a01c610a7357610200525b60206102005161010052604036610120376102e6610220610803565b610220f3610335565b639f3118d9811861033557606436103417610a73576004358060a01c610a735761020052602061020051610100526040602461012037610330610220610803565b610220f35b5f5ffd5b604051606052670de0b6b3a763ffff60405111610371576040518015610a7357806ec097ce7bc90715b34b9f10000000000490506060525b5f6080525f6008905b8060a05260a0518060070360078111610a7357905060ff8111610a73578060020a905060c05260c05160ff8111610a73578060020a905060e05260e051670de0b6b3a7640000810281670de0b6b3a7640000820418610a73579050606051106104295760605160e0518015610a73578082049050905060605260805160c051670de0b6b3a7640000810281670de0b6b3a7640000820418610a73579050808201828110610a7357905090506080525b60010181811861037a575050670de0b6b3a764000060a0525f603b905b8060c052671bc16d674ec800006060511061047f5760805160a051808201828110610a7357905090506080526060518060011c90506060525b606051606051808202811583838304141715610a735790509050670de0b6b3a76400008104905060605260a0518060011c905060a052600101818118610446575050608051670de0b6b3a7640000810281670de0b6b3a7640000820418610a735790506714057b7ef7678100810490508060ff1c610a735760c052670de0b6b3a764000060405110156105445760c0517f80000000000000000000000000000000000000000000000000000000000000008114610a73575f0381525061054b5661054b565b60c0518152505b565b7ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a466806040511361057f575f815250610801565b680755bf798b4a1bf1e5604051126105a357683635c9adc5dea00000815250610801565b670de0b6b3a764000060405160601b056060526c010000000000000000000000006b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b0501056080526bb17217f7d1cf79abc9e3b39860805102606051036060526c10fe68e7fd37d0007b713f76506060510160a0526d02d16720577bd19bf614176fe9ea6c0100000000000000000000000060605160a05102050160a0526d04a4fd9f2a8b96949216d2255a6c60605160a051010360c0526e0587f503bb6ea29d25fcb7401964506c0100000000000000000000000060a05160c05102050160c05279d835ebba824c98fb31b83b2ca45c00000000000000000000000060605160c051020160c0526060516c240c330e9fb2d9cbaf0fd5aafc8103818113610a7357905060e0526d0277594991cfc85f6e2461837cd96c0100000000000000000000000060605160e05102050160e0526d1a521255e34f6a5061b25ef1c9c46c0100000000000000000000000060605160e05102050360e0526db1bbb201f443cf962f1a1d3db4a56c0100000000000000000000000060605160e05102050160e0526e02c72388d9f74f51a9331fed693f156c0100000000000000000000000060605160e05102050360e0526e05180bb14799ab47a8a8cb2a527d576c0100000000000000000000000060605160e05102050160e05274029d9dc38563c32e5c2f6dc192ee70ef65f9978af360e05160c051055f8112610a73570260c3608051037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156107f35781811b6107f9565b81815f031c5b905090508152505b565b610100516331dc3ca8610180526020610180600461019c845afa610829573d5f5f3e3d5ffd5b60203d10610a73576101809050518060ff1c610a7357610160526020610a8d5f395f516370a082316101a052610100516101c05260206101a060246101bc845afa610876573d5f5f3e3d5ffd5b60203d10610a73576101a09050518060ff1c610a7357610160518082018281125f831218610a735790509050610120518082018281125f831218610a7357905090506101805261016051610140518082018281125f831218610a735790509050610160525f61016051121561094a57600d6101a0527f4e656761746976652064656274000000000000000000000000000000000000006101c0526101a0506101a051806101c001601f825f031636823750506308c379a061016052602061018052601f19601f6101a051011660440161017cfd5b610160516101805112156109bd5760126101a0527f526573657276657320746f6f20736d616c6c00000000000000000000000000006101c0526101a0506101a051806101c001601f825f031636823750506308c379a061016052602061018052601f19601f6101a051011660440161017cfd5b610160516109d3575f54815250610a7156610a71565b6002546101a0526003546101c052610160516101c0516101a0518082038281135f831218610a73579050905080820281191515600160ff1b8414151782158484840514171615610a735790509050610180518015610a7357808205600160ff1b8314155f198314151715610a7357905090506101a0518082018281125f831218610a735790509050604052610a696101e061054d565b6101e0518152505b565b5f80fd0140028700a403350335001802a502ef0335010500c7000000000000000000000000f939e0a03fb07f59a73314e73794be0e57ac1b4e000000000000000000000000ea6876dde9e3467564acbee1ed5bac88783205e0

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.