S Price: $0.495432 (+12.50%)

Contract

0xFAbC421e3368D158d802684A217a83c083c94CeB

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CurveRateProvider

Compiler Version
vyper:0.3.10

Optimization Enabled:
N/A

Other Settings:
default evmVersion, None license

Contract Source Code (Vyper language format)

# pragma version 0.3.10
# pragma evm-version paris
"""
@title CurveRateProvider
@custom:version 1.0.1
@author Curve.Fi
@license Copyright (c) Curve.Fi, 2020-2024 - all rights reserved
@notice Provides quotes for coin pairs, iff coin pair is in a Curve AMM that the Metaregistry recognises.
"""

version: public(constant(String[8])) = "1.0.1"

from vyper.interfaces import ERC20Detailed

MAX_COINS: constant(uint256) = 8
MAX_QUOTES: constant(uint256) = 100

struct Quote:
    source_token_index: uint256
    dest_token_index: uint256
    is_underlying: bool
    amount_out: uint256
    pool: address
    source_token_pool_balance: uint256
    dest_token_pool_balance: uint256
    pool_type: uint8  # 0 for stableswap, 1 for cryptoswap, 2 for LLAMMA.


# Interfaces

interface AddressProvider:
    def get_address(id: uint256) -> address: view

interface Metaregistry:
    def find_pools_for_coins(source_coin: address, destination_coin: address) -> DynArray[address, 1000]: view
    def get_coin_indices(_pool: address, _from: address, _to: address) -> (int128, int128, bool): view
    def get_underlying_balances(_pool: address) -> uint256[MAX_COINS]: view


ADDRESS_PROVIDER: public(immutable(AddressProvider))
METAREGISTRY_ID: constant(uint256) = 7
STABLESWAP_META_ABI: constant(String[64]) = "get_dy_underlying(int128,int128,uint256)"
STABLESWAP_ABI: constant(String[64]) = "get_dy(int128,int128,uint256)"
CRYPTOSWAP_ABI: constant(String[64]) = "get_dy(uint256,uint256,uint256)"

@external
def __init__(address_provider: address):
    ADDRESS_PROVIDER = AddressProvider(address_provider)


@external
@view
def get_quotes(source_token: address, destination_token: address, amount_in: uint256) -> DynArray[Quote, MAX_QUOTES]:
    return self._get_quotes(source_token, destination_token, amount_in)


@external
@view
def get_aggregated_rate(source_token: address, destination_token: address) -> uint256:

    amount_in: uint256 = 10**convert(ERC20Detailed(source_token).decimals(), uint256)
    quotes: DynArray[Quote, MAX_QUOTES] = self._get_quotes(source_token, destination_token, amount_in)

    return self.weighted_average_quote(
        convert(ERC20Detailed(source_token).decimals(), uint256), 
        convert(ERC20Detailed(destination_token).decimals(), uint256),
        quotes, 
    )


@internal
@pure
def weighted_average_quote(
    source_token_decimals: uint256, 
    dest_token_decimals: uint256, 
    quotes: DynArray[Quote, MAX_QUOTES]
) -> uint256:
    
    num_quotes: uint256 = len(quotes)

    # Calculate total balance with normalization
    total_balance: uint256 = 0
    for i in range(num_quotes, bound=MAX_QUOTES):
        source_balance_normalized: uint256 = quotes[i].source_token_pool_balance * 10**(18 - source_token_decimals)
        dest_balance_normalized: uint256 = quotes[i].dest_token_pool_balance * 10**(18 - dest_token_decimals)
        total_balance += source_balance_normalized + dest_balance_normalized


    # Calculate weighted sum with normalization
    weighted_avg: uint256 = 0
    for i in range(num_quotes, bound=MAX_QUOTES):
        source_balance_normalized: uint256 = quotes[i].source_token_pool_balance * 10**(18 - source_token_decimals)
        dest_balance_normalized: uint256 = quotes[i].dest_token_pool_balance * 10**(18 - dest_token_decimals)
        pool_balance_normalized: uint256 = source_balance_normalized + dest_balance_normalized
        weight: uint256 = (pool_balance_normalized * 10**18) / total_balance  # Use 18 decimal places for precision
        weighted_avg += weight * quotes[i].amount_out / 10**18

    return weighted_avg


@internal
@view
def _get_quotes(source_token: address, destination_token: address, amount_in: uint256) -> DynArray[Quote, MAX_QUOTES]:

    quotes: DynArray[Quote, MAX_QUOTES] = []
    metaregistry: Metaregistry = Metaregistry(ADDRESS_PROVIDER.get_address(METAREGISTRY_ID))
    pools: DynArray[address, 1000] = metaregistry.find_pools_for_coins(source_token, destination_token)

    if len(pools) == 0:
        return quotes

    # get pool types for each pool
    for pool in pools:

        # is it a stableswap pool? are the coin pairs part of a metapool?
        pool_type: uint8 = self._get_pool_type(pool, metaregistry)

        # get coin indices
        i: int128 = 0
        j: int128 = 0
        is_underlying: bool = False
        (i, j, is_underlying) = metaregistry.get_coin_indices(pool, source_token, destination_token)

        # get balances
        balances: uint256[MAX_COINS] = metaregistry.get_underlying_balances(pool)
        balances_i: uint256 = balances[i]
        balances_j: uint256 = balances[j]

        # skip if pool is too small or if amount_in is zero
        if 0 in [balances_i, balances_j] or amount_in == 0:
            continue

        # do a get_dy call and only save quote if call does not bork; use correct abi (in128 vs uint256)
        quote: uint256 = self._get_pool_quote(i, j, amount_in, pool, pool_type, is_underlying)

        # check if get_dy works and if so, append quote to dynarray
        if quote > 0 and len(quotes) < MAX_QUOTES:
            quotes.append(
                Quote(
                    {
                        source_token_index: convert(i, uint256),
                        dest_token_index: convert(j, uint256),
                        is_underlying: is_underlying,
                        amount_out: quote,
                        pool: pool,
                        source_token_pool_balance: balances_i,
                        dest_token_pool_balance: balances_j,
                        pool_type: pool_type
                    }
                )
            )

    return quotes


@internal
@view
def _get_pool_type(pool: address, metaregistry: Metaregistry) -> uint8:
    
    # 0 for stableswap, 1 for cryptoswap, 2 for LLAMMA.

    success: bool = False
    response: Bytes[32] = b""

    # check if cryptoswap
    success, response = raw_call(
        pool,
        method_id("allowed_extra_profit()"),
        max_outsize=32,
        revert_on_failure=False,
        is_static_call=True
    )
    if success:
        return 1

    # check if llamma
    success, response = raw_call(
        pool,
        method_id("get_rate_mul()"),
        max_outsize=32,
        revert_on_failure=False,
        is_static_call=True
    )
    if success:
        return 2

    return 0


@internal
@view
def _get_pool_quote(
    i: int128,
    j: int128, 
    amount_in: uint256, 
    pool: address, 
    pool_type: uint8, 
    is_underlying: bool
) -> uint256:

    success: bool = False
    response: Bytes[32] = b""
    method_abi: Bytes[4] = b""

    # choose the right abi:
    if pool_type == 0 and is_underlying:
        method_abi = method_id(STABLESWAP_META_ABI)
    elif pool_type == 0 and not is_underlying:
        method_abi = method_id(STABLESWAP_ABI)
    else:
        method_abi = method_id(CRYPTOSWAP_ABI)

    success, response = raw_call(
        pool,
        concat(
            method_abi,
            convert(i, bytes32),
            convert(j, bytes32),
            convert(amount_in, bytes32),
        ),
        max_outsize=32,
        revert_on_failure=False,
        is_static_call=True
    )

    if success:
        return convert(response, uint256)

    return 0

Contract Security Audit

Contract ABI

[{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"address_provider","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"get_quotes","inputs":[{"name":"source_token","type":"address"},{"name":"destination_token","type":"address"},{"name":"amount_in","type":"uint256"}],"outputs":[{"name":"","type":"tuple[]","components":[{"name":"source_token_index","type":"uint256"},{"name":"dest_token_index","type":"uint256"},{"name":"is_underlying","type":"bool"},{"name":"amount_out","type":"uint256"},{"name":"pool","type":"address"},{"name":"source_token_pool_balance","type":"uint256"},{"name":"dest_token_pool_balance","type":"uint256"},{"name":"pool_type","type":"uint8"}]}]},{"stateMutability":"view","type":"function","name":"get_aggregated_rate","inputs":[{"name":"source_token","type":"address"},{"name":"destination_token","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"ADDRESS_PROVIDER","inputs":[],"outputs":[{"name":"","type":"address"}]}]

610c4b515034610038576020610c9d6000396000518060a01c61003857604052604051610c4b52610c4b61003d61000039610c6b610000f35b600080fd60003560e01c60026003820660011b610c4501601e39600051565b6354fd4d5081186103375734610c405760208060805260056040527f312e302e3100000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f3610337565b631848effa81186100bb5734610c40576020610c4b60403960206040f35b63ebf113f0811861033757606436103417610c40576004358060a01c610c40576201dec0526024358060a01c610c40576201dee05260208062024320526201dec051610280526201dee0516102a0526044356102c05261011d6201df006105ee565b6201df00816202432001600082518083528060081b60008260648111610c4057801561017157905b8060081b60208801018160081b6020880101610100816101008460045afa505050600101818118610145575b50508201602001915050905090508101905062024320f3610337565b63ca1751fa811861033757604436103417610c40576004358060a01c610c40576201dec0526024358060a01c610c40576201dee0526201dec05163313ce5676201df205260206201df2060046201df3c845afa6101ef573d600060003e3d6000fd5b60203d10610c40576201df20518060081c610c40576201df60526201df60905051604d8111610c405780600a0a90506201df00526201dec051610280526201dee0516102a0526201df00516102c05261024a620243406105ee565b62024340805160208160081b01806201df20828560045afa5050505060206201dec05163313ce567620243405260206202434060046202435c845afa610295573d600060003e3d6000fd5b60203d10610c405762024340518060081c610c40576202438052620243809050516040526201dee05163313ce567620243a0526020620243a06004620243bc845afa6102e6573d600060003e3d6000fd5b60203d10610c4057620243a0518060081c610c4057620243e052620243e09050516060526201df205160208160081b01806080826201df2060045afa505050610331620244006109b9565b62024400f35b60006000fd5b6040366080376040515a600460e0527f49fe9e77000000000000000000000000000000000000000000000000000000006101005260e050602061014060e0516101008585fa905090506080523d602081183d602010021861012052610120805160a052602081015160c05250608051156103bb576001815250610439565b6040515a600460e0527f095a0fc6000000000000000000000000000000000000000000000000000000006101005260e050602061014060e0516101008585fa905090506080523d602081183d602010021861012052610120805160a052602081015160c0525060805115610433576002815250610439565b60008152505b565b6040366101003760006101605260c0516104575760e05161045a565b60005b6104fb5760c05161046e5760e05115610471565b60005b6104b85760046101a0527f556d6e9f000000000000000000000000000000000000000000000000000000006101c0526101a08051610160526020810151610180525061053a565b60046101a0527f5e0d443f000000000000000000000000000000000000000000000000000000006101c0526101a08051610160526020810151610180525061053a565b60046101a0527f07211ef7000000000000000000000000000000000000000000000000000000006101c0526101a0805161016052602081015161018052505b60a0515a600061016051816101c00161018051815250808201915050604051816101c00152602081019050606051816101c00152602081019050608051816101c00152602081019050806101a0526101a0505060206102606101a0516101c08585fa90509050610100523d602081183d6020100218610240526102408051610120526020810151610140525061010051156105e657610140516101205160200360031b1c8152506105ec565b60008152505b565b60006102e0526020610c4b60003960005163493f4f74616720526007616740526020616720602461673c845afa61062a573d600060003e3d6000fd5b60203d10610c4057616720518060a01c610c405761676052616760905051616700526167005163a064072b61e440526102805161e460526102a05161e48052617d4061e440604461e45c845afa610686573d600060003e3d6000fd5b60403d10610c405761e4405161e440016103e8815111610c405780516000816103e88111610c405780156106dd57905b8060051b6020850101518060a01c610c40578160051b620161c001526001018181186106b6575b505080620161a0525050620161a09050805160208160051b0180616720828560045afa505050506167205161072a576102e05160208160081b018083826102e060045afa505050506109b7565b6000616720516103e88111610c4057801561099b57905b8060051b616740015161e4405261e440516040526167005160605261076761e48061033d565b61e4805161e4605260603661e480376167005163eb85226d61e4e05261e4405161e500526102805161e520526102a05161e54052606061e4e0606461e4fc845afa6107b7573d600060003e3d6000fd5b60603d10610c405761e4e05180600f0b8118610c405761e5605261e5005180600f0b8118610c405761e5805261e520518060011c610c405761e5a05261e5609050805161e48052602081015161e4a052604081015161e4c05250616700516359f4f35161e5e05261e4405161e6005261010061e5e0602461e5fc845afa610843573d600060003e3d6000fd5b6101003d10610c405761e5e0905061010061e4e06101008360045afa505061e4805160078111610c405760051b61e4e0015161e5e05261e4a05160078111610c405760051b61e4e0015161e6005261e5e0516108a05760016108a6565b61e60051155b6108b4576102c051156108b7565b60015b156108c157610990565b61e4805160405261e4a0516060526102c05160805261e4405160a05261e4605160c05261e4c05160e0526108f661e64061043b565b61e6405161e6205261e62051156109145760636102e0511115610917565b60005b15610990576102e05160638111610c40578060081b6103000161e4805160008112610c4057815261e4a05160008112610c4057602082015261e4c051604082015261e62051606082015261e44051608082015261e5e05160a082015261e6005160c082015261e4605160e082015250600181016102e052505b600101818118610741575b50506102e05160208160081b018083826102e060045afa505050505b565b6080516164a05260006164c05260006164a05160648111610c40578015610abc57905b806164e0526164e051608051811015610c405760081b60a00160a081019050516040518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c405790509050616500526164e051608051811015610c405760081b60a00160c081019050516060518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c405790509050616520526164c0516165005161652051808201828110610c405790509050808201828110610c4057905090506164c0526001018181186109dc575b505060006164e05260006164a05160648111610c40578015610c3557905b806165005261650051608051811015610c405760081b60a00160a081019050516040518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c4057905090506165205261650051608051811015610c405760081b60a00160c081019050516060518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c405790509050616540526165205161654051808201828110610c4057905090506165605261656051670de0b6b3a7640000810281670de0b6b3a7640000820418610c405790506164c0518015610c405780820490509050616580526164e0516165805161650051608051811015610c405760081b60a00160608101905051808202811583838304141715610c405790509050670de0b6b3a764000081049050808201828110610c4057905090506164e052600101818118610ada575b50506164e051815250565b600080fd009d018d001a84190c4b81061820a16576797065728300030a001500000000000000000000000087fe17697d0f14a222e8bef386a0860ecffdd617

Deployed Bytecode

0x60003560e01c60026003820660011b610c4501601e39600051565b6354fd4d5081186103375734610c405760208060805260056040527f312e302e3100000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f3610337565b631848effa81186100bb5734610c40576020610c4b60403960206040f35b63ebf113f0811861033757606436103417610c40576004358060a01c610c40576201dec0526024358060a01c610c40576201dee05260208062024320526201dec051610280526201dee0516102a0526044356102c05261011d6201df006105ee565b6201df00816202432001600082518083528060081b60008260648111610c4057801561017157905b8060081b60208801018160081b6020880101610100816101008460045afa505050600101818118610145575b50508201602001915050905090508101905062024320f3610337565b63ca1751fa811861033757604436103417610c40576004358060a01c610c40576201dec0526024358060a01c610c40576201dee0526201dec05163313ce5676201df205260206201df2060046201df3c845afa6101ef573d600060003e3d6000fd5b60203d10610c40576201df20518060081c610c40576201df60526201df60905051604d8111610c405780600a0a90506201df00526201dec051610280526201dee0516102a0526201df00516102c05261024a620243406105ee565b62024340805160208160081b01806201df20828560045afa5050505060206201dec05163313ce567620243405260206202434060046202435c845afa610295573d600060003e3d6000fd5b60203d10610c405762024340518060081c610c40576202438052620243809050516040526201dee05163313ce567620243a0526020620243a06004620243bc845afa6102e6573d600060003e3d6000fd5b60203d10610c4057620243a0518060081c610c4057620243e052620243e09050516060526201df205160208160081b01806080826201df2060045afa505050610331620244006109b9565b62024400f35b60006000fd5b6040366080376040515a600460e0527f49fe9e77000000000000000000000000000000000000000000000000000000006101005260e050602061014060e0516101008585fa905090506080523d602081183d602010021861012052610120805160a052602081015160c05250608051156103bb576001815250610439565b6040515a600460e0527f095a0fc6000000000000000000000000000000000000000000000000000000006101005260e050602061014060e0516101008585fa905090506080523d602081183d602010021861012052610120805160a052602081015160c0525060805115610433576002815250610439565b60008152505b565b6040366101003760006101605260c0516104575760e05161045a565b60005b6104fb5760c05161046e5760e05115610471565b60005b6104b85760046101a0527f556d6e9f000000000000000000000000000000000000000000000000000000006101c0526101a08051610160526020810151610180525061053a565b60046101a0527f5e0d443f000000000000000000000000000000000000000000000000000000006101c0526101a08051610160526020810151610180525061053a565b60046101a0527f07211ef7000000000000000000000000000000000000000000000000000000006101c0526101a0805161016052602081015161018052505b60a0515a600061016051816101c00161018051815250808201915050604051816101c00152602081019050606051816101c00152602081019050608051816101c00152602081019050806101a0526101a0505060206102606101a0516101c08585fa90509050610100523d602081183d6020100218610240526102408051610120526020810151610140525061010051156105e657610140516101205160200360031b1c8152506105ec565b60008152505b565b60006102e0526020610c4b60003960005163493f4f74616720526007616740526020616720602461673c845afa61062a573d600060003e3d6000fd5b60203d10610c4057616720518060a01c610c405761676052616760905051616700526167005163a064072b61e440526102805161e460526102a05161e48052617d4061e440604461e45c845afa610686573d600060003e3d6000fd5b60403d10610c405761e4405161e440016103e8815111610c405780516000816103e88111610c405780156106dd57905b8060051b6020850101518060a01c610c40578160051b620161c001526001018181186106b6575b505080620161a0525050620161a09050805160208160051b0180616720828560045afa505050506167205161072a576102e05160208160081b018083826102e060045afa505050506109b7565b6000616720516103e88111610c4057801561099b57905b8060051b616740015161e4405261e440516040526167005160605261076761e48061033d565b61e4805161e4605260603661e480376167005163eb85226d61e4e05261e4405161e500526102805161e520526102a05161e54052606061e4e0606461e4fc845afa6107b7573d600060003e3d6000fd5b60603d10610c405761e4e05180600f0b8118610c405761e5605261e5005180600f0b8118610c405761e5805261e520518060011c610c405761e5a05261e5609050805161e48052602081015161e4a052604081015161e4c05250616700516359f4f35161e5e05261e4405161e6005261010061e5e0602461e5fc845afa610843573d600060003e3d6000fd5b6101003d10610c405761e5e0905061010061e4e06101008360045afa505061e4805160078111610c405760051b61e4e0015161e5e05261e4a05160078111610c405760051b61e4e0015161e6005261e5e0516108a05760016108a6565b61e60051155b6108b4576102c051156108b7565b60015b156108c157610990565b61e4805160405261e4a0516060526102c05160805261e4405160a05261e4605160c05261e4c05160e0526108f661e64061043b565b61e6405161e6205261e62051156109145760636102e0511115610917565b60005b15610990576102e05160638111610c40578060081b6103000161e4805160008112610c4057815261e4a05160008112610c4057602082015261e4c051604082015261e62051606082015261e44051608082015261e5e05160a082015261e6005160c082015261e4605160e082015250600181016102e052505b600101818118610741575b50506102e05160208160081b018083826102e060045afa505050505b565b6080516164a05260006164c05260006164a05160648111610c40578015610abc57905b806164e0526164e051608051811015610c405760081b60a00160a081019050516040518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c405790509050616500526164e051608051811015610c405760081b60a00160c081019050516060518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c405790509050616520526164c0516165005161652051808201828110610c405790509050808201828110610c4057905090506164c0526001018181186109dc575b505060006164e05260006164a05160648111610c40578015610c3557905b806165005261650051608051811015610c405760081b60a00160a081019050516040518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c4057905090506165205261650051608051811015610c405760081b60a00160c081019050516060518060120360128111610c40579050604d8111610c405780600a0a9050808202811583838304141715610c405790509050616540526165205161654051808201828110610c4057905090506165605261656051670de0b6b3a7640000810281670de0b6b3a7640000820418610c405790506164c0518015610c405780820490509050616580526164e0516165805161650051608051811015610c405760081b60a00160608101905051808202811583838304141715610c405790509050670de0b6b3a764000081049050808201828110610c4057905090506164e052600101818118610ada575b50506164e051815250565b600080fd009d018d001a00000000000000000000000087fe17697d0f14a222e8bef386a0860ecffdd617

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000087fe17697d0f14a222e8bef386a0860ecffdd617

-----Decoded View---------------
Arg [0] : address_provider (address): 0x87FE17697D0f14A222e8bEf386a0860eCffDD617

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000087fe17697d0f14a222e8bef386a0860ecffdd617


Block Transaction 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

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.