Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Initialize | 486075 | 1533 days ago | IN | 0 ETH | 0.000489826347 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 107500185 | 924 days ago | 0 ETH | ||||
| 107494897 | 924 days ago | 0 ETH | ||||
| 107472267 | 924 days ago | 0 ETH | ||||
| 107451422 | 925 days ago | 0 ETH | ||||
| 107451258 | 925 days ago | 0 ETH | ||||
| 107434516 | 925 days ago | 0 ETH | ||||
| 107432950 | 925 days ago | 0 ETH | ||||
| 107423791 | 926 days ago | 0 ETH | ||||
| 107364627 | 927 days ago | 0 ETH | ||||
| 107364567 | 927 days ago | 0 ETH | ||||
| 107364548 | 927 days ago | 0 ETH | ||||
| 107345274 | 927 days ago | 0 ETH | ||||
| 107337206 | 928 days ago | 0 ETH | ||||
| 107336470 | 928 days ago | 0 ETH | ||||
| 107328923 | 928 days ago | 0 ETH | ||||
| 107264344 | 929 days ago | 0 ETH | ||||
| 107220698 | 930 days ago | 0 ETH | ||||
| 107207898 | 931 days ago | 0 ETH | ||||
| 107207892 | 931 days ago | 0 ETH | ||||
| 107200032 | 931 days ago | 0 ETH | ||||
| 107200032 | 931 days ago | 0 ETH | ||||
| 107195166 | 931 days ago | 0 ETH | ||||
| 107193299 | 931 days ago | 0 ETH | ||||
| 107130959 | 932 days ago | 0 ETH | ||||
| 107130907 | 932 days ago | 0 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "./MSD.sol";
/**
* @dev Interface for Minters, minters now can be iMSD and MSDS
*/
interface IMinter {
function totalMint() external returns (uint256);
}
/**
* @title dForce's Multi-currency Stable Debt Token Controller
* @author dForce
*/
contract MSDControllerV2 is Initializable, Ownable {
using SafeMathUpgradeable for uint256;
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
/// @dev EnumerableSet of all msdTokens
EnumerableSetUpgradeable.AddressSet internal msdTokens;
// @notice Mapping of msd tokens to corresponding minters
mapping(address => EnumerableSetUpgradeable.AddressSet) internal msdMinters;
struct TokenData {
// System earning from borrow interest
uint256 earning;
// System debt from saving interest
uint256 debt;
}
// @notice Mapping of msd tokens to corresponding TokenData
mapping(address => TokenData) public msdTokenData;
// @notice Mapping of msd minters to corresponding msd token mintage cap
// @dev Each minter now typically iMSD can only mint 1 msd token
/*
* The mint cap of the msd minter, will be checked in mintMSD()
* -1 means there is no limit on the cap
* 0 means the msd token can not be mint any more
*/
mapping(address => mapping(address => uint256)) public mintCaps;
/**
* @dev Emitted when `token` is added into msdTokens.
*/
event MSDAdded(address token);
/**
* @dev Emitted when `minter` is added into `tokens`'s minters.
*/
event MinterAdded(address token, address minter);
/**
* @dev Emitted when `minter` is removed from `tokens`'s minters.
*/
event MinterRemoved(address token, address minter);
/**
* @dev Emitted when reserve is withdrawn from `token`.
*/
event ReservesWithdrawn(
address owner,
address token,
uint256 amount,
uint256 oldTotalReserves,
uint256 newTotalReserves
);
/// @dev Emitted when msd token minter's mint cap is changed
event NewMintCap(
address token,
address minter,
uint256 oldMintCap,
uint256 newMintCap
);
/**
* @notice Expects to call only once to initialize the MSD controller.
*/
function initialize() external initializer {
__Ownable_init();
}
/**
* @notice Ensure this is a MSD Controller contract.
*/
function isMSDController() external pure returns (bool) {
return true;
}
/**
* @dev Throws if token is not in msdTokens
*/
function _checkMSD(address _token) internal view {
require(hasMSD(_token), "token is not a valid MSD token");
}
/**
* @dev Throws if token is not a valid MSD token.
*/
modifier onlyMSD(address _token) {
_checkMSD(_token);
_;
}
/**
* @dev Throws if called by any account other than the _token's minters.
*/
modifier onlyMSDMinter(address _token, address caller) {
_checkMSD(_token);
require(
msdMinters[_token].contains(caller),
"onlyMinter: caller is not the token's minter"
);
_;
}
function _addMSDInternal(address _token) internal {
require(_token != address(0), "MSD token cannot be a zero address");
if (msdTokens.add(_token)) {
emit MSDAdded(_token);
}
}
function _addMinterInternal(address _token, address _minter) internal {
require(_minter != address(0), "minter cannot be a zero address");
if (msdMinters[_token].add(_minter)) {
emit MinterAdded(_token, _minter);
}
}
function _removeMinterInternal(address _token, address _minter) internal {
require(_minter != address(0), "minter cannot be a zero address");
if (msdMinters[_token].remove(_minter)) {
emit MinterRemoved(_token, _minter);
}
}
function _setMintCapInternal(
address _token,
address _minter,
uint256 _newMintCap
) internal {
uint256 oldMintCap = mintCaps[_token][_minter];
if (oldMintCap != _newMintCap) {
mintCaps[_token][_minter] = _newMintCap;
emit NewMintCap(_token, _minter, oldMintCap, _newMintCap);
}
}
function _addMintersInternal(
address _token,
address[] calldata _minters,
uint256[] calldata _mintCaps
) internal {
require(
_minters.length == _mintCaps.length,
"Length of _minters and _mintCaps mismatch"
);
uint256 _len = _minters.length;
for (uint256 i = 0; i < _len; i++) {
_addMinterInternal(_token, _minters[i]);
_setMintCapInternal(_token, _minters[i], _mintCaps[i]);
}
}
/**
* @notice Add `_token` into msdTokens, and add `_minters` into minters along with `_mintCaps`.
* If `_token` have not been in msdTokens, emits a `MSDTokenAdded` event.
* If _minter in `_minters` have not been in msd Token's minters, emits a `MinterAdded` event.
* If cap in `_mintCaps` has changed, emits a `NewMintCap` event.
*
* @param _token The msd token to add
* @param _minters The addresses to add as msd token's minters
* @param _mintCaps The mint caps to set for minters
*
* Requirements:
* - the caller must be `owner`.
*/
function _addMSD(
address _token,
address[] calldata _minters,
uint256[] calldata _mintCaps
) external onlyOwner {
_addMSDInternal(_token);
_addMintersInternal(_token, _minters, _mintCaps);
}
/**
* @notice Add `_minters` into minters along with `_mintCaps`.
* If _minter in `_minters` have not been in msd Token's minters, emits a `MinterAdded` event.
* If cap in `_mintCaps` has changed, emits a `NewMintCap` event.
*
* @param _token The msd token to add minters
* @param _minters The addresses to add as msd token's minters
* @param _mintCaps The mint caps to set for minters
*
* Requirements:
* - the caller must be `owner`.
*/
function _addMinters(
address _token,
address[] calldata _minters,
uint256[] calldata _mintCaps
) external onlyOwner onlyMSD(_token) {
_addMintersInternal(_token, _minters, _mintCaps);
}
/**
* @notice Remove `minters` from minters and reset mint cap to 0.
* If `minter` is minters, emits a `MinterRemoved` event.
*
* @param _minters The minters to remove
*
* Requirements:
* - the caller must be `owner`, `_token` must be a MSD Token.
*/
function _removeMinters(address _token, address[] calldata _minters)
external
onlyOwner
onlyMSD(_token)
{
uint256 _len = _minters.length;
for (uint256 i = 0; i < _len; i++) {
_removeMinterInternal(_token, _minters[i]);
_setMintCapInternal(_token, _minters[i], 0);
}
}
/**
* @notice set `_mintCaps` for `_token`'s `_minters`, emits a `NewMintCap` event.
*
* @param _token The msd token to set
* @param _minters The msd token's minters' addresses to set
* @param _mintCaps The mint caps to set for minters
*
* Requirements:
* - the caller must be `owner`.
*/
function _setMintCaps(
address _token,
address[] calldata _minters,
uint256[] calldata _mintCaps
) external onlyOwner onlyMSD(_token) {
require(
_minters.length == _mintCaps.length,
"Length of _minters and _mintCaps mismatch"
);
uint256 _len = _minters.length;
for (uint256 i = 0; i < _len; i++) {
require(
msdMinters[_token].contains(_minters[i]),
"minter is not the token's minter"
);
_setMintCapInternal(_token, _minters[i], _mintCaps[i]);
}
}
/**
* @notice Withdraw the reserve of `_token`.
* @param _token The MSD token to withdraw
* @param _amount The amount of token to withdraw
*
* Requirements:
* - the caller must be `owner`, `_token` must be a MSD Token.
*/
function _withdrawReserves(address _token, uint256 _amount)
external
onlyOwner
onlyMSD(_token)
{
(uint256 _equity, ) = calcEquity(_token);
require(_equity >= _amount, "Token do not have enough reserve");
// Increase the token debt
msdTokenData[_token].debt = msdTokenData[_token].debt.add(_amount);
// Directly mint the token to owner
MSD(_token).mint(owner, _amount);
emit ReservesWithdrawn(
owner,
_token,
_amount,
_equity,
_equity.sub(_amount)
);
}
/**
* @notice Mint `amount` of `_token` to `_to`.
* @param _token The MSD token to mint
* @param _to The account to mint to
* @param _amount The amount of token to mint
*
* Requirements:
* - the caller must be `minter` of `_token`.
*/
function mintMSD(
address _token,
address _to,
uint256 _amount
) external onlyMSDMinter(_token, msg.sender) {
_beforeMint(_token, msg.sender, _to, _amount);
MSD(_token).mint(_to, _amount);
}
function _beforeMint(
address _token,
address _minter,
address _to,
uint256 _amount
) internal virtual {
// Check minter's mint cap, -1 means no limit
// _amount has been taken account into totalMint/totalBorrows
require(
IMinter(_minter).totalMint() <= mintCaps[_token][_minter],
"Minter mint capacity reached"
);
_to;
_amount;
}
/*********************************/
/******** MSD Token Equity *******/
/*********************************/
/**
* @notice Get the MSD token equity
* @param _token The MSD token to query
* @return token equity, token debt, will call `updateInterest()` on its minters
*
* Requirements:
* - `_token` must be a MSD Token.
*
*/
function calcEquity(address _token)
public
view
onlyMSD(_token)
returns (uint256, uint256)
{
TokenData storage _tokenData = msdTokenData[_token];
return
_tokenData.earning > _tokenData.debt
? (_tokenData.earning.sub(_tokenData.debt), uint256(0))
: (uint256(0), _tokenData.debt.sub(_tokenData.earning));
}
/*********************************/
/****** General Information ******/
/*********************************/
/**
* @notice Return all of the MSD tokens
* @return _allMSDs The list of MSD token addresses
*/
function getAllMSDs() public view returns (address[] memory _allMSDs) {
EnumerableSetUpgradeable.AddressSet storage _msdTokens = msdTokens;
uint256 _len = _msdTokens.length();
_allMSDs = new address[](_len);
for (uint256 i = 0; i < _len; i++) {
_allMSDs[i] = _msdTokens.at(i);
}
}
/**
* @notice Check whether a address is a valid MSD
* @param _token The token address to check for
* @return true if the _token is a valid MSD otherwise false
*/
function hasMSD(address _token) public view returns (bool) {
return msdTokens.contains(_token);
}
/**
* @notice Return all minter of a MSD token
* @param _token The MSD token address to get minters for
* @return _minters The list of MSD token minter addresses
* Will retuen empty if `_token` is not a valid MSD token
*/
function getMSDMinters(address _token)
public
view
returns (address[] memory _minters)
{
EnumerableSetUpgradeable.AddressSet storage _msdMinters =
msdMinters[_token];
uint256 _len = _msdMinters.length();
_minters = new address[](_len);
for (uint256 i = 0; i < _len; i++) {
_minters[i] = _msdMinters.at(i);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSetUpgradeable {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(value)));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(value)));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(value)));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint256(_at(set._inner, index)));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMathUpgradeable {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol";
import "../library/Initializable.sol";
import "../library/Ownable.sol";
import "../library/ERC20.sol";
/**
* @title dForce's Multi-currency Stable Debt Token
* @author dForce
*/
contract MSD is Initializable, Ownable, ERC20 {
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
bytes32 public DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 chainId, uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH =
0x576144ed657c8304561e56ca632e17751956250114636e8c01f64a7f2c6d98cf;
mapping(address => uint256) public nonces;
/// @dev EnumerableSet of minters
EnumerableSetUpgradeable.AddressSet internal minters;
/**
* @dev Emitted when `minter` is added as `minter`.
*/
event MinterAdded(address minter);
/**
* @dev Emitted when `minter` is removed from `minters`.
*/
event MinterRemoved(address minter);
/**
* @notice Expects to call only once to initialize the MSD token.
* @param _name Token name.
* @param _symbol Token symbol.
*/
function initialize(
string memory _name,
string memory _symbol,
uint8 _decimals
) external initializer {
__Ownable_init();
__ERC20_init(_name, _symbol, _decimals);
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(_name)),
keccak256(bytes("1")),
_getChainId(),
address(this)
)
);
}
/**
* @dev Throws if called by any account other than the minters.
*/
modifier onlyMinter() {
require(
minters.contains(msg.sender),
"onlyMinter: caller is not minter"
);
_;
}
/**
* @notice Add `minter` into minters.
* If `minter` have not been a minter, emits a `MinterAdded` event.
*
* @param _minter The minter to add
*
* Requirements:
* - the caller must be `owner`.
*/
function _addMinter(address _minter) external onlyOwner {
require(_minter != address(0), "_addMinter: _minter the zero address");
if (minters.add(_minter)) {
emit MinterAdded(_minter);
}
}
/**
* @notice Remove `minter` from minters.
* If `minter` is a minter, emits a `MinterRemoved` event.
*
* @param _minter The minter to remove
*
* Requirements:
* - the caller must be `owner`.
*/
function _removeMinter(address _minter) external onlyOwner {
require(
_minter != address(0),
"_removeMinter: _minter the zero address"
);
if (minters.remove(_minter)) {
emit MinterRemoved(_minter);
}
}
function mint(address to, uint256 amount) external onlyMinter {
_mint(to, amount);
}
function burn(address from, uint256 amount) external {
_burnFrom(from, amount);
}
function _getChainId() internal pure returns (uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
/**
* @dev EIP2612 permit function. For more details, please look at here:
* https://eips.ethereum.org/EIPS/eip-2612
* @param _owner The owner of the funds.
* @param _spender The spender.
* @param _value The amount.
* @param _deadline The deadline timestamp, type(uint256).max for max deadline.
* @param _v Signature param.
* @param _s Signature param.
* @param _r Signature param.
*/
function permit(
address _owner,
address _spender,
uint256 _value,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) external {
require(_deadline >= block.timestamp, "permit: EXPIRED!");
uint256 _currentNonce = nonces[_owner];
bytes32 _digest =
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
_owner,
_spender,
_getChainId(),
_value,
_currentNonce,
_deadline
)
)
)
);
address _recoveredAddress = ecrecover(_digest, _v, _r, _s);
require(
_recoveredAddress != address(0) && _recoveredAddress == _owner,
"permit: INVALID_SIGNATURE!"
);
nonces[_owner] = _currentNonce.add(1);
_approve(_owner, _spender, _value);
}
/**
* @notice Return all minters of this MSD token
* @return _minters The list of minter addresses
*/
function getMinters() public view returns (address[] memory _minters) {
uint256 _len = minters.length();
_minters = new address[](_len);
for (uint256 i = 0; i < _len; i++) {
_minters[i] = minters.at(i);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(
!_initialized,
"Initializable: contract is already initialized"
);
_;
_initialized = true;
}
}//SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {_setPendingOwner} and {_acceptOwner}.
*/
contract Ownable {
/**
* @dev Returns the address of the current owner.
*/
address payable public owner;
/**
* @dev Returns the address of the current pending owner.
*/
address payable public pendingOwner;
event NewOwner(address indexed previousOwner, address indexed newOwner);
event NewPendingOwner(
address indexed oldPendingOwner,
address indexed newPendingOwner
);
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner == msg.sender, "onlyOwner: caller is not the owner");
_;
}
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal {
owner = msg.sender;
emit NewOwner(address(0), msg.sender);
}
/**
* @notice Base on the inputing parameter `newPendingOwner` to check the exact error reason.
* @dev Transfer contract control to a new owner. The newPendingOwner must call `_acceptOwner` to finish the transfer.
* @param newPendingOwner New pending owner.
*/
function _setPendingOwner(address payable newPendingOwner)
external
onlyOwner
{
require(
newPendingOwner != address(0) && newPendingOwner != pendingOwner,
"_setPendingOwner: New owenr can not be zero address and owner has been set!"
);
// Gets current owner.
address oldPendingOwner = pendingOwner;
// Sets new pending owner.
pendingOwner = newPendingOwner;
emit NewPendingOwner(oldPendingOwner, newPendingOwner);
}
/**
* @dev Accepts the admin rights, but only for pendingOwenr.
*/
function _acceptOwner() external {
require(
msg.sender == pendingOwner,
"_acceptOwner: Only for pending owner!"
);
// Gets current values for events.
address oldOwner = owner;
address oldPendingOwner = pendingOwner;
// Set the new contract owner.
owner = pendingOwner;
// Clear the pendingOwner.
pendingOwner = address(0);
emit NewOwner(oldOwner, owner);
emit NewPendingOwner(oldPendingOwner, pendingOwner);
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 {
using SafeMathUpgradeable for uint256;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 public totalSupply;
string public name;
string public symbol;
uint8 public decimals;
/**
* @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 Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(
string memory name_,
string memory symbol_,
uint8 decimals_
) internal {
name = name_;
symbol = symbol_;
decimals = decimals_;
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount)
public
virtual
returns (bool)
{
_transfer(msg.sender, recipient, amount);
return true;
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount)
public
virtual
returns (bool)
{
_approve(msg.sender, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, msg.sender, allowance[sender][msg.sender].sub(amount));
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue)
public
virtual
returns (bool)
{
_approve(
msg.sender,
spender,
allowance[msg.sender][spender].add(addedValue)
);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
returns (bool)
{
_approve(
msg.sender,
spender,
allowance[msg.sender][spender].sub(subtractedValue)
);
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
balanceOf[sender] = balanceOf[sender].sub(amount);
balanceOf[recipient] = balanceOf[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `to` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
totalSupply = totalSupply.add(amount);
balanceOf[account] = balanceOf[account].add(amount);
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
balanceOf[account] = balanceOf[account].sub(amount);
totalSupply = totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance if caller is not the `account`.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller other than `msg.sender` must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function _burnFrom(address account, uint256 amount) internal virtual {
if (msg.sender != account)
_approve(
account,
msg.sender,
allowance[account][msg.sender].sub(amount)
);
_burn(account, amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
allowance[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
uint256[50] private __gap;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"MSDAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"minter","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"minter","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldMintCap","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMintCap","type":"uint256"}],"name":"NewMintCap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldTotalReserves","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalReserves","type":"uint256"}],"name":"ReservesWithdrawn","type":"event"},{"inputs":[],"name":"_acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_minters","type":"address[]"},{"internalType":"uint256[]","name":"_mintCaps","type":"uint256[]"}],"name":"_addMSD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_minters","type":"address[]"},{"internalType":"uint256[]","name":"_mintCaps","type":"uint256[]"}],"name":"_addMinters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_minters","type":"address[]"}],"name":"_removeMinters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_minters","type":"address[]"},{"internalType":"uint256[]","name":"_mintCaps","type":"uint256[]"}],"name":"_setMintCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newPendingOwner","type":"address"}],"name":"_setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"_withdrawReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"calcEquity","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllMSDs","outputs":[{"internalType":"address[]","name":"_allMSDs","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getMSDMinters","outputs":[{"internalType":"address[]","name":"_minters","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"hasMSD","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMSDController","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"mintCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintMSD","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"msdTokenData","outputs":[{"internalType":"uint256","name":"earning","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50611a26806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c80638da5cb5b116100a2578063d2de243411610071578063d2de243414610572578063e30c397814610598578063fb43d68d146105a0578063fc4d33f9146105a8578063fc662774146105b057610116565b80638da5cb5b1461041a578063b1e1436f1461043e578063b5add45c14610464578063bfeb5c1c146104a457610116565b80636e96dfd7116100e95780636e96dfd7146103475780637431fc381461036d5780638129fc1c146103a757806386c975e0146103af5780638af225ae146103ee57610116565b8063014db0011461011b578063494c6e88146101eb57806352be45af146102435780636e839b0b14610311575b600080fd5b6101e96004803603606081101561013157600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561015b57600080fd5b82018360208201111561016d57600080fd5b803590602001918460208302840111600160201b8311171561018e57600080fd5b919390929091602081019035600160201b8111156101ab57600080fd5b8201836020820111156101bd57600080fd5b803590602001918460208302840111600160201b831117156101de57600080fd5b50909250905061062e565b005b6101f36107a5565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561022f578181015183820152602001610217565b505050509050019250505060405180910390f35b6101e96004803603606081101561025957600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561028357600080fd5b82018360208201111561029557600080fd5b803590602001918460208302840111600160201b831117156102b657600080fd5b919390929091602081019035600160201b8111156102d357600080fd5b8201836020820111156102e557600080fd5b803590602001918460208302840111600160201b8311171561030657600080fd5b509092509050610841565b6101e96004803603606081101561032757600080fd5b506001600160a01b038135811691602081013590911690604001356108ac565b6101e96004803603602081101561035d57600080fd5b50356001600160a01b0316610996565b6103936004803603602081101561038357600080fd5b50356001600160a01b0316610a97565b604080519115158252519081900360200190f35b6101e9610aaa565b6103d5600480360360208110156103c557600080fd5b50356001600160a01b0316610b03565b6040805192835260208301919091528051918290030190f35b6101e96004803603604081101561040457600080fd5b506001600160a01b038135169060200135610b6b565b610422610d4b565b604080516001600160a01b039092168252519081900360200190f35b6103d56004803603602081101561045457600080fd5b50356001600160a01b0316610d5f565b6104926004803603604081101561047a57600080fd5b506001600160a01b0381358116916020013516610d78565b60408051918252519081900360200190f35b6101e9600480360360608110156104ba57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104e457600080fd5b8201836020820111156104f657600080fd5b803590602001918460208302840111600160201b8311171561051757600080fd5b919390929091602081019035600160201b81111561053457600080fd5b82018360208201111561054657600080fd5b803590602001918460208302840111600160201b8311171561056757600080fd5b509092509050610d95565b6101f36004803603602081101561058857600080fd5b50356001600160a01b0316610e02565b610422610eb5565b610393610ec4565b6101e9610ec9565b6101e9600480360360408110156105c657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105f057600080fd5b82018360208201111561060257600080fd5b803590602001918460208302840111600160201b8311171561062357600080fd5b509092509050610fc0565b60005461010090046001600160a01b0316331461067c5760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b8461068681611078565b8382146106c45760405162461bcd60e51b81526004018080602001828103825260298152602001806119c86029913960400191505060405180910390fd5b8360005b8181101561079b5761070a8787838181106106df57fe5b6001600160a01b038c81166000908152603660209081526040909120949202909101351690506110d5565b61075b576040805162461bcd60e51b815260206004820181905260248201527f6d696e746572206973206e6f742074686520746f6b656e2773206d696e746572604482015290519081900360640190fd5b6107938888888481811061076b57fe5b905060200201356001600160a01b031687878581811061078757fe5b905060200201356110f1565b6001016106c8565b5050505050505050565b6060603460006107b482611195565b90508067ffffffffffffffff811180156107cd57600080fd5b506040519080825280602002602001820160405280156107f7578160200160208202803683370190505b50925060005b8181101561083b5761080f83826111a0565b84828151811061081b57fe5b6001600160a01b03909216602092830291909101909101526001016107fd565b50505090565b60005461010090046001600160a01b0316331461088f5760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b610898856111ac565b6108a58585858585611240565b5050505050565b82336108b782611078565b6001600160a01b03821660009081526036602052604090206108d990826110d5565b6109145760405162461bcd60e51b815260040180806020018281038252602c815260200180611905602c913960400191505060405180910390fd5b610920853386866112ec565b846001600160a01b03166340c10f1985856040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561097757600080fd5b505af115801561098b573d6000803e3d6000fd5b505050505050505050565b60005461010090046001600160a01b031633146109e45760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b6001600160a01b03811615801590610a0a57506001546001600160a01b03828116911614155b610a455760405162461bcd60e51b815260040180806020018281038252604b8152602001806118ba604b913960600191505060405180910390fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b6000610aa46034836110d5565b92915050565b60005460ff1615610aec5760405162461bcd60e51b815260040180806020018281038252602e815260200180611953602e913960400191505060405180910390fd5b610af46113cb565b6000805460ff19166001179055565b60008082610b1081611078565b6001600160a01b03841660009081526037602052604090206001810154815411610b4d5780546001820154600091610b489190611413565b610b60565b60018101548154610b5d91611413565b60005b935093505050915091565b60005461010090046001600160a01b03163314610bb95760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b81610bc381611078565b6000610bce84610b03565b50905082811015610c26576040805162461bcd60e51b815260206004820181905260248201527f546f6b656e20646f206e6f74206861766520656e6f7567682072657365727665604482015290519081900360640190fd5b6001600160a01b038416600090815260376020526040902060010154610c4c9084611455565b6001600160a01b0380861660008181526037602052604080822060010194909455805484516340c10f1960e01b8152610100909104909316600484015260248301879052925190926340c10f19926044808201939182900301818387803b158015610cb657600080fd5b505af1158015610cca573d6000803e3d6000fd5b50506000547fbb3007a1d7ecb62ce86e6c72f7b9d6a1455956365b1120e2f24f8d6ea69e56f0925061010090046001600160a01b03169050858584610d0f8183611413565b604080516001600160a01b039687168152949095166020850152838501929092526060830152608082015290519081900360a00190a150505050565b60005461010090046001600160a01b031681565b6037602052600090815260409020805460019091015482565b603860209081526000928352604080842090915290825290205481565b60005461010090046001600160a01b03163314610de35760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b84610ded81611078565b610dfa8686868686611240565b505050505050565b6001600160a01b0381166000908152603660205260408120606091610e2682611195565b90508067ffffffffffffffff81118015610e3f57600080fd5b50604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50925060005b81811015610ead57610e8183826111a0565b848281518110610e8d57fe5b6001600160a01b0390921660209283029190910190910152600101610e6f565b505050919050565b6001546001600160a01b031681565b600190565b6001546001600160a01b03163314610f125760405162461bcd60e51b81526004018080602001828103825260258152602001806119a36025913960400191505060405180910390fd5b60008054600180546001600160a01b03818116610100818102610100600160a81b03198716178088556001600160a01b031990941690945560405194849004821695909493909204169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b60005461010090046001600160a01b0316331461100e5760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b8261101881611078565b8160005b81811015610dfa576110498686868481811061103457fe5b905060200201356001600160a01b03166114af565b6110708686868481811061105957fe5b905060200201356001600160a01b031660006110f1565b60010161101c565b61108181610a97565b6110d2576040805162461bcd60e51b815260206004820152601e60248201527f746f6b656e206973206e6f7420612076616c6964204d534420746f6b656e0000604482015290519081900360640190fd5b50565b60006110ea836001600160a01b03841661157b565b9392505050565b6001600160a01b0380841660009081526038602090815260408083209386168352929052205481811461118f576001600160a01b0380851660008181526038602090815260408083209488168084529482529182902086905581519283528201929092528082018390526060810184905290517f1e3f360c914ab8be8439fdda7a6e955753721d1bcb60a6b206d6678e6fd5b8e39181900360800190a15b50505050565b6000610aa482611593565b60006110ea8383611597565b6001600160a01b0381166111f15760405162461bcd60e51b81526004018080602001828103825260228152602001806119316022913960400191505060405180910390fd5b6111fc6034826115fb565b156110d257604080516001600160a01b038316815290517fcb1a9e6e24c5ee692ea7080e45f4c71c5cc2a6f1bcea90b6b291651ed0facdde9181900360200190a150565b82811461127e5760405162461bcd60e51b81526004018080602001828103825260298152602001806119c86029913960400191505060405180910390fd5b8260005b818110156112e3576112af8787878481811061129a57fe5b905060200201356001600160a01b0316611610565b6112db878787848181106112bf57fe5b905060200201356001600160a01b031686868581811061078757fe5b600101611282565b50505050505050565b6001600160a01b038085166000908152603860209081526040808320938716808452938252808320548151632cd3b8ad60e11b815291519094936359a7715a93600480850194919392918390030190829087803b15801561134c57600080fd5b505af1158015611360573d6000803e3d6000fd5b505050506040513d602081101561137657600080fd5b5051111561118f576040805162461bcd60e51b815260206004820152601c60248201527f4d696e746572206d696e74206361706163697479207265616368656400000000604482015290519081900360640190fd5b60008054610100600160a81b0319163361010081029190911782556040519091907f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b2364908290a3565b60006110ea83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506116db565b6000828201838110156110ea576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03811661150a576040805162461bcd60e51b815260206004820152601f60248201527f6d696e7465722063616e6e6f742062652061207a65726f206164647265737300604482015290519081900360640190fd5b6001600160a01b038216600090815260366020526040902061152c9082611772565b1561157757604080516001600160a01b0380851682528316602082015281517f4b5ef9a786cf64a7d82ebcf2d5132667edc9faef4ac36260d9a9e52c526b6232929181900390910190a15b5050565b60009081526001919091016020526040902054151590565b5490565b815460009082106115d95760405162461bcd60e51b81526004018080602001828103825260228152602001806118986022913960400191505060405180910390fd5b8260000182815481106115e857fe5b9060005260206000200154905092915050565b60006110ea836001600160a01b038416611787565b6001600160a01b03811661166b576040805162461bcd60e51b815260206004820152601f60248201527f6d696e7465722063616e6e6f742062652061207a65726f206164647265737300604482015290519081900360640190fd5b6001600160a01b038216600090815260366020526040902061168d90826115fb565b1561157757604080516001600160a01b0380851682528316602082015281517f3c091dafb1d99e4a4c333024492eac3b2cd8bf921a3dd547c937db33be307bb8929181900390910190a15050565b6000818484111561176a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561172f578181015183820152602001611717565b50505050905090810190601f16801561175c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60006110ea836001600160a01b0384166117d1565b6000611793838361157b565b6117c957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610aa4565b506000610aa4565b6000818152600183016020526040812054801561188d578354600019808301919081019060009087908390811061180457fe5b906000526020600020015490508087600001848154811061182157fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061185157fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610aa4565b6000915050610aa456fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64735f73657450656e64696e674f776e65723a204e6577206f77656e722063616e206e6f74206265207a65726f206164647265737320616e64206f776e657220686173206265656e20736574216f6e6c794d696e7465723a2063616c6c6572206973206e6f742074686520746f6b656e2773206d696e7465724d534420746f6b656e2063616e6e6f742062652061207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65646f6e6c794f776e65723a2063616c6c6572206973206e6f7420746865206f776e65725f6163636570744f776e65723a204f6e6c7920666f722070656e64696e67206f776e6572214c656e677468206f66205f6d696e7465727320616e64205f6d696e7443617073206d69736d61746368a2646970667358221220c55c5eb71f824ddf9dc75b921743c0aa725bf200379b3ad2b2c32fbe5fb9346d64736f6c634300060c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101165760003560e01c80638da5cb5b116100a2578063d2de243411610071578063d2de243414610572578063e30c397814610598578063fb43d68d146105a0578063fc4d33f9146105a8578063fc662774146105b057610116565b80638da5cb5b1461041a578063b1e1436f1461043e578063b5add45c14610464578063bfeb5c1c146104a457610116565b80636e96dfd7116100e95780636e96dfd7146103475780637431fc381461036d5780638129fc1c146103a757806386c975e0146103af5780638af225ae146103ee57610116565b8063014db0011461011b578063494c6e88146101eb57806352be45af146102435780636e839b0b14610311575b600080fd5b6101e96004803603606081101561013157600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561015b57600080fd5b82018360208201111561016d57600080fd5b803590602001918460208302840111600160201b8311171561018e57600080fd5b919390929091602081019035600160201b8111156101ab57600080fd5b8201836020820111156101bd57600080fd5b803590602001918460208302840111600160201b831117156101de57600080fd5b50909250905061062e565b005b6101f36107a5565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561022f578181015183820152602001610217565b505050509050019250505060405180910390f35b6101e96004803603606081101561025957600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561028357600080fd5b82018360208201111561029557600080fd5b803590602001918460208302840111600160201b831117156102b657600080fd5b919390929091602081019035600160201b8111156102d357600080fd5b8201836020820111156102e557600080fd5b803590602001918460208302840111600160201b8311171561030657600080fd5b509092509050610841565b6101e96004803603606081101561032757600080fd5b506001600160a01b038135811691602081013590911690604001356108ac565b6101e96004803603602081101561035d57600080fd5b50356001600160a01b0316610996565b6103936004803603602081101561038357600080fd5b50356001600160a01b0316610a97565b604080519115158252519081900360200190f35b6101e9610aaa565b6103d5600480360360208110156103c557600080fd5b50356001600160a01b0316610b03565b6040805192835260208301919091528051918290030190f35b6101e96004803603604081101561040457600080fd5b506001600160a01b038135169060200135610b6b565b610422610d4b565b604080516001600160a01b039092168252519081900360200190f35b6103d56004803603602081101561045457600080fd5b50356001600160a01b0316610d5f565b6104926004803603604081101561047a57600080fd5b506001600160a01b0381358116916020013516610d78565b60408051918252519081900360200190f35b6101e9600480360360608110156104ba57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156104e457600080fd5b8201836020820111156104f657600080fd5b803590602001918460208302840111600160201b8311171561051757600080fd5b919390929091602081019035600160201b81111561053457600080fd5b82018360208201111561054657600080fd5b803590602001918460208302840111600160201b8311171561056757600080fd5b509092509050610d95565b6101f36004803603602081101561058857600080fd5b50356001600160a01b0316610e02565b610422610eb5565b610393610ec4565b6101e9610ec9565b6101e9600480360360408110156105c657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105f057600080fd5b82018360208201111561060257600080fd5b803590602001918460208302840111600160201b8311171561062357600080fd5b509092509050610fc0565b60005461010090046001600160a01b0316331461067c5760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b8461068681611078565b8382146106c45760405162461bcd60e51b81526004018080602001828103825260298152602001806119c86029913960400191505060405180910390fd5b8360005b8181101561079b5761070a8787838181106106df57fe5b6001600160a01b038c81166000908152603660209081526040909120949202909101351690506110d5565b61075b576040805162461bcd60e51b815260206004820181905260248201527f6d696e746572206973206e6f742074686520746f6b656e2773206d696e746572604482015290519081900360640190fd5b6107938888888481811061076b57fe5b905060200201356001600160a01b031687878581811061078757fe5b905060200201356110f1565b6001016106c8565b5050505050505050565b6060603460006107b482611195565b90508067ffffffffffffffff811180156107cd57600080fd5b506040519080825280602002602001820160405280156107f7578160200160208202803683370190505b50925060005b8181101561083b5761080f83826111a0565b84828151811061081b57fe5b6001600160a01b03909216602092830291909101909101526001016107fd565b50505090565b60005461010090046001600160a01b0316331461088f5760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b610898856111ac565b6108a58585858585611240565b5050505050565b82336108b782611078565b6001600160a01b03821660009081526036602052604090206108d990826110d5565b6109145760405162461bcd60e51b815260040180806020018281038252602c815260200180611905602c913960400191505060405180910390fd5b610920853386866112ec565b846001600160a01b03166340c10f1985856040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561097757600080fd5b505af115801561098b573d6000803e3d6000fd5b505050505050505050565b60005461010090046001600160a01b031633146109e45760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b6001600160a01b03811615801590610a0a57506001546001600160a01b03828116911614155b610a455760405162461bcd60e51b815260040180806020018281038252604b8152602001806118ba604b913960600191505060405180910390fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b6000610aa46034836110d5565b92915050565b60005460ff1615610aec5760405162461bcd60e51b815260040180806020018281038252602e815260200180611953602e913960400191505060405180910390fd5b610af46113cb565b6000805460ff19166001179055565b60008082610b1081611078565b6001600160a01b03841660009081526037602052604090206001810154815411610b4d5780546001820154600091610b489190611413565b610b60565b60018101548154610b5d91611413565b60005b935093505050915091565b60005461010090046001600160a01b03163314610bb95760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b81610bc381611078565b6000610bce84610b03565b50905082811015610c26576040805162461bcd60e51b815260206004820181905260248201527f546f6b656e20646f206e6f74206861766520656e6f7567682072657365727665604482015290519081900360640190fd5b6001600160a01b038416600090815260376020526040902060010154610c4c9084611455565b6001600160a01b0380861660008181526037602052604080822060010194909455805484516340c10f1960e01b8152610100909104909316600484015260248301879052925190926340c10f19926044808201939182900301818387803b158015610cb657600080fd5b505af1158015610cca573d6000803e3d6000fd5b50506000547fbb3007a1d7ecb62ce86e6c72f7b9d6a1455956365b1120e2f24f8d6ea69e56f0925061010090046001600160a01b03169050858584610d0f8183611413565b604080516001600160a01b039687168152949095166020850152838501929092526060830152608082015290519081900360a00190a150505050565b60005461010090046001600160a01b031681565b6037602052600090815260409020805460019091015482565b603860209081526000928352604080842090915290825290205481565b60005461010090046001600160a01b03163314610de35760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b84610ded81611078565b610dfa8686868686611240565b505050505050565b6001600160a01b0381166000908152603660205260408120606091610e2682611195565b90508067ffffffffffffffff81118015610e3f57600080fd5b50604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50925060005b81811015610ead57610e8183826111a0565b848281518110610e8d57fe5b6001600160a01b0390921660209283029190910190910152600101610e6f565b505050919050565b6001546001600160a01b031681565b600190565b6001546001600160a01b03163314610f125760405162461bcd60e51b81526004018080602001828103825260258152602001806119a36025913960400191505060405180910390fd5b60008054600180546001600160a01b03818116610100818102610100600160a81b03198716178088556001600160a01b031990941690945560405194849004821695909493909204169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b60005461010090046001600160a01b0316331461100e5760405162461bcd60e51b81526004018080602001828103825260228152602001806119816022913960400191505060405180910390fd5b8261101881611078565b8160005b81811015610dfa576110498686868481811061103457fe5b905060200201356001600160a01b03166114af565b6110708686868481811061105957fe5b905060200201356001600160a01b031660006110f1565b60010161101c565b61108181610a97565b6110d2576040805162461bcd60e51b815260206004820152601e60248201527f746f6b656e206973206e6f7420612076616c6964204d534420746f6b656e0000604482015290519081900360640190fd5b50565b60006110ea836001600160a01b03841661157b565b9392505050565b6001600160a01b0380841660009081526038602090815260408083209386168352929052205481811461118f576001600160a01b0380851660008181526038602090815260408083209488168084529482529182902086905581519283528201929092528082018390526060810184905290517f1e3f360c914ab8be8439fdda7a6e955753721d1bcb60a6b206d6678e6fd5b8e39181900360800190a15b50505050565b6000610aa482611593565b60006110ea8383611597565b6001600160a01b0381166111f15760405162461bcd60e51b81526004018080602001828103825260228152602001806119316022913960400191505060405180910390fd5b6111fc6034826115fb565b156110d257604080516001600160a01b038316815290517fcb1a9e6e24c5ee692ea7080e45f4c71c5cc2a6f1bcea90b6b291651ed0facdde9181900360200190a150565b82811461127e5760405162461bcd60e51b81526004018080602001828103825260298152602001806119c86029913960400191505060405180910390fd5b8260005b818110156112e3576112af8787878481811061129a57fe5b905060200201356001600160a01b0316611610565b6112db878787848181106112bf57fe5b905060200201356001600160a01b031686868581811061078757fe5b600101611282565b50505050505050565b6001600160a01b038085166000908152603860209081526040808320938716808452938252808320548151632cd3b8ad60e11b815291519094936359a7715a93600480850194919392918390030190829087803b15801561134c57600080fd5b505af1158015611360573d6000803e3d6000fd5b505050506040513d602081101561137657600080fd5b5051111561118f576040805162461bcd60e51b815260206004820152601c60248201527f4d696e746572206d696e74206361706163697479207265616368656400000000604482015290519081900360640190fd5b60008054610100600160a81b0319163361010081029190911782556040519091907f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b2364908290a3565b60006110ea83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506116db565b6000828201838110156110ea576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03811661150a576040805162461bcd60e51b815260206004820152601f60248201527f6d696e7465722063616e6e6f742062652061207a65726f206164647265737300604482015290519081900360640190fd5b6001600160a01b038216600090815260366020526040902061152c9082611772565b1561157757604080516001600160a01b0380851682528316602082015281517f4b5ef9a786cf64a7d82ebcf2d5132667edc9faef4ac36260d9a9e52c526b6232929181900390910190a15b5050565b60009081526001919091016020526040902054151590565b5490565b815460009082106115d95760405162461bcd60e51b81526004018080602001828103825260228152602001806118986022913960400191505060405180910390fd5b8260000182815481106115e857fe5b9060005260206000200154905092915050565b60006110ea836001600160a01b038416611787565b6001600160a01b03811661166b576040805162461bcd60e51b815260206004820152601f60248201527f6d696e7465722063616e6e6f742062652061207a65726f206164647265737300604482015290519081900360640190fd5b6001600160a01b038216600090815260366020526040902061168d90826115fb565b1561157757604080516001600160a01b0380851682528316602082015281517f3c091dafb1d99e4a4c333024492eac3b2cd8bf921a3dd547c937db33be307bb8929181900390910190a15050565b6000818484111561176a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561172f578181015183820152602001611717565b50505050905090810190601f16801561175c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60006110ea836001600160a01b0384166117d1565b6000611793838361157b565b6117c957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610aa4565b506000610aa4565b6000818152600183016020526040812054801561188d578354600019808301919081019060009087908390811061180457fe5b906000526020600020015490508087600001848154811061182157fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061185157fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610aa4565b6000915050610aa456fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64735f73657450656e64696e674f776e65723a204e6577206f77656e722063616e206e6f74206265207a65726f206164647265737320616e64206f776e657220686173206265656e20736574216f6e6c794d696e7465723a2063616c6c6572206973206e6f742074686520746f6b656e2773206d696e7465724d534420746f6b656e2063616e6e6f742062652061207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65646f6e6c794f776e65723a2063616c6c6572206973206e6f7420746865206f776e65725f6163636570744f776e65723a204f6e6c7920666f722070656e64696e67206f776e6572214c656e677468206f66205f6d696e7465727320616e64205f6d696e7443617073206d69736d61746368a2646970667358221220c55c5eb71f824ddf9dc75b921743c0aa725bf200379b3ad2b2c32fbe5fb9346d64736f6c634300060c0033
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.