Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: cantina-118 #1

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/adapter/BaseAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import {Errors} from "src/lib/Errors.sol";
/// @author Euler Labs (https://www.eulerlabs.com/)
/// @notice Abstract adapter with virtual bid/ask pricing.
abstract contract BaseAdapter is IPriceOracle {
// @dev Addresses <= 0x00..00ffffffff are considered to have 18 decimals without dispatching a call.
// This avoids collisions between ISO 4217 representations and (future) precompiles.
uint256 internal constant ADDRESS_RESERVED_RANGE = 0xffffffff;

/// @inheritdoc IPriceOracle
function getQuote(uint256 inAmount, address base, address quote) external view returns (uint256) {
return _getQuote(inAmount, base, quote);
Expand All @@ -22,14 +26,16 @@ abstract contract BaseAdapter is IPriceOracle {
return (outAmount, outAmount);
}

/// @notice Call `decimals()`, falling back to 18 decimals.
/// @notice Determine the decimals of an asset.
/// @param asset ERC20 token address or other asset.
/// @dev Oracles can use ERC-7535, ISO 4217 or other conventions to represent non-ERC20 assets as addresses.
/// Integrator Note: `_getDecimals` will return 18 if `asset` is:
/// - any address <= 0x00000000000000000000000000000000ffffffff (4294967295)
/// - an EOA or a to-be-deployed contract (which may implement `decimals()` after deployment).
/// - a contract that does not implement `decimals()`.
/// @return The decimals of the asset.
function _getDecimals(address asset) internal view returns (uint8) {
if (uint160(asset) <= ADDRESS_RESERVED_RANGE) return 18;
(bool success, bytes memory data) = asset.staticcall(abi.encodeCall(IERC20.decimals, ()));
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
}
Expand Down
8 changes: 8 additions & 0 deletions test/adapter/BaseAdapter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@ import {BaseAdapterHarness} from "test/adapter/BaseAdapterHarness.sol";
import {boundAddr} from "test/utils/TestUtils.sol";

contract BaseAdapterTest is Test {
uint160 internal constant ADDRESS_RESERVED_RANGE = 0xffffffff;
BaseAdapterHarness oracle;

function setUp() public {
oracle = new BaseAdapterHarness();
}

function test_GetDecimals_Integrity_ReservedRange(address x) public view {
x = address(uint160(x) % ADDRESS_RESERVED_RANGE);
assertEq(oracle.getDecimals(x), 18);
}

function test_GetDecimals_Integrity_ERC20(address x, uint8 decimals) public {
x = boundAddr(x);
vm.assume(uint160(x) > ADDRESS_RESERVED_RANGE);
vm.mockCall(x, abi.encodeWithSelector(IERC20.decimals.selector), abi.encode(decimals));

uint8 _decimals = oracle.getDecimals(x);
Expand All @@ -23,6 +30,7 @@ contract BaseAdapterTest is Test {

function test_GetDecimals_Integrity_nonERC20(address x) public view {
x = boundAddr(x);
vm.assume(uint160(x) > ADDRESS_RESERVED_RANGE);

uint8 decimals = oracle.getDecimals(x);
assertEq(decimals, 18);
Expand Down
4 changes: 2 additions & 2 deletions test/utils/TestUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ pragma solidity ^0.8.0;

function boundAddr(address addr) pure returns (address) {
if (
uint160(addr) < 256 || addr == 0x4e59b44847b379578588920cA78FbF26c0B4956C
uint160(addr) < 0x100000000 || addr == 0x4e59b44847b379578588920cA78FbF26c0B4956C
|| addr == 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D || addr == 0x000000000000000000636F6e736F6c652e6c6f67
|| addr == 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f || addr == 0x2e234DAe75C793f67A35089C9d99245E1C58470b
|| addr == 0x104fBc016F4bb334D775a19E8A6510109AC63E00 || addr == 0x4f81992FCe2E1846dD528eC0102e6eE1f61ed3e2
) return address(uint160(addr) + 256);
) return address(uint160(addr) + uint160(0x100000000));

return addr;
}
Expand Down