diff --git a/abis/oracle.ts b/abis/oracle.ts index 264517081..b240d30f9 100644 --- a/abis/oracle.ts +++ b/abis/oracle.ts @@ -1,3 +1,14 @@ +/** `governor()` getter from euler-price-oracle's Governable (EulerRouter). */ +export const governableGovernorAbi = [ + { + type: 'function', + name: 'governor', + inputs: [], + outputs: [{ name: 'governor', type: 'address' }], + stateMutability: 'view', + }, +] as const + export const priceOracleAbi = [ { type: 'function', diff --git a/abis/safe.ts b/abis/safe.ts new file mode 100644 index 000000000..7aaec779c --- /dev/null +++ b/abis/safe.ts @@ -0,0 +1,33 @@ +/** + * Minimal fragments for probing Safe (ex Gnosis Safe) smart accounts. + * + * `masterCopy()` is not a regular function on the Safe singleton — Safe proxy + * contracts (v1.1.1+) special-case the `0xa619486e` selector in their fallback + * and return the singleton address stored at slot 0 without delegating. An + * `eth_call` against any Safe proxy therefore answers it, while EOAs return + * empty data and non-Safe contracts revert or return garbage that fails + * decoding. + */ +export const safeAccountAbi = [ + { + type: 'function', + name: 'masterCopy', + inputs: [], + outputs: [{ name: 'masterCopy', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + name: 'getThreshold', + inputs: [], + outputs: [{ name: 'threshold', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + name: 'getOwners', + inputs: [], + outputs: [{ name: 'owners', type: 'address[]' }], + stateMutability: 'view', + }, +] as const diff --git a/assets/sprite/svg/safe.svg b/assets/sprite/svg/safe.svg new file mode 100644 index 000000000..c0dd53f94 --- /dev/null +++ b/assets/sprite/svg/safe.svg @@ -0,0 +1 @@ + diff --git a/components/entities/safe/SafeAccountBadge.vue b/components/entities/safe/SafeAccountBadge.vue new file mode 100644 index 000000000..4bd600176 --- /dev/null +++ b/components/entities/safe/SafeAccountBadge.vue @@ -0,0 +1,36 @@ + + + diff --git a/components/entities/vault/overview/SecuritizeVaultOverview.vue b/components/entities/vault/overview/SecuritizeVaultOverview.vue index 5febee351..8b4df7d51 100644 --- a/components/entities/vault/overview/SecuritizeVaultOverview.vue +++ b/components/entities/vault/overview/SecuritizeVaultOverview.vue @@ -5,10 +5,8 @@ import { getProductByVault, getProductKeyByVault, isVaultGovernanceLimited } fro import { getEulerLabelEntityLogo } from '~/entities/euler/labels' import { isVaultBlockedByCountry } from '~/composables/useGeoBlock' import { autoLink } from '~/utils/autoLink' -import { getExplorerLink } from '~/utils/block-explorer' -import { getSpecialAddressLabel } from '~/utils/special-addresses' import { formatAssetValue } from '~/utils/sdk-prices' -import { formatNumber, compactNumber, formatUsdValue, formatCompactUsdValue, shortenAddress } from '~/utils/string-utils' +import { formatNumber, compactNumber, formatUsdValue, formatCompactUsdValue } from '~/utils/string-utils' import { nanoToValue } from '~/utils/crypto-utils' import { formatMarketAvailability } from '~/utils/vault-display' import { VaultApyModal } from '#components' @@ -23,7 +21,6 @@ const emit = defineEmits<{ const route = useRoute() const { enableEntityBranding: enableEntityBrandingDisplay, enableVaultType: enableVaultTypeDisplay } = useDeployConfig() -const { chainId } = useEulerAddresses() const { borrowList: _borrowList, isVaultGovernorVerified } = useVaults() const { settings } = useUserSettings() const enableIntrinsicApy = computed(() => settings.value.enableIntrinsicApy) @@ -45,14 +42,6 @@ const isDeprecated = computed(() => { const deprecationReason = computed(() => isDeprecated.value ? product.deprecationReason || '' : '') const isRestricted = computed(() => isVaultBlockedByCountry(vault.address)) -const { copyToClipboard } = useClipboardCopy() - -const onCopyClick = (address: string) => { - copyToClipboard(address).catch(() => {}) -} - -const getExplorerAddressLink = (address: string) => getExplorerLink(address, chainId.value, true) - // Count markets where this can be borrowed (securitize vaults cannot be borrow destinations) const borrowCount = computed(() => 0) @@ -330,71 +319,23 @@ const supplyCapPercentageDisplay = computed(() => { :label="`${vault.asset.symbol} token`" orientation="horizontal" > -
- - {{ getSpecialAddressLabel(vault.asset.address) || shortenAddress(vault.asset.address) }} - - -
+ -
- - {{ getSpecialAddressLabel(vault.address) || shortenAddress(vault.address) }} - - -
+
-
- - {{ getSpecialAddressLabel(vault.governor) || shortenAddress(vault.governor) }} - - -
+
diff --git a/components/entities/vault/overview/VaultOverviewAddressValue.vue b/components/entities/vault/overview/VaultOverviewAddressValue.vue new file mode 100644 index 000000000..a4afe7e09 --- /dev/null +++ b/components/entities/vault/overview/VaultOverviewAddressValue.vue @@ -0,0 +1,50 @@ + + + diff --git a/components/entities/vault/overview/VaultOverviewBlockAddresses.vue b/components/entities/vault/overview/VaultOverviewBlockAddresses.vue index db98148f5..e014ca6db 100644 --- a/components/entities/vault/overview/VaultOverviewBlockAddresses.vue +++ b/components/entities/vault/overview/VaultOverviewBlockAddresses.vue @@ -1,15 +1,10 @@ -
- - {{ getSpecialAddressLabel(infoItem.address) || shortenAddress(infoItem.address) }} - - -
+ diff --git a/components/entities/vault/overview/earn/VaultOverviewEarnBlockAddresses.vue b/components/entities/vault/overview/earn/VaultOverviewEarnBlockAddresses.vue index be700b9f7..af0d531de 100644 --- a/components/entities/vault/overview/earn/VaultOverviewEarnBlockAddresses.vue +++ b/components/entities/vault/overview/earn/VaultOverviewEarnBlockAddresses.vue @@ -1,11 +1,7 @@ diff --git a/components/entities/vault/overview/earn/VaultOverviewEarnBlockManagement.vue b/components/entities/vault/overview/earn/VaultOverviewEarnBlockManagement.vue index 07bc1a585..2e58b4cad 100644 --- a/components/entities/vault/overview/earn/VaultOverviewEarnBlockManagement.vue +++ b/components/entities/vault/overview/earn/VaultOverviewEarnBlockManagement.vue @@ -1,12 +1,8 @@