Skip to content

Commit

Permalink
Andrei/agora 1650 tenant abstraction contracts factory (#155)
Browse files Browse the repository at this point in the history
* Tenant contracts

* dynamic tenant contract type

* WIP

* refactored contract defs

* moar refactoring

* Removed OptimismContracts

* leftover namespace

* Misc

* updated paths and minor cleanup

* Misc code review

* Code review and misc fixes

* prep for adding tenant types

* ns type

* Fixed voting delay

* Set voting period
  • Loading branch information
andreitr committed Mar 10, 2024
1 parent 1836bff commit a8ef0a2
Show file tree
Hide file tree
Showing 49 changed files with 395 additions and 442 deletions.
7 changes: 3 additions & 4 deletions src/app/api/common/authority-chains/getAuthorityChains.ts
@@ -1,9 +1,8 @@
import prisma from "@/app/lib/prisma";
import provider from "@/app/lib/provider";
import { contracts } from "@/lib/contracts/contracts";
import { AuthorityChainsSnaps } from "./authorityChains";
import { validateChain } from "@/lib/alligatorUtils";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export async function getAuthorityChains({
address,
Expand All @@ -12,7 +11,7 @@ export async function getAuthorityChains({
address: string;
blockNumber: number;
}): Promise<Array<string[]>> {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();
const chainsQuery = prisma.$queryRawUnsafe<AuthorityChainsSnaps[]>(
`
SELECT
Expand All @@ -39,7 +38,7 @@ export async function getAuthorityChains({
AND ac.allowance > 0;
`,
address.toLowerCase(),
contracts(namespace).alligator.address.toLowerCase(),
contracts.alligator!.address,
blockNumber
);

Expand Down
2 changes: 1 addition & 1 deletion src/app/api/common/citizens/getCitizens.ts
Expand Up @@ -4,7 +4,7 @@ import { paginatePrismaResult } from "@/app/lib/pagination";
import { Prisma } from "@prisma/client";
import prisma from "@/app/lib/prisma";
import { getDelegateStatement } from "../delegateStatement/getDelegateStatement";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

type citizen = {
address: string;
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/common/citizens/isCitizen.ts
@@ -1,6 +1,6 @@
import { Prisma } from "@prisma/client";
import prisma from "@/app/lib/prisma";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export async function isCitizen(address: string) {
const { slug } = Tenant.getInstance();
Expand Down
Expand Up @@ -4,7 +4,7 @@ import prisma from "@/app/lib/prisma";
import { DelegateStatementFormValues } from "@/components/DelegateStatement/CurrentDelegateStatement";
import { Prisma } from "@prisma/client";
import verifyMessage from "@/lib/serverVerifyMessage";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export async function createDelegateStatement({
address,
Expand Down
Expand Up @@ -3,7 +3,7 @@ import "server-only";
import prisma from "@/app/lib/prisma";
import { makeDynamoClient } from "@/app/lib/dynamodb";
import { addressOrEnsNameWrap } from "../utils/ensName";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export const getDelegateStatement = (addressOrENSName: string) =>
addressOrEnsNameWrap(getDelegateStatementForAddress, addressOrENSName);
Expand Down
9 changes: 4 additions & 5 deletions src/app/api/common/delegates/getDelegates.ts
Expand Up @@ -9,10 +9,9 @@ import {
import prisma from "@/app/lib/prisma";
import { isAddress } from "viem";
import { resolveENSName } from "@/app/lib/ENSUtils";
import { contracts } from "@/lib/contracts/contracts";
import { Delegate } from "./delegate";
import { isCitizen } from "../citizens/isCitizen";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";
import { getDelegateStatement } from "@/app/api/common/delegateStatement/getDelegateStatement";
import { getCurrentQuorum } from "@/app/api/common/quorum/getQuorum";

Expand Down Expand Up @@ -110,7 +109,7 @@ type DelegateStats = {
};

export async function getDelegate(addressOrENSName: string): Promise<Delegate> {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();
const address = isAddress(addressOrENSName)
? addressOrENSName.toLowerCase()
: await resolveENSName(addressOrENSName);
Expand Down Expand Up @@ -146,7 +145,7 @@ export async function getDelegate(addressOrENSName: string): Promise<Delegate> {
} vp WHERE vp.delegate = $1 LIMIT 1) c ON TRUE
`,
address,
contracts(namespace).alligator.address.toLowerCase()
contracts.alligator!.address
);

const [delegate, votableSupply, delegateStatement, quorum, _isCitizen] =
Expand Down Expand Up @@ -176,7 +175,7 @@ export async function getDelegate(addressOrENSName: string): Promise<Delegate> {
) t;
`,
address,
contracts(namespace).alligator.address.toLowerCase()
contracts.alligator!.address
);

const totalVotingPower =
Expand Down
16 changes: 8 additions & 8 deletions src/app/api/common/delegations/getDelegations.ts
Expand Up @@ -3,9 +3,8 @@ import { getHumanBlockTime } from "@/lib/blockTimes";
import prisma from "@/app/lib/prisma";
import provider from "@/app/lib/provider";
import { getProxyAddress } from "@/lib/alligatorUtils";
import { contracts } from "@/lib/contracts/contracts";
import { addressOrEnsNameWrap } from "../utils/ensName";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

/**
* Delegations for a given address (addresses the given address is delegating to)
Expand All @@ -19,15 +18,15 @@ async function getCurrentDelegateesForAddress({
}: {
address: string;
}): Promise<Delegation[]> {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();

const advancedDelegatees = await prisma[
`${namespace}AdvancedDelegatees`
].findMany({
where: {
from: address.toLowerCase(),
delegated_amount: { gt: 0 },
contract: contracts(namespace).alligator.address.toLowerCase(),
contract: contracts.alligator!.address,
},
});

Expand Down Expand Up @@ -129,12 +128,13 @@ async function getCurrentDelegatorsForAddress({
}: {
address: string;
}) {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();

const advancedDelegators = prisma[`${namespace}AdvancedDelegatees`].findMany({
where: {
to: address.toLowerCase(),
delegated_amount: { gt: 0 },
contract: contracts(namespace).alligator.address.toLowerCase(),
contract: contracts.alligator!.address,
},
});

Expand Down Expand Up @@ -251,15 +251,15 @@ async function getAllDelegatorsInChainsForAddress({
}: {
address: string;
}) {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();
const allAddresess = await prisma.$queryRawUnsafe<{ addresses: string[] }[]>(
`
SELECT array_agg(DISTINCT u.element) AS addresses
FROM ${namespace + ".authority_chains"}, unnest(chain) as u(element)
WHERE delegate=$1 AND contract=$2 AND allowance > 0;
`,
address,
contracts(namespace).alligator.address.toLowerCase()
contracts.alligator!.address
);

return allAddresess[0].addresses;
Expand Down
7 changes: 3 additions & 4 deletions src/app/api/common/metrics/getMetrics.ts
@@ -1,10 +1,9 @@
import prisma from "@/app/lib/prisma";
import { getTokenSupply } from "@/lib/tokenUtils";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export async function getMetrics() {
const { namespace } = Tenant.getInstance();
const totalSupply = await getTokenSupply(namespace);
const { namespace, contracts } = Tenant.getInstance();
const totalSupply = await contracts.token.contract.totalSupply();
const votableSupply = await prisma[`${namespace}VotableSupply`].findFirst({});
const quorum = (BigInt(Number(votableSupply?.votable_supply)) * 30n) / 100n;

Expand Down
7 changes: 3 additions & 4 deletions src/app/api/common/proposals/getNeedsMyVoteProposals.ts
@@ -1,14 +1,13 @@
import { parseProposal } from "@/lib/proposalUtils";
import prisma from "@/app/lib/prisma";
import provider from "@/app/lib/provider";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";
import { ProposalPayload } from "./proposal";
import { getVotableSupply } from "../votableSupply/getVotableSupply";
import { getQuorumForProposal } from "../quorum/getQuorum";
import { contracts } from "@/lib/contracts/contracts";

export async function getNeedsMyVoteProposals(address: string) {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();
const [latestBlock, votableSupply] = await Promise.all([
provider.getBlockNumber(),
getVotableSupply(),
Expand Down Expand Up @@ -40,7 +39,7 @@ export async function getNeedsMyVoteProposals(address: string) {
`,
latestBlock,
address.toLowerCase(),
contracts(namespace).governor.address.toLowerCase()
contracts.governor.address
);

const resolvedProposals = Promise.all(
Expand Down
12 changes: 5 additions & 7 deletions src/app/api/common/proposals/getProposals.ts
Expand Up @@ -5,8 +5,7 @@ import prisma from "@/app/lib/prisma";
import provider from "@/app/lib/provider";
import { getVotableSupply } from "../votableSupply/getVotableSupply";
import { getQuorumForProposal } from "../quorum/getQuorum";
import Tenant from "@/lib/tenant";
import { contracts } from "@/lib/contracts/contracts";
import Tenant from "@/lib/tenant/tenant";

export async function getProposals({
filter,
Expand All @@ -17,9 +16,9 @@ export async function getProposals({
}) {
const pageSize = 10;

const { namespace, isProd } = Tenant.getInstance();
const { namespace, contracts, isProd } = Tenant.getInstance();
const prodDataOnly = isProd && {
contract: contracts(namespace).governor.address.toLowerCase(),
contract: contracts.governor.address,
};

const { meta, data: proposals } = await paginatePrismaResult(
Expand Down Expand Up @@ -92,12 +91,11 @@ export async function getProposal(proposal_id: string) {
}

export async function getProposalTypes() {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();

return prisma[`${namespace}ProposalTypes`].findMany({
where: {
contract:
contracts(namespace).proposalTypesConfigurator.address.toLowerCase(),
contract: contracts.proposalTypesConfigurator!.address,
},
});
}
11 changes: 5 additions & 6 deletions src/app/api/common/quorum/getQuorum.ts
@@ -1,15 +1,14 @@
import provider from "@/app/lib/provider";
import prisma from "@/app/lib/prisma";
import { contracts } from "@/lib/contracts/contracts";
import { ProposalPayload } from "../proposals/proposal";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export async function getQuorumForProposal(proposal: ProposalPayload) {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();

switch (namespace) {
case "optimism": {
const contractQuorum = contracts(namespace).governor.contract.quorum(
const contractQuorum = contracts.governor.contract.quorum(
proposal.proposal_id
);

Expand All @@ -27,7 +26,7 @@ export async function getQuorumForProposal(proposal: ProposalPayload) {
}

export async function getCurrentQuorum() {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();

switch (namespace) {
case "optimism": {
Expand All @@ -36,7 +35,7 @@ export async function getCurrentQuorum() {
return null;
}
// latest - 1 because latest block might not be mined yet
return contracts(namespace).governor.contract.quorum(latestBlock - 1);
return contracts.governor.contract.quorum(latestBlock - 1);
}
}
}
2 changes: 1 addition & 1 deletion src/app/api/common/votableSupply/getVotableSupply.ts
@@ -1,5 +1,5 @@
import prisma from "@/app/lib/prisma";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export async function getVotableSupply() {
const { namespace } = Tenant.getInstance();
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/common/votes/getVotes.ts
Expand Up @@ -5,7 +5,7 @@ import { VotePayload, VotesSort } from "./vote";
import prisma from "@/app/lib/prisma";
import provider from "@/app/lib/provider";
import { addressOrEnsNameWrap } from "../utils/ensName";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

export const getVotesForDelegate = ({
addressOrENSName,
Expand Down
21 changes: 10 additions & 11 deletions src/app/api/common/voting-power/getVotingPower.ts
Expand Up @@ -3,11 +3,10 @@ import {
getProxyAddress,
getTotalVotableAllowance,
} from "@/lib/alligatorUtils";
import { contracts } from "@/lib/contracts/contracts";
import { addressOrEnsNameWrap } from "../utils/ensName";
import { VotingPowerData } from "./votingPower";
import { AuhtorityChainsAggregate } from "../authority-chains/authorityChains";
import Tenant from "@/lib/tenant";
import Tenant from "@/lib/tenant/tenant";

/**
* Voting Power for a given block
Expand Down Expand Up @@ -38,7 +37,7 @@ async function getVotingPowerForProposalByAddress({
blockNumber: number;
proposalId: string;
}): Promise<VotingPowerData> {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();

const votingPowerQuery = prisma[`${namespace}VotingPowerSnaps`].findFirst({
where: {
Expand Down Expand Up @@ -104,7 +103,7 @@ async function getVotingPowerForProposalByAddress({
WHERE allowance > 0;
`,
address,
contracts(namespace).alligator.address.toLowerCase(),
contracts.alligator!.address,
blockNumber
);

Expand Down Expand Up @@ -137,7 +136,7 @@ async function getCurrentVotingPowerForAddress({
}: {
address: string;
}): Promise<VotingPowerData> {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();
const votingPower = await prisma[`${namespace}VotingPower`].findFirst({
where: {
delegate: address,
Expand All @@ -150,7 +149,7 @@ async function getCurrentVotingPowerForAddress({
].findFirst({
where: {
delegate: address,
contract: contracts(namespace).alligator.address.toLowerCase(),
contract: contracts.alligator!.address,
},
});

Expand Down Expand Up @@ -181,20 +180,20 @@ async function getVotingPowerAvailableForSubdelegationForAddress({
}: {
address: string;
}): Promise<string> {
const { namespace } = Tenant.getInstance();
const { namespace, contracts } = Tenant.getInstance();
const advancedVotingPower = await prisma[
`${namespace}AdvancedVotingPower`
].findFirst({
where: {
delegate: address,
contract: contracts(namespace).alligator.address.toLowerCase(),
contract: contracts.alligator!.address,
},
});

const undelegatedVotingPower = (async () => {
const [isBalanceAccountedFor, balance] = await Promise.all([
isAddressDelegatingToProxy({ address }),
contracts(namespace).token.contract.balanceOf(address),
contracts.token.contract.balanceOf(address),
]);
return isBalanceAccountedFor ? 0n : balance;
})();
Expand Down Expand Up @@ -223,8 +222,8 @@ async function getVotingPowerAvailableForDirectDelegationForAddress({
}: {
address: string;
}): Promise<bigint> {
const { namespace } = Tenant.getInstance();
return contracts(namespace).token.contract.balanceOf(address); // TODO: update based on namespace
const { contracts } = Tenant.getInstance();
return contracts.token.contract.balanceOf(address);
}

/**
Expand Down

0 comments on commit a8ef0a2

Please sign in to comment.