Skip to content

Commit

Permalink
Merge branch 'main' into auction
Browse files Browse the repository at this point in the history
  • Loading branch information
conradocanasm0 committed Oct 15, 2024
2 parents 0a58c97 + 207ddb5 commit ffc88b1
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 95 deletions.
3 changes: 3 additions & 0 deletions assets/data/error-proposals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
"103700040478888763716057861639293706989913755085520977741041074598448586673404"
]
6 changes: 3 additions & 3 deletions components/layout/LayoutSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,10 @@ const mainMenuItems = computed(() => {
notification: amountLeftToAuction.value && isTransferEpoch.value,
},
{
title: "Protocol Fees",
path: "/fees/",
title: "Rewards",
path: "/rewards/",
isShow: isAuctionActive.value,
dataTest: "sidebar-link-fees",
dataTest: "sidebar-link-rewards",
},
{
title: "Wrap/Unwrap",
Expand Down
33 changes: 28 additions & 5 deletions components/proposal/Card.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
<template>
<div class="mb-4 bg-transparent">
<div
class="mb-4 bg-transparent"
:class="{ 'border border-red-500': isProposalWithError }"
>
<article
:data-test="hasVoted ? 'voted' : 'not-voted'"
class="text-white bg-grey-800 p-6 lg:p-8"
>
<div
v-if="isProposalWithError"
class="flex items-center gap-2 mb-2 bg-red-500 p-2 leading-tight"
>
<span class="-mb-1">CAUTION: Suspicious or wrong proposal</span>
<VTooltip placement="right">
<img src="/img/icon-info.svg" class="w-6 h-6" alt="" />
<template #popper>
<div class="max-w-80 text-sm">
This proposal has been labeled as suspicious or wrong by the M^0
Foundation. We recommend to vote <b>NO</b>.
</div>
</template>
</VTooltip>
</div>
<ProposalTypeBadge
v-if="proposal.votingType !== 'Standard' || proposal.state !== 'Active'"
:type="proposal.votingType"
class="mb-4"
/>

<div class="mb-4">
<h2 class="text-2xl break-all">
<div class="mb-4 text-xl lg:text-2xl break-words">
<h3>
{{ title }}
</h2>
</h3>
</div>

<div class="text-grey-500 font-inter mb-4 break-words">
<div class="text-grey-500 max-lg:text-sm font-inter mb-4 break-words">
{{ truncate(onlyDescription, { length: 450 }) }}
</div>

Expand Down Expand Up @@ -161,6 +179,7 @@ import { useAccount, useReadContract, useBlockNumber } from "use-wagmi";
import { Hash, Abi } from "viem";
import { useMVotingPower } from "@/lib/hooks";
import { MProposal } from "@/lib/api/types";
import errorProposals from "@/assets/data/error-proposals.json";
export interface ProposalCardProps {
proposal: MProposal;
Expand Down Expand Up @@ -198,6 +217,10 @@ watch(reasonForVote, (value) => {
emit("update-reason-for-vote", value, props.proposal.proposalId);
});
const isProposalWithError = computed(() => {
return errorProposals?.some((id) => id === props.proposal.proposalId);
});
const isVoteYesActive = computed(() => {
// vote has been casted to Yes
if (voteEvent && voteEvent.value?.support === true) return "active";
Expand Down
6 changes: 3 additions & 3 deletions components/proposal/InputDynamic.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<div
v-if="props.modelValueErrors?.length"
class="text-red-500 text-xs my-2 h-4"
class="text-red-500 text-xs my-2 h-4 font-inter"
>
<p v-for="error of props.modelValueErrors" :key="error.$uid">
{{ error.$message }}
Expand Down Expand Up @@ -68,8 +68,8 @@ const value = useVModelWrapper<InputProps>(props, emit, "modelValue");
const hasErrors = computed(() => props.modelValueErrors?.length);
</script>
<style>
<style scoped>
.error {
@apply border border-red-500;
@apply bg-transparent border border-red-500;
}
</style>
10 changes: 4 additions & 6 deletions components/proposal/InputProtocolConfigOperation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const inputs = {
penalty_rate: {
component: InputDynamic,
props: {
decorator: "%",
decorator: "BPS",
maska: masks.percentage,
},
},
Expand All @@ -77,7 +77,7 @@ const inputs = {
mint_ratio: {
component: InputDynamic,
props: {
decorator: "%",
decorator: "BPS",
maska: masks.percentage,
},
},
Expand All @@ -94,30 +94,28 @@ const inputs = {
component: InputDynamic,
props: {
decorator: "contract",
maska: masks.ethereumAddress,
},
},
earner_rate_model: {
component: InputDynamic,
props: {
decorator: "contract",
maska: masks.ethereumAddress,
},
},
base_minter_rate: {
component: InputDynamic,
props: {
decorator: "%",
decorator: "BPS",
maska: masks.percentage,
},
},
max_earner_rate: {
component: InputDynamic,
props: {
decorator: "%",
decorator: "BPS",
maska: masks.percentage,
},
},
Expand Down
2 changes: 1 addition & 1 deletion components/proposal/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</h2>
<div
class="text-grey-400 my-1 font-inter text-xs truncate w-52 lg:w-full"
class="text-grey-500 my-1 font-inter text-xs truncate w-52 lg:w-full"
>
Proposed by
<u><MAddressAvatar :address="proposal?.proposer" /></u>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe("Proposals", () => {
describe("type action: Emergency setKey", () => {
const value = "1";
const value = "60";
const key = "mint_delay";
const description = `Add config ${key} = ${value}`;
let proposalUrl = "";
Expand Down
1 change: 1 addition & 0 deletions cypress/e2e/basic/basic_governance_configuration.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ describe("Governance configuration", () => {
"Distribution Vault",
"Registrar",
"M Token",
"Smart $M",
]

// non-changeable parameters table
Expand Down
10 changes: 5 additions & 5 deletions lib/api/modules/governor/modules/proposal/proposals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import {
fromHex,
toFunctionSelector,
parseAbiItem,
trim,
} from "viem";

import pick from "lodash/pick";

import { GovernorModule } from "../GovernorModule";
import { GovernanceType } from "../../governor.types";
import {
Expand Down Expand Up @@ -142,8 +141,6 @@ export class Proposals extends GovernorModule {
removeSelectorFromCallData(calldata),
);

const key = hexWith32BytesToString(params[0]);

const decodeValue = (key: string, value: string) => {
if (["minter_rate_model", "earner_rate_model"].includes(key)) {
return hexWith32BytesToAddress(value as Hash);
Expand All @@ -156,7 +153,10 @@ export class Proposals extends GovernorModule {
return decodeAbiParameters([{ type: "uint256" }], value as Hash);
};

const value = decodeValue(key, params[1]);
const tempKey = hexWith32BytesToString(params[0]);
const isOtherKey = tempKey.includes("�");
const key = isOtherKey ? params[0] : tempKey;
const value = isOtherKey ? trim(params[1]) : decodeValue(key, params[1]);

return { proposalType, params: [key, value] };
}
Expand Down
2 changes: 1 addition & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default defineNuxtConfig({
"pages/delegate.vue",
]
: auctionActive === false
? ["pages/auction.vue", "pages/fees.vue"]
? ["pages/auction.vue", "pages/rewards.vue"]
: undefined, //no router is ignored
imports: {
dirs: ["./stores"],
Expand Down
10 changes: 10 additions & 0 deletions pages/config/governance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ const immutable = computed(() => {
key: "mToken",
value: getMToken().value,
},
{
key: "smartMContract",
value: useNetworkStore().getNetwork().value.contracts.wrappedMToken,
},
];
});
Expand Down Expand Up @@ -188,6 +192,12 @@ const inmutableParametersData = [
description:
"$M is a fungible token that can be generated by a Minter by locking Eligible Collateral in a secure off-chain facility.",
},
{
title: "Smart $M",
key: "smartMContract",
description:
"Our next-gen wrapper contract for the $M cryptodollar. This wrapper maintains a 1:1 rate with $M and offers integrators unprecedented control over yield in DeFi protocols.",
},
{
title: "Distribution Vault",
key: "vault",
Expand Down
80 changes: 56 additions & 24 deletions pages/proposal/create.vue
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,15 @@ import {
writeContract,
readContract,
} from "@wagmi/core";
import { encodeFunctionData, encodeAbiParameters, Hash, erc20Abi } from "viem";
import {
encodeFunctionData,
encodeAbiParameters,
Hash,
erc20Abi,
isAddress,
} from "viem";
import { useAccount } from "use-wagmi";
import { required, minLength, maxLength, url } from "@vuelidate/validators";
import { required, minLength, url, helpers } from "@vuelidate/validators";
import { useVuelidate } from "@vuelidate/core";
import { storeToRefs } from "pinia";
Expand Down Expand Up @@ -271,6 +277,21 @@ const formData = reactive({
discussionURL: null,
});
const validations = {
address: helpers.withMessage(
"Address is not valid",
(value: string) => isAddress(value) || !value,
),
range: (min: number, max: number) =>
helpers.withMessage(
`Invalid value, acceptable range is ${min}-${max}`,
(value: string) => {
const numberValue = Number(value);
return numberValue >= min && numberValue <= max;
},
),
};
const rules = computed(() => {
const constRules = {
description: { required, minLength: minLength(6) },
Expand All @@ -286,8 +307,7 @@ const rules = computed(() => {
proposalValue: { required },
proposalValue2: {
required,
minLength: minLength(42),
maxLength: maxLength(42),
addressValidation: validations.address,
},
proposalValue3: {},
...constRules,
Expand All @@ -299,22 +319,21 @@ const rules = computed(() => {
proposalValue: { required },
proposalValue2: {
required,
minLength: minLength(42),
maxLength: maxLength(42),
addressValidation: validations.address,
},
proposalValue3: {
required,
minLength: minLength(42),
maxLength: maxLength(42),
addressValidation: validations.address,
},
...constRules,
};
}
if (["setKey"].includes(type)) {
const selectedKey = formData.proposalValue || "";
return {
proposalValue: { required },
proposalValue2: { required },
proposalValue2: getKeyBasedValidation(selectedKey),
proposalValue3: {},
...constRules,
};
Expand All @@ -336,7 +355,7 @@ const rules = computed(() => {
].includes(type)
) {
return {
proposalValue: { required },
proposalValue: { required, range: validations.range(10, 100) },
proposalValue2: {},
proposalValue3: {},
...constRules,
Expand Down Expand Up @@ -854,20 +873,6 @@ function buildCalldatas(formData) {
return addressToHexWith32Bytes(inp);
}
if (
[
"penalty_rate",
"mint_ratio",
"base_minter_rate",
"max_earner_rate",
].includes(key)
) {
return encodeAbiParameters(
[{ type: "uint256" }],
[BigInt(percentageToBasispoints(inp))],
);
}
return encodeAbiParameters([{ type: "uint256" }], [BigInt(inp)]);
};
Expand Down Expand Up @@ -924,6 +929,33 @@ function buildCalldatasTtg(functionName: any, args: any) {
});
}
function getKeyBasedValidation(key: string) {
switch (key) {
case "minter_rate_model":
case "earner_rate_model":
return { required, address: validations.address };
case "base_minter_rate":
case "max_earner_rate":
return { required, range: validations.range(1, 5000) };
case "penalty_rate":
return { required, range: validations.range(1, 1000) };
case "update_collateral_interval":
return { required, range: validations.range(60, 31536000) }; // 1 minute to 1 year
case "update_collateral_threshold":
return { required, range: validations.range(1, 10) };
case "mint_delay":
return { required, range: validations.range(60, 86400) }; // 1 minute to 1 day
case "mint_ttl":
return { required, range: validations.range(3600, 864000) }; // 1 hour to 10 days
case "mint_ratio":
return { required, range: validations.range(50, 100) }; // Percent range
case "minter_freeze_time":
return { required, range: validations.range(3600, 2592000) }; // 1 hour to 1 month
default:
return { required };
}
}
function onBack() {
isPreview.value = false;
previewDescription.value = null;
Expand Down
Loading

0 comments on commit ffc88b1

Please sign in to comment.