Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 91 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Collect And Vali... | 16990001 | 981 days ago | IN | 0 ETH | 0.01720078 | ||||
| Collect And Vali... | 16989989 | 981 days ago | IN | 0 ETH | 0.02030041 | ||||
| Collect And Vali... | 16989923 | 981 days ago | IN | 0 ETH | 0.02225742 | ||||
| Collect And Vali... | 16431409 | 1060 days ago | IN | 0 ETH | 0.01099419 | ||||
| Collect And Vali... | 15728090 | 1158 days ago | IN | 0 ETH | 0.0135329 | ||||
| Collect And Vali... | 15677978 | 1165 days ago | IN | 0 ETH | 0.00947303 | ||||
| Collect And Vali... | 15627898 | 1172 days ago | IN | 0 ETH | 0.00608989 | ||||
| Collect And Vali... | 15577902 | 1179 days ago | IN | 0 ETH | 0.00811998 | ||||
| Collect And Vali... | 15529666 | 1186 days ago | IN | 0 ETH | 0.0074432 | ||||
| Collect And Vali... | 15486891 | 1193 days ago | IN | 0 ETH | 0.01230426 | ||||
| Collect And Vali... | 15443168 | 1200 days ago | IN | 0 ETH | 0.01025425 | ||||
| Collect And Vali... | 15399470 | 1207 days ago | IN | 0 ETH | 0.01786384 | ||||
| Collect And Vali... | 15355225 | 1214 days ago | IN | 0 ETH | 0.01572493 | ||||
| Collect And Vali... | 15310858 | 1221 days ago | IN | 0 ETH | 0.01435671 | ||||
| Collect And Vali... | 15265993 | 1228 days ago | IN | 0 ETH | 0.00683613 | ||||
| Collect And Vali... | 15221001 | 1235 days ago | IN | 0 ETH | 0.01572355 | ||||
| Collect And Vali... | 15175983 | 1242 days ago | IN | 0 ETH | 0.02461078 | ||||
| Collect And Vali... | 15130773 | 1249 days ago | IN | 0 ETH | 0.01167979 | ||||
| Collect And Vali... | 15085425 | 1256 days ago | IN | 0 ETH | 0.03691726 | ||||
| Collect And Vali... | 15042113 | 1263 days ago | IN | 0 ETH | 0.0246115 | ||||
| Collect And Vali... | 15004706 | 1270 days ago | IN | 0 ETH | 0.02119293 | ||||
| Collect And Vali... | 14964380 | 1277 days ago | IN | 0 ETH | 0.02404769 | ||||
| Collect And Vali... | 14923501 | 1284 days ago | IN | 0 ETH | 0.02939535 | ||||
| Collect And Vali... | 14881494 | 1291 days ago | IN | 0 ETH | 0.03572852 | ||||
| Collect And Vali... | 14838481 | 1298 days ago | IN | 0 ETH | 0.04534906 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
InterestValidator
Compiler Version
v0.8.2+commit.661d1103
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-04-07
*/
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.2;
struct BassetPersonal {
// Address of the bAsset
address addr;
// Address of the bAsset
address integrator;
// An ERC20 can charge transfer fee, for example USDT, DGX tokens.
bool hasTxFee; // takes a byte in storage
// Status of the bAsset
BassetStatus status;
}
struct BassetData {
// 1 Basset * ratio / ratioScale == x Masset (relative value)
// If ratio == 10e8 then 1 bAsset = 10 mAssets
// A ratio is divised as 10^(18-tokenDecimals) * measurementMultiple(relative value of 1 base unit)
uint128 ratio;
// Amount of the Basset that is held in Collateral
uint128 vaultBalance;
}
// Status of the Basset - has it broken its peg?
enum BassetStatus {
Default,
Normal,
BrokenBelowPeg,
BrokenAbovePeg,
Blacklisted,
Liquidating,
Liquidated,
Failed
}
struct BasketState {
bool undergoingRecol;
bool failed;
}
struct InvariantConfig {
uint256 a;
WeightLimits limits;
}
struct WeightLimits {
uint128 min;
uint128 max;
}
struct FeederConfig {
uint256 supply;
uint256 a;
WeightLimits limits;
}
struct AmpData {
uint64 initialA;
uint64 targetA;
uint64 rampStartTime;
uint64 rampEndTime;
}
struct FeederData {
uint256 swapFee;
uint256 redemptionFee;
uint256 govFee;
uint256 pendingFees;
uint256 cacheSize;
BassetPersonal[] bAssetPersonal;
BassetData[] bAssetData;
AmpData ampData;
WeightLimits weightLimits;
}
struct AssetData {
uint8 idx;
uint256 amt;
BassetPersonal personal;
}
struct Asset {
uint8 idx;
address addr;
bool exists;
}
abstract contract IFeederPool {
// Mint
function mint(
address _input,
uint256 _inputQuantity,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 mintOutput);
function mintMulti(
address[] calldata _inputs,
uint256[] calldata _inputQuantities,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 mintOutput);
function getMintOutput(address _input, uint256 _inputQuantity)
external
view
virtual
returns (uint256 mintOutput);
function getMintMultiOutput(address[] calldata _inputs, uint256[] calldata _inputQuantities)
external
view
virtual
returns (uint256 mintOutput);
// Swaps
function swap(
address _input,
address _output,
uint256 _inputQuantity,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 swapOutput);
function getSwapOutput(
address _input,
address _output,
uint256 _inputQuantity
) external view virtual returns (uint256 swapOutput);
// Redemption
function redeem(
address _output,
uint256 _fpTokenQuantity,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 outputQuantity);
function redeemProportionately(
uint256 _fpTokenQuantity,
uint256[] calldata _minOutputQuantities,
address _recipient
) external virtual returns (uint256[] memory outputQuantities);
function redeemExactBassets(
address[] calldata _outputs,
uint256[] calldata _outputQuantities,
uint256 _maxMassetQuantity,
address _recipient
) external virtual returns (uint256 mAssetRedeemed);
function getRedeemOutput(address _output, uint256 _fpTokenQuantity)
external
view
virtual
returns (uint256 bAssetOutput);
function getRedeemExactBassetsOutput(
address[] calldata _outputs,
uint256[] calldata _outputQuantities
) external view virtual returns (uint256 mAssetAmount);
// Views
function mAsset() external view virtual returns (address);
function getPrice() public view virtual returns (uint256 price, uint256 k);
function getConfig() external view virtual returns (FeederConfig memory config);
function getBasset(address _token)
external
view
virtual
returns (BassetPersonal memory personal, BassetData memory data);
function getBassets()
external
view
virtual
returns (BassetPersonal[] memory personal, BassetData[] memory data);
// SavingsManager
function collectPlatformInterest()
external
virtual
returns (uint256 mintAmount, uint256 newSupply);
function collectPendingFees() external virtual;
}
contract ModuleKeys {
// Governance
// ===========
// keccak256("Governance");
bytes32 internal constant KEY_GOVERNANCE =
0x9409903de1e6fd852dfc61c9dacb48196c48535b60e25abf92acc92dd689078d;
//keccak256("Staking");
bytes32 internal constant KEY_STAKING =
0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034;
//keccak256("ProxyAdmin");
bytes32 internal constant KEY_PROXY_ADMIN =
0x96ed0203eb7e975a4cbcaa23951943fa35c5d8288117d50c12b3d48b0fab48d1;
// mStable
// =======
// keccak256("OracleHub");
bytes32 internal constant KEY_ORACLE_HUB =
0x8ae3a082c61a7379e2280f3356a5131507d9829d222d853bfa7c9fe1200dd040;
// keccak256("Manager");
bytes32 internal constant KEY_MANAGER =
0x6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f;
//keccak256("Recollateraliser");
bytes32 internal constant KEY_RECOLLATERALISER =
0x39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f;
//keccak256("MetaToken");
bytes32 internal constant KEY_META_TOKEN =
0xea7469b14936af748ee93c53b2fe510b9928edbdccac3963321efca7eb1a57a2;
// keccak256("SavingsManager");
bytes32 internal constant KEY_SAVINGS_MANAGER =
0x12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf1;
// keccak256("Liquidator");
bytes32 internal constant KEY_LIQUIDATOR =
0x1e9cb14d7560734a61fa5ff9273953e971ff3cd9283c03d8346e3264617933d4;
// keccak256("InterestValidator");
bytes32 internal constant KEY_INTEREST_VALIDATOR =
0xc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f;
}
interface INexus {
function governor() external view returns (address);
function getModule(bytes32 key) external view returns (address);
function proposeModule(bytes32 _key, address _addr) external;
function cancelProposedModule(bytes32 _key) external;
function acceptProposedModule(bytes32 _key) external;
function acceptProposedModules(bytes32[] calldata _keys) external;
function requestLockModule(bytes32 _key) external;
function cancelLockModule(bytes32 _key) external;
function lockModule(bytes32 _key) external;
}
abstract contract ImmutableModule is ModuleKeys {
INexus public immutable nexus;
/**
* @dev Initialization function for upgradable proxy contracts
* @param _nexus Nexus contract address
*/
constructor(address _nexus) {
require(_nexus != address(0), "Nexus address is zero");
nexus = INexus(_nexus);
}
/**
* @dev Modifier to allow function calls only from the Governor.
*/
modifier onlyGovernor() {
_onlyGovernor();
_;
}
function _onlyGovernor() internal view {
require(msg.sender == _governor(), "Only governor can execute");
}
/**
* @dev Modifier to allow function calls only from the Governance.
* Governance is either Governor address or Governance address.
*/
modifier onlyGovernance() {
require(
msg.sender == _governor() || msg.sender == _governance(),
"Only governance can execute"
);
_;
}
/**
* @dev Modifier to allow function calls only from the ProxyAdmin.
*/
modifier onlyProxyAdmin() {
require(msg.sender == _proxyAdmin(), "Only ProxyAdmin can execute");
_;
}
/**
* @dev Modifier to allow function calls only from the Manager.
*/
modifier onlyManager() {
require(msg.sender == _manager(), "Only manager can execute");
_;
}
/**
* @dev Returns Governor address from the Nexus
* @return Address of Governor Contract
*/
function _governor() internal view returns (address) {
return nexus.governor();
}
/**
* @dev Returns Governance Module address from the Nexus
* @return Address of the Governance (Phase 2)
*/
function _governance() internal view returns (address) {
return nexus.getModule(KEY_GOVERNANCE);
}
/**
* @dev Return Staking Module address from the Nexus
* @return Address of the Staking Module contract
*/
function _staking() internal view returns (address) {
return nexus.getModule(KEY_STAKING);
}
/**
* @dev Return ProxyAdmin Module address from the Nexus
* @return Address of the ProxyAdmin Module contract
*/
function _proxyAdmin() internal view returns (address) {
return nexus.getModule(KEY_PROXY_ADMIN);
}
/**
* @dev Return MetaToken Module address from the Nexus
* @return Address of the MetaToken Module contract
*/
function _metaToken() internal view returns (address) {
return nexus.getModule(KEY_META_TOKEN);
}
/**
* @dev Return OracleHub Module address from the Nexus
* @return Address of the OracleHub Module contract
*/
function _oracleHub() internal view returns (address) {
return nexus.getModule(KEY_ORACLE_HUB);
}
/**
* @dev Return Manager Module address from the Nexus
* @return Address of the Manager Module contract
*/
function _manager() internal view returns (address) {
return nexus.getModule(KEY_MANAGER);
}
/**
* @dev Return SavingsManager Module address from the Nexus
* @return Address of the SavingsManager Module contract
*/
function _savingsManager() internal view returns (address) {
return nexus.getModule(KEY_SAVINGS_MANAGER);
}
/**
* @dev Return Recollateraliser Module address from the Nexus
* @return Address of the Recollateraliser Module contract (Phase 2)
*/
function _recollateraliser() internal view returns (address) {
return nexus.getModule(KEY_RECOLLATERALISER);
}
}
abstract contract PausableModule is ImmutableModule {
/**
* @dev Emitted when the pause is triggered by Governor
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by Governor
*/
event Unpaused(address account);
bool internal _paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!_paused, "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(_paused, "Pausable: not paused");
_;
}
/**
* @dev Initializes the contract in unpaused state.
* Hooks into the Module to give the Governor ability to pause
* @param _nexus Nexus contract address
*/
constructor(address _nexus) ImmutableModule(_nexus) {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
* @return Returns `true` when paused, otherwise `false`
*/
function paused() external view returns (bool) {
return _paused;
}
/**
* @dev Called by the Governor to pause, triggers stopped state.
*/
function pause() external onlyGovernor whenNotPaused {
_paused = true;
emit Paused(msg.sender);
}
/**
* @dev Called by Governor to unpause, returns to normal state.
*/
function unpause() external onlyGovernor whenPaused {
_paused = false;
emit Unpaused(msg.sender);
}
}
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @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 Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
/**
* @title InterestValidator
* @author mStable
* @notice Simply validates the platform interest collection from the Feeder Pools. Normally this function
* is supported by the SavingsManager, which then distributes the inflated tokens to SAVE contracts.
* However, given that fPools collect value internally, we simply want to provide protections here
* without actually inflating supply. As such, this code is forked from `savings/SavingsManager.sol`.
* @dev VERSION: 1.0
* DATE: 2021-03-01
*/
contract InterestValidator is PausableModule {
event InterestCollected(
address indexed feederPool,
uint256 interest,
uint256 newTotalSupply,
uint256 apy
);
event GovFeeCollected(address indexed feederPool, address mAsset, uint256 amount);
// Utils to help keep interest under check
uint256 private constant SECONDS_IN_YEAR = 365 days;
// Theoretical cap on APY to avoid excess inflation
uint256 private constant MAX_APY = 15e18;
mapping(address => uint256) public lastBatchCollected;
constructor(address _nexus) PausableModule(_nexus) {}
/**
* @notice Collects and validates the interest of n feeder pools.
* @dev First calls to calculate the interest that has accrued, and then validates the potential inflation
* with respect to the previous timestamp.
* @param _fPools Addresses of the feeder pools on which to accrue interest
*/
function collectAndValidateInterest(address[] calldata _fPools) external whenNotPaused {
uint256 currentTime = block.timestamp;
uint256 len = _fPools.length;
for (uint256 i = 0; i < len; i++) {
address feeder = _fPools[i];
uint256 previousBatch = lastBatchCollected[feeder];
uint256 timeSincePreviousBatch = currentTime - previousBatch;
require(timeSincePreviousBatch > 12 hours, "Cannot collect twice in 12 hours");
lastBatchCollected[feeder] = currentTime;
// Batch collect
(uint256 interestCollected, uint256 totalSupply) =
IFeederPool(feeder).collectPlatformInterest();
if (interestCollected > 0) {
// Validate APY
uint256 apy =
_validateCollection(totalSupply, interestCollected, timeSincePreviousBatch);
emit InterestCollected(feeder, interestCollected, totalSupply, apy);
} else {
emit InterestCollected(feeder, interestCollected, totalSupply, 0);
}
}
}
/**
* @dev Collects gov fees from fPools in the form of fPtoken, then converts to
* mAsset and sends directly to the SavingsManager, where it will be picked up and
* converted to mBPT upon the next collection
*/
function collectGovFees(address[] calldata _fPools) external onlyGovernor {
uint256 len = _fPools.length;
address savingsManager = _savingsManager();
for (uint256 i = 0; i < len; i++) {
address fPool = _fPools[i];
// 1. Collect pending fees
IFeederPool(fPool).collectPendingFees();
uint256 fpTokenBal = IERC20(fPool).balanceOf(address(this));
// 2. If fpTokenBal > 0, convert to mAsset and transfer to savingsManager
if (fpTokenBal > 0) {
address mAsset = IFeederPool(fPool).mAsset();
uint256 outputAmt =
IFeederPool(fPool).redeem(mAsset, fpTokenBal, (fpTokenBal * 7) / 10, savingsManager);
emit GovFeeCollected(fPool, mAsset, outputAmt);
}
}
}
/**
* @dev Validates that an interest collection does not exceed a maximum APY. If last collection
* was under 30 mins ago, simply check it does not exceed 10bps
* @param _newSupply New total supply of the mAsset
* @param _interest Increase in total supply since last collection
* @param _timeSinceLastCollection Seconds since last collection
*/
function _validateCollection(
uint256 _newSupply,
uint256 _interest,
uint256 _timeSinceLastCollection
) internal pure returns (uint256 extrapolatedAPY) {
// Percentage increase in total supply
// e.g. (1e20 * 1e18) / 1e24 = 1e14 (or a 0.01% increase)
// e.g. (5e18 * 1e18) / 1.2e24 = 4.1667e12
// e.g. (1e19 * 1e18) / 1e21 = 1e16
uint256 oldSupply = _newSupply - _interest;
uint256 percentageIncrease = (_interest * 1e18) / oldSupply;
// If over 30 mins, extrapolate APY
// e.g. day: (86400 * 1e18) / 3.154e7 = 2.74..e15
// e.g. 30 mins: (1800 * 1e18) / 3.154e7 = 5.7..e13
// e.g. epoch: (1593596907 * 1e18) / 3.154e7 = 50.4..e18
uint256 yearsSinceLastCollection = (_timeSinceLastCollection * 1e18) / SECONDS_IN_YEAR;
// e.g. 0.01% (1e14 * 1e18) / 2.74..e15 = 3.65e16 or 3.65% apr
// e.g. (4.1667e12 * 1e18) / 5.7..e13 = 7.1e16 or 7.1% apr
// e.g. (1e16 * 1e18) / 50e18 = 2e14
extrapolatedAPY = (percentageIncrease * 1e18) / yearsSinceLastCollection;
require(extrapolatedAPY < MAX_APY, "Interest protected from inflating past maxAPY");
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_nexus","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feederPool","type":"address"},{"indexed":false,"internalType":"address","name":"mAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"GovFeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feederPool","type":"address"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"apy","type":"uint256"}],"name":"InterestCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address[]","name":"_fPools","type":"address[]"}],"name":"collectAndValidateInterest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_fPools","type":"address[]"}],"name":"collectGovFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastBatchCollected","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nexus","outputs":[{"internalType":"contract INexus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a06040526000805460ff1916905534801561001a57600080fd5b50604051610cc2380380610cc2833981016040819052610039916100b6565b80806001600160a01b0381166100955760405162461bcd60e51b815260206004820152601560248201527f4e657875732061646472657373206973207a65726f0000000000000000000000604482015260640160405180910390fd5b60601b6001600160601b03191660805250506000805460ff191690556100e4565b6000602082840312156100c7578081fd5b81516001600160a01b03811681146100dd578182fd5b9392505050565b60805160601c610bb361010f6000396000818160f501528181610828015261099e0152610bb36000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80635c975abb1161005b5780635c975abb146100d25780638456cb59146100e8578063a3f5c1d2146100f0578063a600f0dd1461012f5761007d565b80631cf743271461008257806333bda1f7146100975780633f4ba83a146100ca575b600080fd5b610095610090366004610a34565b610142565b005b6100b76100a53660046109f5565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b610095610406565b60005460ff1660405190151581526020016100c1565b61009561049c565b6101177f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100c1565b61009561013d366004610a34565b610527565b61014a610786565b8060006101556107f0565b905060005b828110156103ff57600085858381811061018457634e487b7160e01b600052603260045260246000fd5b905060200201602081019061019991906109f5565b9050806001600160a01b03166398fec3af6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156101d657600080fd5b505af11580156101ea573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b03841691506370a082319060240160206040518083038186803b15801561023057600080fd5b505afa158015610244573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102689190610aa3565b905080156103ea576000826001600160a01b031663178d341f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ab57600080fd5b505afa1580156102bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e39190610a18565b905060006001600160a01b0384166343bcfab68385600a610305826007610afe565b61030f9190610ade565b6040516001600160e01b031960e086901b1681526001600160a01b039384166004820152602481019290925260448201529089166064820152608401602060405180830381600087803b15801561036557600080fd5b505af1158015610379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039d9190610aa3565b604080516001600160a01b03858116825260208201849052929350918616917f24b98558c8051808230c888e96f8352b78e39de78fc2300c4e922c9b48e9d176910160405180910390a250505b505080806103f790610b34565b91505061015a565b5050505050565b61040e610786565b60005460ff1661045c5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064015b60405180910390fd5b6000805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6104a4610786565b60005460ff16156104ea5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610453565b6000805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610492565b60005460ff161561056d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610453565b428160005b818110156103ff57600085858381811061059c57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906105b191906109f5565b6001600160a01b0381166000908152600160205260408120549192506105d78287610b1d565b905061a8c0811161062a5760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f7420636f6c6c65637420747769636520696e20313220686f7572736044820152606401610453565b6001600160a01b0383166000818152600160205260408082208990558051633f4480f560e11b81528151929384939092637e8901ea926004808201939182900301818787803b15801561067c57600080fd5b505af1158015610690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b49190610abb565b909250905081156107215760006106cc8284866108af565b60408051858152602081018590529081018290529091506001600160a01b038716907f0abcfa9ece819bcdcfa052a818ce11f0b9fad8b3e3ccd98f120c40be689b690f9060600160405180910390a25061076e565b604080518381526020810183905260008183015290516001600160a01b038716917f0abcfa9ece819bcdcfa052a818ce11f0b9fad8b3e3ccd98f120c40be689b690f919081900360600190a25b5050505050808061077e90610b34565b915050610572565b61078e61099a565b6001600160a01b0316336001600160a01b0316146107ee5760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e2065786563757465000000000000006044820152606401610453565b565b6040516385acd64160e01b81527f12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf160048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906385acd6419060240160206040518083038186803b15801561087257600080fd5b505afa158015610886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108aa9190610a18565b905090565b6000806108bc8486610b1d565b90506000816108d386670de0b6b3a7640000610afe565b6108dd9190610ade565b905060006301e133806108f886670de0b6b3a7640000610afe565b6109029190610ade565b90508061091783670de0b6b3a7640000610afe565b6109219190610ade565b935067d02ab486cedc000084106109905760405162461bcd60e51b815260206004820152602d60248201527f496e7465726573742070726f7465637465642066726f6d20696e666c6174696e60448201526c672070617374206d617841505960981b6064820152608401610453565b5050509392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b15801561087257600080fd5b600060208284031215610a06578081fd5b8135610a1181610b65565b9392505050565b600060208284031215610a29578081fd5b8151610a1181610b65565b60008060208385031215610a46578081fd5b823567ffffffffffffffff80821115610a5d578283fd5b818501915085601f830112610a70578283fd5b813581811115610a7e578384fd5b8660208083028501011115610a91578384fd5b60209290920196919550909350505050565b600060208284031215610ab4578081fd5b5051919050565b60008060408385031215610acd578182fd5b505080516020909101519092909150565b600082610af957634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615610b1857610b18610b4f565b500290565b600082821015610b2f57610b2f610b4f565b500390565b6000600019821415610b4857610b48610b4f565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114610b7a57600080fd5b5056fea2646970667358221220436abad8c082d58d56e17d4d951ac6f414c37a712373bfa60a2bceea83a23fbd64736f6c63430008020033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80635c975abb1161005b5780635c975abb146100d25780638456cb59146100e8578063a3f5c1d2146100f0578063a600f0dd1461012f5761007d565b80631cf743271461008257806333bda1f7146100975780633f4ba83a146100ca575b600080fd5b610095610090366004610a34565b610142565b005b6100b76100a53660046109f5565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b610095610406565b60005460ff1660405190151581526020016100c1565b61009561049c565b6101177f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b6040516001600160a01b0390911681526020016100c1565b61009561013d366004610a34565b610527565b61014a610786565b8060006101556107f0565b905060005b828110156103ff57600085858381811061018457634e487b7160e01b600052603260045260246000fd5b905060200201602081019061019991906109f5565b9050806001600160a01b03166398fec3af6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156101d657600080fd5b505af11580156101ea573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b03841691506370a082319060240160206040518083038186803b15801561023057600080fd5b505afa158015610244573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102689190610aa3565b905080156103ea576000826001600160a01b031663178d341f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ab57600080fd5b505afa1580156102bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e39190610a18565b905060006001600160a01b0384166343bcfab68385600a610305826007610afe565b61030f9190610ade565b6040516001600160e01b031960e086901b1681526001600160a01b039384166004820152602481019290925260448201529089166064820152608401602060405180830381600087803b15801561036557600080fd5b505af1158015610379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039d9190610aa3565b604080516001600160a01b03858116825260208201849052929350918616917f24b98558c8051808230c888e96f8352b78e39de78fc2300c4e922c9b48e9d176910160405180910390a250505b505080806103f790610b34565b91505061015a565b5050505050565b61040e610786565b60005460ff1661045c5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064015b60405180910390fd5b6000805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6104a4610786565b60005460ff16156104ea5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610453565b6000805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610492565b60005460ff161561056d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610453565b428160005b818110156103ff57600085858381811061059c57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906105b191906109f5565b6001600160a01b0381166000908152600160205260408120549192506105d78287610b1d565b905061a8c0811161062a5760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f7420636f6c6c65637420747769636520696e20313220686f7572736044820152606401610453565b6001600160a01b0383166000818152600160205260408082208990558051633f4480f560e11b81528151929384939092637e8901ea926004808201939182900301818787803b15801561067c57600080fd5b505af1158015610690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b49190610abb565b909250905081156107215760006106cc8284866108af565b60408051858152602081018590529081018290529091506001600160a01b038716907f0abcfa9ece819bcdcfa052a818ce11f0b9fad8b3e3ccd98f120c40be689b690f9060600160405180910390a25061076e565b604080518381526020810183905260008183015290516001600160a01b038716917f0abcfa9ece819bcdcfa052a818ce11f0b9fad8b3e3ccd98f120c40be689b690f919081900360600190a25b5050505050808061077e90610b34565b915050610572565b61078e61099a565b6001600160a01b0316336001600160a01b0316146107ee5760405162461bcd60e51b815260206004820152601960248201527f4f6e6c7920676f7665726e6f722063616e2065786563757465000000000000006044820152606401610453565b565b6040516385acd64160e01b81527f12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf160048201526000907f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316906385acd6419060240160206040518083038186803b15801561087257600080fd5b505afa158015610886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108aa9190610a18565b905090565b6000806108bc8486610b1d565b90506000816108d386670de0b6b3a7640000610afe565b6108dd9190610ade565b905060006301e133806108f886670de0b6b3a7640000610afe565b6109029190610ade565b90508061091783670de0b6b3a7640000610afe565b6109219190610ade565b935067d02ab486cedc000084106109905760405162461bcd60e51b815260206004820152602d60248201527f496e7465726573742070726f7465637465642066726f6d20696e666c6174696e60448201526c672070617374206d617841505960981b6064820152608401610453565b5050509392505050565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b15801561087257600080fd5b600060208284031215610a06578081fd5b8135610a1181610b65565b9392505050565b600060208284031215610a29578081fd5b8151610a1181610b65565b60008060208385031215610a46578081fd5b823567ffffffffffffffff80821115610a5d578283fd5b818501915085601f830112610a70578283fd5b813581811115610a7e578384fd5b8660208083028501011115610a91578384fd5b60209290920196919550909350505050565b600060208284031215610ab4578081fd5b5051919050565b60008060408385031215610acd578182fd5b505080516020909101519092909150565b600082610af957634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615610b1857610b18610b4f565b500290565b600082821015610b2f57610b2f610b4f565b500390565b6000600019821415610b4857610b48610b4f565b5060010190565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114610b7a57600080fd5b5056fea2646970667358221220436abad8c082d58d56e17d4d951ac6f414c37a712373bfa60a2bceea83a23fbd64736f6c63430008020033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
-----Decoded View---------------
Arg [0] : _nexus (address): 0xAFcE80b19A8cE13DEc0739a1aaB7A028d6845Eb3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3
Deployed Bytecode Sourcemap
26996:4871:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29361:850;;;;;;:::i;:::-;;:::i;:::-;;27506:53;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2949:25:1;;;2937:2;2922:18;27506:53:0;;;;;;;;12465:122;;;:::i;12074:80::-;12115:4;12139:7;;;12074:80;;2776:14:1;;2769:22;2751:41;;2739:2;2724:18;12074:80:0;2706:92:1;12250:120:0;;;:::i;7206:29::-;;;;;;;;-1:-1:-1;;;;;1836:32:1;;;1818:51;;1806:2;1791:18;7206:29:0;1773:102:1;27963:1149:0;;;;;;:::i;:::-;;:::i;29361:850::-;7640:15;:13;:15::i;:::-;29460:7;29446:11:::1;29512:17;:15;:17::i;:::-;29487:42;;29545:9;29540:664;29564:3;29560:1;:7;29540:664;;;29589:13;29605:7;;29613:1;29605:10;;;;;-1:-1:-1::0;;;29605:10:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29589:26;;29682:5;-1:-1:-1::0;;;;;29670:37:0::1;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;29745:38:0::1;::::0;-1:-1:-1;;;29745:38:0;;29777:4:::1;29745:38;::::0;::::1;1818:51:1::0;29724:18:0::1;::::0;-1:-1:-1;;;;;;29745:23:0;::::1;::::0;-1:-1:-1;29745:23:0::1;::::0;1791:18:1;;29745:38:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29724:59:::0;-1:-1:-1;29889:14:0;;29885:308:::1;;29924:14;29953:5;-1:-1:-1::0;;;;;29941:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29924:44:::0;-1:-1:-1;29987:17:0::1;-1:-1:-1::0;;;;;30028:25:0;::::1;;29924:44:::0;30062:10;30093:2:::1;30075:14;30062:10:::0;30088:1:::1;30075:14;:::i;:::-;30074:21;;;;:::i;:::-;30028:84;::::0;-1:-1:-1;;;;;;30028:84:0::1;::::0;;;;;;-1:-1:-1;;;;;2446:15:1;;;30028:84:0::1;::::0;::::1;2428:34:1::0;2478:18;;;2471:34;;;;2521:18;;;2514:34;2584:15;;;2564:18;;;2557:43;2362:19;;30028:84:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30136:41;::::0;;-1:-1:-1;;;;;2072:32:1;;;2054:51;;2136:2;2121:18;;2114:34;;;29987:125:0;;-1:-1:-1;30136:41:0;;::::1;::::0;::::1;::::0;2027:18:1;30136:41:0::1;;;;;;;29885:308;;;29540:664;;29569:3;;;;;:::i;:::-;;;;29540:664;;;;7666:1;;29361:850:::0;;:::o;12465:122::-;7640:15;:13;:15::i;:::-;11578:7:::1;::::0;::::1;;11570:40;;;::::0;-1:-1:-1;;;11570:40:0;;3409:2:1;11570:40:0::1;::::0;::::1;3391:21:1::0;3448:2;3428:18;;;3421:30;-1:-1:-1;;;3467:18:1;;;3460:50;3527:18;;11570:40:0::1;;;;;;;;;12538:5:::2;12528:15:::0;;-1:-1:-1;;12528:15:0::2;::::0;;12559:20:::2;::::0;12568:10:::2;1818:51:1::0;;12559:20:0::2;::::0;1806:2:1;1791:18;12559:20:0::2;;;;;;;;12465:122::o:0;12250:120::-;7640:15;:13;:15::i;:::-;11379:7:::1;::::0;::::1;;11378:8;11370:37;;;::::0;-1:-1:-1;;;11370:37:0;;4473:2:1;11370:37:0::1;::::0;::::1;4455:21:1::0;4512:2;4492:18;;;4485:30;-1:-1:-1;;;4531:18:1;;;4524:46;4587:18;;11370:37:0::1;4445:166:1::0;11370:37:0::1;12314:7:::2;:14:::0;;-1:-1:-1;;12314:14:0::2;12324:4;12314:14;::::0;;12344:18:::2;::::0;12351:10:::2;1818:51:1::0;;12344:18:0::2;::::0;1806:2:1;1791:18;12344::0::2;1773:102:1::0;27963:1149:0;11379:7;;;;11378:8;11370:37;;;;-1:-1:-1;;;11370:37:0;;4473:2:1;11370:37:0;;;4455:21:1;4512:2;4492:18;;;4485:30;-1:-1:-1;;;4531:18:1;;;4524:46;4587:18;;11370:37:0;4445:166:1;11370:37:0;28083:15:::1;28125:7:::0;28061:19:::1;28152:953;28176:3;28172:1;:7;28152:953;;;28201:14;28218:7;;28226:1;28218:10;;;;;-1:-1:-1::0;;;28218:10:0::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;28269:26:0;::::1;28245:21;28269:26:::0;;;:18:::1;:26;::::0;;;;;28201:27;;-1:-1:-1;28343:27:0::1;28269:26:::0;28343:11;:27:::1;:::i;:::-;28310:60;;28418:8;28393:22;:33;28385:78;;;::::0;-1:-1:-1;;;28385:78:0;;3758:2:1;28385:78:0::1;::::0;::::1;3740:21:1::0;;;3777:18;;;3770:30;3836:34;3816:18;;;3809:62;3888:18;;28385:78:0::1;3730:182:1::0;28385:78:0::1;-1:-1:-1::0;;;;;28478:26:0;::::1;;::::0;;;:18:::1;:26;::::0;;;;;:40;;;28633:45;;-1:-1:-1;;;28633:45:0;;;;28478:26;;;;;;28633:43:::1;::::0;:45:::1;::::0;;::::1;::::0;;;;;;;28478:26;;28633:45;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28565:113:::0;;-1:-1:-1;28565:113:0;-1:-1:-1;28699:21:0;;28695:399:::1;;28774:11;28809:75;28829:11;28842:17;28861:22;28809:19;:75::i;:::-;28910:62;::::0;;5422:25:1;;;5478:2;5463:18;;5456:34;;;5506:18;;;5499:34;;;28774:110:0;;-1:-1:-1;;;;;;28910:62:0;::::1;::::0;::::1;::::0;5410:2:1;5395:18;28910:62:0::1;;;;;;;28695:399;;;;29018:60;::::0;;5422:25:1;;;5478:2;5463:18;;5456:34;;;-1:-1:-1;5506:18:1;;;5499:34;29018:60:0;;-1:-1:-1;;;;;29018:60:0;::::1;::::0;::::1;::::0;;;;;5410:2:1;29018:60:0;;::::1;28695:399;28152:953;;;;;28181:3;;;;;:::i;:::-;;;;28152:953;;7683:121:::0;7755:11;:9;:11::i;:::-;-1:-1:-1;;;;;7741:25:0;:10;-1:-1:-1;;;;;7741:25:0;;7733:63;;;;-1:-1:-1;;;7733:63:0;;4119:2:1;7733:63:0;;;4101:21:1;4158:2;4138:18;;;4131:30;4197:27;4177:18;;;4170:55;4242:18;;7733:63:0;4091:175:1;7733:63:0;7683:121::o;10478:::-;10555:36;;-1:-1:-1;;;10555:36:0;;6160:66;10555:36;;;2949:25:1;10528:7:0;;10555:5;-1:-1:-1;;;;;10555:15:0;;;;2922:18:1;;10555:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10548:43;;10478:121;:::o;30635:1229::-;30794:23;;31062:22;31075:9;31062:10;:22;:::i;:::-;31042:42;-1:-1:-1;31095:26:0;31042:42;31125:16;:9;31137:4;31125:16;:::i;:::-;31124:30;;;;:::i;:::-;31095:59;-1:-1:-1;31403:32:0;27385:8;31439:31;:24;31466:4;31439:31;:::i;:::-;31438:51;;;;:::i;:::-;31403:86;-1:-1:-1;31403:86:0;31707:25;:18;31728:4;31707:25;:::i;:::-;31706:54;;;;:::i;:::-;31688:72;;27492:5;31781:15;:25;31773:83;;;;-1:-1:-1;;;31773:83:0;;4818:2:1;31773:83:0;;;4800:21:1;4857:2;4837:18;;;4830:30;4896:34;4876:18;;;4869:62;-1:-1:-1;;;4947:18:1;;;4940:43;5000:19;;31773:83:0;4790:235:1;31773:83:0;30635:1229;;;;;;;;:::o;8722:95::-;8766:7;8793:5;-1:-1:-1;;;;;8793:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:257:1;;126:2;114:9;105:7;101:23;97:32;94:2;;;147:6;139;132:22;94:2;191:9;178:23;210:31;235:5;210:31;:::i;:::-;260:5;84:187;-1:-1:-1;;;84:187:1:o;276:261::-;;399:2;387:9;378:7;374:23;370:32;367:2;;;420:6;412;405:22;367:2;457:9;451:16;476:31;501:5;476:31;:::i;542:666::-;;;689:2;677:9;668:7;664:23;660:32;657:2;;;710:6;702;695:22;657:2;755:9;742:23;784:18;825:2;817:6;814:14;811:2;;;846:6;838;831:22;811:2;889:6;878:9;874:22;864:32;;934:7;927:4;923:2;919:13;915:27;905:2;;961:6;953;946:22;905:2;1006;993:16;1032:2;1024:6;1021:14;1018:2;;;1053:6;1045;1038:22;1018:2;1112:7;1107:2;1101;1093:6;1089:15;1085:2;1081:24;1077:33;1074:46;1071:2;;;1138:6;1130;1123:22;1071:2;1174;1166:11;;;;;1196:6;;-1:-1:-1;647:561:1;;-1:-1:-1;;;;647:561:1:o;1213:194::-;;1336:2;1324:9;1315:7;1311:23;1307:32;1304:2;;;1357:6;1349;1342:22;1304:2;-1:-1:-1;1385:16:1;;1294:113;-1:-1:-1;1294:113:1:o;1412:255::-;;;1552:2;1540:9;1531:7;1527:23;1523:32;1520:2;;;1573:6;1565;1558:22;1520:2;-1:-1:-1;;1601:16:1;;1657:2;1642:18;;;1636:25;1601:16;;1636:25;;-1:-1:-1;1510:157:1:o;5868:217::-;;5934:1;5924:2;;-1:-1:-1;;;5959:31:1;;6013:4;6010:1;6003:15;6041:4;5966:1;6031:15;5924:2;-1:-1:-1;6070:9:1;;5914:171::o;6090:168::-;;6196:1;6192;6188:6;6184:14;6181:1;6178:21;6173:1;6166:9;6159:17;6155:45;6152:2;;;6203:18;;:::i;:::-;-1:-1:-1;6243:9:1;;6142:116::o;6263:125::-;;6331:1;6328;6325:8;6322:2;;;6336:18;;:::i;:::-;-1:-1:-1;6373:9:1;;6312:76::o;6393:135::-;;-1:-1:-1;;6453:17:1;;6450:2;;;6473:18;;:::i;:::-;-1:-1:-1;6520:1:1;6509:13;;6440:88::o;6533:127::-;6594:10;6589:3;6585:20;6582:1;6575:31;6625:4;6622:1;6615:15;6649:4;6646:1;6639:15;6665:131;-1:-1:-1;;;;;6740:31:1;;6730:42;;6720:2;;6786:1;6783;6776:12;6720:2;6710:86;:::o
Swarm Source
ipfs://436abad8c082d58d56e17d4d951ac6f414c37a712373bfa60a2bceea83a23fbd
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.