Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 7710726 | 2030 days ago | IN | 0 ETH | 0.00612301 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
WhitePaperInterestRateModel
Compiler Version
v0.5.8+commit.23d335f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-05-07 */ // File: contracts/CarefulMath.sol pragma solidity ^0.5.8; /** * @title Careful Math * @author Compound * @notice Derived from OpenZeppelin's SafeMath library * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol */ contract CarefulMath { /** * @dev Possible error codes that we can return */ enum MathError { NO_ERROR, DIVISION_BY_ZERO, INTEGER_OVERFLOW, INTEGER_UNDERFLOW } /** * @dev Multiplies two numbers, returns an error on overflow. */ function mulUInt(uint a, uint b) internal pure returns (MathError, uint) { if (a == 0) { return (MathError.NO_ERROR, 0); } uint c = a * b; if (c / a != b) { return (MathError.INTEGER_OVERFLOW, 0); } else { return (MathError.NO_ERROR, c); } } /** * @dev Integer division of two numbers, truncating the quotient. */ function divUInt(uint a, uint b) internal pure returns (MathError, uint) { if (b == 0) { return (MathError.DIVISION_BY_ZERO, 0); } return (MathError.NO_ERROR, a / b); } /** * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend). */ function subUInt(uint a, uint b) internal pure returns (MathError, uint) { if (b <= a) { return (MathError.NO_ERROR, a - b); } else { return (MathError.INTEGER_UNDERFLOW, 0); } } /** * @dev Adds two numbers, returns an error on overflow. */ function addUInt(uint a, uint b) internal pure returns (MathError, uint) { uint c = a + b; if (c >= a) { return (MathError.NO_ERROR, c); } else { return (MathError.INTEGER_OVERFLOW, 0); } } /** * @dev add a and b and then subtract c */ function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) { (MathError err0, uint sum) = addUInt(a, b); if (err0 != MathError.NO_ERROR) { return (err0, 0); } return subUInt(sum, c); } } // File: contracts/Exponential.sol pragma solidity ^0.5.8; /** * @title Exponential module for storing fixed-decision decimals * @author Compound * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: * `Exp({mantissa: 5100000000000000000})`. */ contract Exponential is CarefulMath { uint constant expScale = 1e18; uint constant halfExpScale = expScale/2; uint constant mantissaOne = expScale; struct Exp { uint mantissa; } /** * @dev Creates an exponential from numerator and denominator values. * Note: Returns an error if (`num` * 10e18) > MAX_INT, * or if `denom` is zero. */ function getExp(uint num, uint denom) pure internal returns (MathError, Exp memory) { (MathError err0, uint scaledNumerator) = mulUInt(num, expScale); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } (MathError err1, uint rational) = divUInt(scaledNumerator, denom); if (err1 != MathError.NO_ERROR) { return (err1, Exp({mantissa: 0})); } return (MathError.NO_ERROR, Exp({mantissa: rational})); } /** * @dev Adds two exponentials, returning a new exponential. */ function addExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { (MathError error, uint result) = addUInt(a.mantissa, b.mantissa); return (error, Exp({mantissa: result})); } /** * @dev Subtracts two exponentials, returning a new exponential. */ function subExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { (MathError error, uint result) = subUInt(a.mantissa, b.mantissa); return (error, Exp({mantissa: result})); } /** * @dev Multiply an Exp by a scalar, returning a new Exp. */ function mulScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa})); } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mulScalarTruncate(Exp memory a, uint scalar) pure internal returns (MathError, uint) { (MathError err, Exp memory product) = mulScalar(a, scalar); if (err != MathError.NO_ERROR) { return (err, 0); } return (MathError.NO_ERROR, truncate(product)); } /** * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer. */ function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (MathError, uint) { (MathError err, Exp memory product) = mulScalar(a, scalar); if (err != MathError.NO_ERROR) { return (err, 0); } return addUInt(truncate(product), addend); } /** * @dev Divide an Exp by a scalar, returning a new Exp. */ function divScalar(Exp memory a, uint scalar) pure internal returns (MathError, Exp memory) { (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa})); } /** * @dev Divide a scalar by an Exp, returning a new Exp. */ function divScalarByExp(uint scalar, Exp memory divisor) pure internal returns (MathError, Exp memory) { /* We are doing this as: getExp(mulUInt(expScale, scalar), divisor.mantissa) How it works: Exp = a / b; Scalar = s; `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale` */ (MathError err0, uint numerator) = mulUInt(expScale, scalar); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } return getExp(numerator, divisor.mantissa); } /** * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer. */ function divScalarByExpTruncate(uint scalar, Exp memory divisor) pure internal returns (MathError, uint) { (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor); if (err != MathError.NO_ERROR) { return (err, 0); } return (MathError.NO_ERROR, truncate(fraction)); } /** * @dev Multiplies two exponentials, returning a new exponential. */ function mulExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa); if (err0 != MathError.NO_ERROR) { return (err0, Exp({mantissa: 0})); } // We add half the scale before dividing so that we get rounding instead of truncation. // See "Listing 6" and text above it at https://accu.org/index.php/journals/1717 // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18. (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct); if (err1 != MathError.NO_ERROR) { return (err1, Exp({mantissa: 0})); } (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale); // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero. assert(err2 == MathError.NO_ERROR); return (MathError.NO_ERROR, Exp({mantissa: product})); } /** * @dev Multiplies two exponentials given their mantissas, returning a new exponential. */ function mulExp(uint a, uint b) pure internal returns (MathError, Exp memory) { return mulExp(Exp({mantissa: a}), Exp({mantissa: b})); } /** * @dev Multiplies three exponentials, returning a new exponential. */ function mulExp3(Exp memory a, Exp memory b, Exp memory c) pure internal returns (MathError, Exp memory) { (MathError err, Exp memory ab) = mulExp(a, b); if (err != MathError.NO_ERROR) { return (err, ab); } return mulExp(ab, c); } /** * @dev Divides two exponentials, returning a new exponential. * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b, * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa) */ function divExp(Exp memory a, Exp memory b) pure internal returns (MathError, Exp memory) { return getExp(a.mantissa, b.mantissa); } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) pure internal returns (uint) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } /** * @dev Checks if first Exp is less than second Exp. */ function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa < right.mantissa; //TODO: Add some simple tests and this in another PR yo. } /** * @dev Checks if left Exp <= right Exp. */ function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) { return left.mantissa <= right.mantissa; } /** * @dev returns true if Exp is exactly zero */ function isZeroExp(Exp memory value) pure internal returns (bool) { return value.mantissa == 0; } } // File: contracts/InterestRateModel.sol pragma solidity ^0.5.8; /** * @title The Compound InterestRateModel Interface * @author Compound * @notice Any interest rate model should derive from this contract. * @dev These functions are specifically not marked `pure` as implementations of this * contract may read from storage variables. */ interface InterestRateModel { /** * @notice Gets the current borrow interest rate based on the given asset, total cash, total borrows * and total reserves. * @dev The return value should be scaled by 1e18, thus a return value of * `(true, 1000000000000)` implies an interest rate of 0.000001 or 0.0001% *per block*. * @param cash The total cash of the underlying asset in the CToken * @param borrows The total borrows of the underlying asset in the CToken * @param reserves The total reserves of the underlying asset in the CToken * @return Success or failure and the borrow interest rate per block scaled by 10e18 */ function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint, uint); /** * @notice Marker function used for light validation when updating the interest rate model of a market * @dev Marker function used for light validation when updating the interest rate model of a market. Implementations should simply return true. * @return Success or failure */ function isInterestRateModel() external view returns (bool); } // File: contracts/WhitePaperInterestRateModel.sol pragma solidity ^0.5.8; /** * @title The Compound Standard Interest Rate Model with pluggable constants * @author Compound * @notice See Section 2.4 of the Compound Whitepaper */ contract WhitePaperInterestRateModel is InterestRateModel, Exponential { /** * @notice Indicator that this is an InterestRateModel contract (for inspection) */ bool public constant isInterestRateModel = true; /** * @notice The multiplier of utilization rate that gives the slope of the interest rate */ uint public multiplier; /** * @notice The base interest rate which is the y-intercept when utilization rate is 0 */ uint public baseRate; /** * @notice The approximate number of blocks per year that is assumed by the interest rate model */ uint public constant blocksPerYear = 2102400; constructor(uint baseRate_, uint multiplier_) public { baseRate = baseRate_; multiplier = multiplier_; } enum IRError { NO_ERROR, FAILED_TO_ADD_CASH_PLUS_BORROWS, FAILED_TO_GET_EXP, FAILED_TO_MUL_UTILIZATION_RATE, FAILED_TO_ADD_BASE_RATE } /* * @dev Calculates the utilization rate (borrows / (cash + borrows)) as an Exp */ function getUtilizationRate(uint cash, uint borrows) pure internal returns (IRError, Exp memory) { if (borrows == 0) { // Utilization rate is zero when there's no borrows return (IRError.NO_ERROR, Exp({mantissa: 0})); } (MathError err0, uint cashPlusBorrows) = addUInt(cash, borrows); if (err0 != MathError.NO_ERROR) { return (IRError.FAILED_TO_ADD_CASH_PLUS_BORROWS, Exp({mantissa: 0})); } (MathError err1, Exp memory utilizationRate) = getExp(borrows, cashPlusBorrows); if (err1 != MathError.NO_ERROR) { return (IRError.FAILED_TO_GET_EXP, Exp({mantissa: 0})); } return (IRError.NO_ERROR, utilizationRate); } /* * @dev Calculates the utilization and borrow rates for use by getBorrowRate function */ function getUtilizationAndAnnualBorrowRate(uint cash, uint borrows) view internal returns (IRError, Exp memory, Exp memory) { (IRError err0, Exp memory utilizationRate) = getUtilizationRate(cash, borrows); if (err0 != IRError.NO_ERROR) { return (err0, Exp({mantissa: 0}), Exp({mantissa: 0})); } // Borrow Rate is 5% + UtilizationRate * 45% (baseRate + UtilizationRate * multiplier); // 45% of utilizationRate, is `rate * 45 / 100` (MathError err1, Exp memory utilizationRateMuled) = mulScalar(utilizationRate, multiplier); // `mulScalar` only overflows when the product is >= 2^256. // utilizationRate is a real number on the interval [0,1], which means that // utilizationRate.mantissa is in the interval [0e18,1e18], which means that 45 times // that is in the interval [0e18,45e18]. That interval has no intersection with 2^256, and therefore // this can never overflow for the standard rates. if (err1 != MathError.NO_ERROR) { return (IRError.FAILED_TO_MUL_UTILIZATION_RATE, Exp({mantissa: 0}), Exp({mantissa: 0})); } (MathError err2, Exp memory utilizationRateScaled) = divScalar(utilizationRateMuled, mantissaOne); // 100 is a constant, and therefore cannot be zero, which is the only error case of divScalar. assert(err2 == MathError.NO_ERROR); // Add the 5% for (5% + 45% * Ua) (MathError err3, Exp memory annualBorrowRate) = addExp(utilizationRateScaled, Exp({mantissa: baseRate})); // `addExp` only fails when the addition of mantissas overflow. // As per above, utilizationRateMuled is capped at 45e18, // and utilizationRateScaled is capped at 4.5e17. mantissaFivePercent = 0.5e17, and thus the addition // is capped at 5e17, which is less than 2^256. This only applies to the standard rates if (err3 != MathError.NO_ERROR) { return (IRError.FAILED_TO_ADD_BASE_RATE, Exp({mantissa: 0}), Exp({mantissa: 0})); } return (IRError.NO_ERROR, utilizationRate, annualBorrowRate); } /** * @notice Gets the current borrow interest rate based on the given asset, total cash, total borrows * and total reserves. * @dev The return value should be scaled by 1e18, thus a return value of * `(true, 1000000000000)` implies an interest rate of 0.000001 or 0.0001% *per block*. * @param cash The total cash of the underlying asset in the CToken * @param borrows The total borrows of the underlying asset in the CToken * @param _reserves The total reserves of the underlying asset in the CToken * @return Success or failure and the borrow interest rate per block scaled by 10e18 */ function getBorrowRate(uint cash, uint borrows, uint _reserves) public view returns (uint, uint) { _reserves; // pragma ignore unused argument (IRError err0, Exp memory _utilizationRate, Exp memory annualBorrowRate) = getUtilizationAndAnnualBorrowRate(cash, borrows); if (err0 != IRError.NO_ERROR) { return (uint(err0), 0); } // And then divide down by blocks per year. (MathError err1, Exp memory borrowRate) = divScalar(annualBorrowRate, blocksPerYear); // basis points * blocks per year // divScalar only fails when divisor is zero. This is clearly not the case. assert(err1 == MathError.NO_ERROR); _utilizationRate; // pragma ignore unused variable // Note: mantissa is the rate scaled 1e18, which matches the expected result return (uint(IRError.NO_ERROR), borrowRate.mantissa); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[{"name":"cash","type":"uint256"},{"name":"borrows","type":"uint256"},{"name":"_reserves","type":"uint256"}],"name":"getBorrowRate","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"multiplier","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"baseRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isInterestRateModel","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blocksPerYear","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"baseRate_","type":"uint256"},{"name":"multiplier_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516040806106638339810180604052604081101561003057600080fd5b508051602090910151600191909155600055610612806100516000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806315f240531461005c5780631b3ed7221461009e5780631f68f20a146100b85780632191f92a146100c0578063a385fb96146100dc575b600080fd5b6100856004803603606081101561007257600080fd5b50803590602081013590604001356100e4565b6040805192835260208301919091528051918290030190f35b6100a661017d565b60408051918252519081900360200190f35b6100a6610183565b6100c8610189565b604080519115158252519081900360200190f35b6100a661018e565b60008060006100f16105d3565b6100f96105d3565b6101038888610195565b91945092509050600083600481111561011857fe5b146101385782600481111561012957fe5b94506000935061017592505050565b60006101426105d3565b61014f8362201480610312565b9092509050600082600381111561016257fe5b1461016957fe5b51600096509450505050505b935093915050565b60005481565b60015481565b600181565b6220148081565b600061019f6105d3565b6101a76105d3565b60006101b16105d3565b6101bb878761037c565b909250905060008260048111156101ce57fe5b146101fc5750604080516020808201835260008083528351918201909352918252919450909250905061030b565b60006102066105d3565b6102128360005461043e565b9092509050600082600381111561022557fe5b14610257575050604080516020808201835260008083528351918201909352918252600396509450925061030b915050565b60006102616105d3565b61027383670de0b6b3a7640000610312565b9092509050600082600381111561028657fe5b1461028d57fe5b60006102976105d3565b6102b1836040518060200160405280600154815250610459565b909250905060008260038111156102c457fe5b146102fa57505060408051602080820183526000808352835191820190935291825260049a509850965061030b95505050505050565b60009a509598509496505050505050505b9250925092565b600061031c6105d3565b60008061032d866000015186610493565b9092509050600082600381111561034057fe5b1461035f57506040805160208101909152600081529092509050610375565b6040805160208101909152908152600093509150505b9250929050565b60006103866105d3565b826103a35750506040805160208101909152600080825290610375565b6000806103b086866104be565b909250905060008260038111156103c357fe5b146103e4575050604080516020810190915260008152600192509050610375565b60006103ee6105d3565b6103f887846104e4565b9092509050600082600381111561040b57fe5b1461042f575050604080516020810190915260008152600294509250610375915050565b60009890975095505050505050565b60006104486105d3565b60008061032d866000015186610594565b60006104636105d3565b600080610478866000015186600001516104be565b60408051602081019091529081529097909650945050505050565b600080826104a75750600190506000610375565b60008385816104b257fe5b04915091509250929050565b6000808383018481106104d657600092509050610375565b506002915060009050610375565b60006104ee6105d3565b60008061050386670de0b6b3a7640000610594565b9092509050600082600381111561051657fe5b1461053557506040805160208101909152600081529092509050610375565b6000806105428388610493565b9092509050600082600381111561055557fe5b1461057757506040805160208101909152600081529094509250610375915050565b604080516020810190915290815260009890975095505050505050565b600080836105a757506000905080610375565b838302838582816105b457fe5b04146105c857506002915060009050610375565b600092509050610375565b604051806020016040528060008152509056fea165627a7a7230582021d1e96de1a54e5aaf17c19ae397dd393fa0cd21afedd016b0e6d1fb0e4c7496002900000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100575760003560e01c806315f240531461005c5780631b3ed7221461009e5780631f68f20a146100b85780632191f92a146100c0578063a385fb96146100dc575b600080fd5b6100856004803603606081101561007257600080fd5b50803590602081013590604001356100e4565b6040805192835260208301919091528051918290030190f35b6100a661017d565b60408051918252519081900360200190f35b6100a6610183565b6100c8610189565b604080519115158252519081900360200190f35b6100a661018e565b60008060006100f16105d3565b6100f96105d3565b6101038888610195565b91945092509050600083600481111561011857fe5b146101385782600481111561012957fe5b94506000935061017592505050565b60006101426105d3565b61014f8362201480610312565b9092509050600082600381111561016257fe5b1461016957fe5b51600096509450505050505b935093915050565b60005481565b60015481565b600181565b6220148081565b600061019f6105d3565b6101a76105d3565b60006101b16105d3565b6101bb878761037c565b909250905060008260048111156101ce57fe5b146101fc5750604080516020808201835260008083528351918201909352918252919450909250905061030b565b60006102066105d3565b6102128360005461043e565b9092509050600082600381111561022557fe5b14610257575050604080516020808201835260008083528351918201909352918252600396509450925061030b915050565b60006102616105d3565b61027383670de0b6b3a7640000610312565b9092509050600082600381111561028657fe5b1461028d57fe5b60006102976105d3565b6102b1836040518060200160405280600154815250610459565b909250905060008260038111156102c457fe5b146102fa57505060408051602080820183526000808352835191820190935291825260049a509850965061030b95505050505050565b60009a509598509496505050505050505b9250925092565b600061031c6105d3565b60008061032d866000015186610493565b9092509050600082600381111561034057fe5b1461035f57506040805160208101909152600081529092509050610375565b6040805160208101909152908152600093509150505b9250929050565b60006103866105d3565b826103a35750506040805160208101909152600080825290610375565b6000806103b086866104be565b909250905060008260038111156103c357fe5b146103e4575050604080516020810190915260008152600192509050610375565b60006103ee6105d3565b6103f887846104e4565b9092509050600082600381111561040b57fe5b1461042f575050604080516020810190915260008152600294509250610375915050565b60009890975095505050505050565b60006104486105d3565b60008061032d866000015186610594565b60006104636105d3565b600080610478866000015186600001516104be565b60408051602081019091529081529097909650945050505050565b600080826104a75750600190506000610375565b60008385816104b257fe5b04915091509250929050565b6000808383018481106104d657600092509050610375565b506002915060009050610375565b60006104ee6105d3565b60008061050386670de0b6b3a7640000610594565b9092509050600082600381111561051657fe5b1461053557506040805160208101909152600081529092509050610375565b6000806105428388610493565b9092509050600082600381111561055557fe5b1461057757506040805160208101909152600081529094509250610375915050565b604080516020810190915290815260009890975095505050505050565b600080836105a757506000905080610375565b838302838582816105b457fe5b04146105c857506002915060009050610375565b600092509050610375565b604051806020016040528060008152509056fea165627a7a7230582021d1e96de1a54e5aaf17c19ae397dd393fa0cd21afedd016b0e6d1fb0e4c74960029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000001aa535d3d0c0000
-----Decoded View---------------
Arg [0] : baseRate_ (uint256): 50000000000000000
Arg [1] : multiplier_ (uint256): 120000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000b1a2bc2ec50000
Arg [1] : 00000000000000000000000000000000000000000000000001aa535d3d0c0000
Swarm Source
bzzr://21d1e96de1a54e5aaf17c19ae397dd393fa0cd21afedd016b0e6d1fb0e4c7496
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.