Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6022494 | 13 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
OracleScaler
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.28; import {ISiloOracle} from "silo-core/contracts/interfaces/ISiloOracle.sol"; import {TokenHelper} from "silo-core/contracts/lib/TokenHelper.sol"; /// @notice OracleScaler is an oracle, which scales the token amounts to 18 decimals instead of original decimals. /// For example, USDC decimals are 6. 1 USDC is 10**6. This oracle will scale this amount to 10**18. If the token /// decimals > 18, this oracle will revert. /// This oracle was created to increase the precision for LTV calculation of low decimal tokens. contract OracleScaler is ISiloOracle { /// @dev the amounts will be scaled to 18 decimals. uint8 public constant DECIMALS_TO_SCALE = 18; /// @dev token address to use for a quote. address public immutable QUOTE_TOKEN; // solhint-disable-line var-name-mixedcase /// @dev scale factor will be multiplied with base token's amount to calculate the scaled value. uint256 public immutable SCALE_FACTOR; // solhint-disable-line var-name-mixedcase /// @dev revert if the original token decimals is more or equal 18 error TokenDecimalsTooLarge(); /// @dev revert if the baseToken to quote is not equal to QUOTE_TOKEN error AssetNotSupported(); constructor(address _quoteToken) { uint8 quoteTokenDecimals = uint8(TokenHelper.assertAndGetDecimals(_quoteToken)); require(quoteTokenDecimals < DECIMALS_TO_SCALE, TokenDecimalsTooLarge()); SCALE_FACTOR = 10 ** uint256(DECIMALS_TO_SCALE - quoteTokenDecimals); QUOTE_TOKEN = _quoteToken; } // @inheritdoc ISiloOracle function beforeQuote(address) external virtual {} // @inheritdoc ISiloOracle function quote(uint256 _baseAmount, address _baseToken) external virtual view returns (uint256 quoteAmount) { require(_baseToken == QUOTE_TOKEN, AssetNotSupported()); quoteAmount = _baseAmount * SCALE_FACTOR; } // @inheritdoc ISiloOracle function quoteToken() external virtual view returns (address) { return address(QUOTE_TOKEN); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface ISiloOracle { /// @notice Hook function to call before `quote` function reads price /// @dev This hook function can be used to change state right before the price is read. For example it can be used /// for curve read only reentrancy protection. In majority of implementations this will be an empty function. /// WARNING: reverts are propagated to Silo so if `beforeQuote` reverts, Silo reverts as well. /// @param _baseToken Address of priced token function beforeQuote(address _baseToken) external; /// @return quoteAmount Returns quote price for _baseAmount of _baseToken /// @param _baseAmount Amount of priced token /// @param _baseToken Address of priced token function quote(uint256 _baseAmount, address _baseToken) external view returns (uint256 quoteAmount); /// @return address of token in which quote (price) is denominated function quoteToken() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.28; import {IERC20Metadata} from "openzeppelin5/token/ERC20/extensions/IERC20Metadata.sol"; import {IsContract} from "./IsContract.sol"; library TokenHelper { uint256 private constant _BYTES32_SIZE = 32; error TokenIsNotAContract(); function assertAndGetDecimals(address _token) internal view returns (uint256) { (bool hasMetadata, bytes memory data) = _tokenMetadataCall(_token, abi.encodeCall(IERC20Metadata.decimals, ())); // decimals() is optional in the ERC20 standard, so if metadata is not accessible // we assume there are no decimals and use 0. if (!hasMetadata) { return 0; } return abi.decode(data, (uint8)); } /// @dev Returns the symbol for the provided ERC20 token. /// An empty string is returned if the call to the token didn't succeed. /// @param _token address of the token to get the symbol for /// @return assetSymbol the token symbol function symbol(address _token) internal view returns (string memory assetSymbol) { (bool hasMetadata, bytes memory data) = _tokenMetadataCall(_token, abi.encodeCall(IERC20Metadata.symbol, ())); if (!hasMetadata || data.length == 0) { return "?"; } else if (data.length == _BYTES32_SIZE) { return string(removeZeros(data)); } else { return abi.decode(data, (string)); } } /// @dev Removes bytes with value equal to 0 from the provided byte array. /// @param _data byte array from which to remove zeroes /// @return result byte array with zeroes removed function removeZeros(bytes memory _data) internal pure returns (bytes memory result) { uint256 n = _data.length; for (uint256 i; i < n; i++) { if (_data[i] == 0) continue; result = abi.encodePacked(result, _data[i]); } } /// @dev Performs a staticcall to the token to get its metadata (symbol, decimals, name) function _tokenMetadataCall(address _token, bytes memory _data) private view returns (bool, bytes memory) { // We need to do this before the call, otherwise the call will succeed even for EOAs require(IsContract.isContract(_token), TokenIsNotAContract()); (bool success, bytes memory result) = _token.staticcall(_data); // If the call reverted we assume the token doesn't follow the metadata extension if (!success) { return (false, ""); } return (true, result); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; library IsContract { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address _account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return _account.code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
{ "remappings": [ "forge-std/=gitmodules/forge-std/src/", "silo-foundry-utils/=gitmodules/silo-foundry-utils/contracts/", "properties/=gitmodules/crytic/properties/contracts/", "silo-core/=silo-core/", "silo-oracles/=silo-oracles/", "silo-vaults/=silo-vaults/", "ve-silo/=ve-silo/", "@openzeppelin/=gitmodules/openzeppelin-contracts-5/contracts/", "morpho-blue/=gitmodules/morpho-blue/src/", "openzeppelin5/=gitmodules/openzeppelin-contracts-5/contracts/", "openzeppelin5-upgradeable/=gitmodules/openzeppelin-contracts-upgradeable-5/contracts/", "chainlink/=gitmodules/chainlink/contracts/src/", "chainlink-ccip/=gitmodules/chainlink-ccip/contracts/src/", "uniswap/=gitmodules/uniswap/", "@uniswap/v3-core/=gitmodules/uniswap/v3-core/", "balancer-labs/v2-solidity-utils/=external/balancer-v2-monorepo/pkg/solidity-utils/contracts/", "balancer-labs/v2-interfaces/=external/balancer-v2-monorepo/pkg/interfaces/contracts/", "balancer-labs/v2-liquidity-mining/=external/balancer-v2-monorepo/pkg/liquidity-mining/contracts/", "pyth-sdk-solidity/=gitmodules/pyth-sdk-solidity/target_chains/ethereum/sdk/solidity/", "@balancer-labs/=node_modules/@balancer-labs/", "@openzeppelin/contracts-upgradeable/=gitmodules/openzeppelin-contracts-upgradeable-5/contracts/", "@openzeppelin/contracts/=gitmodules/openzeppelin-contracts-5/contracts/", "@pythnetwork/=node_modules/@pythnetwork/", "ERC4626/=gitmodules/crytic/properties/lib/ERC4626/contracts/", "createx/=gitmodules/pyth-sdk-solidity/lazer/contracts/evm/lib/createx/src/", "crytic/=gitmodules/crytic/", "ds-test/=gitmodules/openzeppelin-contracts-5/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=gitmodules/openzeppelin-contracts-5/lib/erc4626-tests/", "halmos-cheatcodes/=gitmodules/morpho-blue/lib/halmos-cheatcodes/src/", "openzeppelin-contracts-5/=gitmodules/openzeppelin-contracts-5/", "openzeppelin-contracts-upgradeable-5/=gitmodules/openzeppelin-contracts-upgradeable-5/", "openzeppelin-contracts-upgradeable/=gitmodules/pyth-sdk-solidity/lazer/contracts/evm/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=gitmodules/openzeppelin-contracts-upgradeable-5/lib/openzeppelin-contracts/", "proposals/=node_modules/proposals/", "solady/=gitmodules/pyth-sdk-solidity/lazer/contracts/evm/lib/createx/lib/solady/", "solmate/=gitmodules/crytic/properties/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_quoteToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetNotSupported","type":"error"},{"inputs":[],"name":"TokenDecimalsTooLarge","type":"error"},{"inputs":[],"name":"TokenIsNotAContract","type":"error"},{"inputs":[],"name":"DECIMALS_TO_SCALE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"beforeQuote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_baseAmount","type":"uint256"},{"internalType":"address","name":"_baseToken","type":"address"}],"name":"quote","outputs":[{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405234801561000f575f5ffd5b506040516105ea3803806105ea83398101604081905261002e916101b2565b5f6100388261008c565b9050601260ff82161061005e5760405163a7617b4560e01b815260040160405180910390fd5b6100698160126101f3565b6100779060ff16600a6102f5565b60a052506001600160a01b0316608052610336565b6040805160048152602481019091526020810180516001600160e01b0390811663313ce56760e01b179091525f91829182916100cb918691906100fc16565b91509150816100dd57505f9392505050565b808060200190518101906100f19190610300565b60ff16949350505050565b5f60606001600160a01b0384163b610127576040516373d39f9d60e01b815260040160405180910390fd5b5f5f856001600160a01b0316856040516101419190610320565b5f60405180830381855afa9150503d805f8114610179576040519150601f19603f3d011682016040523d82523d5f602084013e61017e565b606091505b5091509150816101a3575f60405180602001604052805f8152509350935050506101ab565b600193509150505b9250929050565b5f602082840312156101c2575f5ffd5b81516001600160a01b03811681146101d8575f5ffd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b60ff828116828216039081111561020c5761020c6101df565b92915050565b6001815b600184111561024d57808504811115610231576102316101df565b600184161561023f57908102905b60019390931c928002610216565b935093915050565b5f826102635750600161020c565b8161026f57505f61020c565b8160018114610285576002811461028f576102ab565b600191505061020c565b60ff8411156102a0576102a06101df565b50506001821b61020c565b5060208310610133831016604e8410600b84101617156102ce575081810a61020c565b6102da5f198484610212565b805f19048211156102ed576102ed6101df565b029392505050565b5f6101d88383610255565b5f60208284031215610310575f5ffd5b815160ff811681146101d8575f5ffd5b5f82518060208501845e5f920191825250919050565b60805160a05161028061036a5f395f818161010a015261019701525f8181608c0152818160c9015261014201526102805ff3fe608060405234801561000f575f5ffd5b5060043610610060575f3560e01c806313b0be3314610064578063217a4b701461008a57806378892cea146100c4578063a6391566146100eb578063ce4b5bbe14610105578063f9fa619a1461012c575b5f5ffd5b6100776100723660046101de565b61013f565b6040519081526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610081565b6100ac7f000000000000000000000000000000000000000000000000000000000000000081565b6100f3601281565b60405160ff9091168152602001610081565b6100777f000000000000000000000000000000000000000000000000000000000000000081565b61013d61013a366004610208565b50565b005b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146101925760405163981a2a2b60e01b815260040160405180910390fd5b6101bc7f000000000000000000000000000000000000000000000000000000000000000084610221565b9392505050565b80356001600160a01b03811681146101d9575f5ffd5b919050565b5f5f604083850312156101ef575f5ffd5b823591506101ff602084016101c3565b90509250929050565b5f60208284031215610218575f5ffd5b6101bc826101c3565b808202811582820484141761024457634e487b7160e01b5f52601160045260245ffd5b9291505056fea26469706673582212202f827b0dc6a7855848f982645223293707d2c480e991247453bc082c67e8472064736f6c634300081c003300000000000000000000000029219dd400f2bf60e5a23d13be72b486d4038894
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610060575f3560e01c806313b0be3314610064578063217a4b701461008a57806378892cea146100c4578063a6391566146100eb578063ce4b5bbe14610105578063f9fa619a1461012c575b5f5ffd5b6100776100723660046101de565b61013f565b6040519081526020015b60405180910390f35b7f00000000000000000000000029219dd400f2bf60e5a23d13be72b486d40388945b6040516001600160a01b039091168152602001610081565b6100ac7f00000000000000000000000029219dd400f2bf60e5a23d13be72b486d403889481565b6100f3601281565b60405160ff9091168152602001610081565b6100777f000000000000000000000000000000000000000000000000000000e8d4a5100081565b61013d61013a366004610208565b50565b005b5f7f00000000000000000000000029219dd400f2bf60e5a23d13be72b486d40388946001600160a01b0316826001600160a01b0316146101925760405163981a2a2b60e01b815260040160405180910390fd5b6101bc7f000000000000000000000000000000000000000000000000000000e8d4a5100084610221565b9392505050565b80356001600160a01b03811681146101d9575f5ffd5b919050565b5f5f604083850312156101ef575f5ffd5b823591506101ff602084016101c3565b90509250929050565b5f60208284031215610218575f5ffd5b6101bc826101c3565b808202811582820484141761024457634e487b7160e01b5f52601160045260245ffd5b9291505056fea26469706673582212202f827b0dc6a7855848f982645223293707d2c480e991247453bc082c67e8472064736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000029219dd400f2bf60e5a23d13be72b486d4038894
-----Decoded View---------------
Arg [0] : _quoteToken (address): 0x29219dd400f2Bf60E5a23d13Be72B486D4038894
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000029219dd400f2bf60e5a23d13be72b486d4038894
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.