Skip to content

Commit fad004d

Browse files
committed
Add StandardFactoryWrapped contract ABI and useEvmDaoCreateStore refactor
1 parent 0194ac3 commit fad004d

6 files changed

Lines changed: 1048 additions & 80 deletions

File tree

src/assets/abis/StandardFactoryNonTransferable.json

Lines changed: 346 additions & 0 deletions
Large diffs are not rendered by default.

src/assets/abis/StandardFactoryTransferable.json

Lines changed: 346 additions & 0 deletions
Large diffs are not rendered by default.

src/assets/abis/StandardFactoryWrapped.json

Lines changed: 299 additions & 0 deletions
Large diffs are not rendered by default.

src/modules/etherlink/creator/EvmDaoMembership.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { IconButton, Typography, Button, Add, RemoveCircleOutline, Box, StyledTe
22
import { DescriptionText, CustomInputContainer, ErrorText } from "components/ui/DaoCreator"
33
import { TitleBlock } from "modules/common/TitleBlock"
44
import useEvmDaoCreateStore from "services/contracts/etherlinkDAO/hooks/useEvmDaoCreateStore"
5-
// StyledTextField imported from components/ui
65
import { isInvalidEvmAddress } from "../utils"
76

87
interface Member {
@@ -54,6 +53,13 @@ export const EvmDaoMembership = () => {
5453
)
5554
}
5655

56+
const wrappedTokenPoints = [
57+
"The wrapped token will start with 0 initial supply",
58+
"Token holders must wrap their existing tokens after DAO deployment",
59+
"Voting power will be delegated automatically when tokens are wrapped",
60+
"Users can unwrap tokens at any time to retrieve their original tokens"
61+
]
62+
5763
if (isWrappedToken) {
5864
return (
5965
<Box>
@@ -81,18 +87,18 @@ export const EvmDaoMembership = () => {
8187
<Typography variant="body1" style={{ color: "rgba(255, 255, 255, 0.7)", marginBottom: "12px" }}>
8288
Since you're wrapping an existing ERC20 token:
8389
</Typography>
84-
<Typography variant="body2" style={{ color: "rgba(255, 255, 255, 0.7)", marginBottom: "8px" }}>
85-
• The wrapped token will start with 0 initial supply
86-
</Typography>
87-
<Typography variant="body2" style={{ color: "rgba(255, 255, 255, 0.7)", marginBottom: "8px" }}>
88-
• Token holders must wrap their existing tokens after DAO deployment
89-
</Typography>
90-
<Typography variant="body2" style={{ color: "rgba(255, 255, 255, 0.7)", marginBottom: "8px" }}>
91-
• Voting power will be delegated automatically when tokens are wrapped
92-
</Typography>
93-
<Typography variant="body2" style={{ color: "rgba(255, 255, 255, 0.7)" }}>
94-
• Users can unwrap tokens at any time to retrieve their original tokens
95-
</Typography>
90+
<Box component="ul" style={{ margin: 0, paddingLeft: "20px" }}>
91+
{wrappedTokenPoints.map(point => (
92+
<Typography
93+
key={point}
94+
variant="body2"
95+
component="li"
96+
style={{ color: "rgba(255, 255, 255, 0.7)", margin: "0 0 4px", lineHeight: 1.4 }}
97+
>
98+
{point}
99+
</Typography>
100+
))}
101+
</Box>
96102
</Box>
97103
</Box>
98104
)

src/modules/etherlink/types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ export interface IEvmFirebaseContract {
77
daoFactory: IEthereumAddress
88
timelockFactory: IEthereumAddress
99
registryFactory: IEthereumAddress
10+
standardFactory?: IEthereumAddress
11+
standardFactory_t?: IEthereumAddress
12+
standardFactory_w?: IEthereumAddress
1013
wrapper?: IEthereumAddress
1114
wrapper_t: IEthereumAddress
1215
wrapper_w: IEthereumAddress

src/services/contracts/etherlinkDAO/hooks/useEvmDaoCreateStore.tsx

Lines changed: 35 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import { persist, createJSONStorage } from "zustand/middleware"
66
import { STEPS } from "modules/etherlink/config"
77
import { useHistory } from "react-router-dom"
88

9-
import WrapperStandardAbi from "assets/abis/hb_wrapper_standard.json"
9+
import StandardFactoryAbi from "assets/abis/StandardFactoryNonTransferable.json"
10+
import StandardFactoryTAbi from "assets/abis/StandardFactoryTransferable.json"
11+
import StandardFactoryWAbi from "assets/abis/StandardFactoryWrapped.json"
1012

1113
import { useCallback, useContext, useState } from "react"
1214
import { useTezos } from "services/beacon/hooks/useTezos"
1315
import { EtherlinkContext } from "services/wagmi/context"
14-
import { EnvKey, getEnv } from "services/config"
1516
import { useNotification } from "modules/common/hooks/useNotification"
1617

1718
interface EvmDaoCreateStore {
@@ -163,7 +164,11 @@ const useEvmDaoCreateStore = () => {
163164
const [isDeploying, setIsDeploying] = useState(false)
164165
const data = useEvmDaoCreateZustantStore()
165166
const history = useHistory()
166-
const { contractData } = useContext(EtherlinkContext)
167+
const { contractData } = useContext<{
168+
wrapper: string
169+
wrapper_t: string
170+
wrapper_w: string
171+
}>(EtherlinkContext)
167172

168173
const { etherlink, network } = useTezos()
169174
const notify = useNotification()
@@ -173,17 +178,13 @@ const useEvmDaoCreateStore = () => {
173178
console.log("=== Starting DAO Deployment ===")
174179
console.log("Full DAO Data:", daoData)
175180

176-
const wrapperAddressOverride = getEnv(EnvKey.REACT_APP_EVM_WRAPPER_ADDRESS)
177-
const wrapperTAddressOverride = getEnv(EnvKey.REACT_APP_EVM_WRAPPER_T_ADDRESS)
178-
const wrapperWrappedOverride = getEnv(EnvKey.REACT_APP_EVM_WRAPPER_W_ADDRESS)
179-
180181
let selectedWrapperAddress: string | undefined
181182
if (daoData.tokenDeploymentMechanism === "wrapped") {
182-
selectedWrapperAddress = wrapperWrappedOverride || contractData?.wrapper_w
183+
selectedWrapperAddress = (contractData as any)?.wrapper_w
183184
} else if (daoData.nonTransferable) {
184-
selectedWrapperAddress = wrapperAddressOverride || contractData?.wrapper
185+
selectedWrapperAddress = (contractData as any)?.wrapper
185186
} else {
186-
selectedWrapperAddress = wrapperTAddressOverride || contractData?.wrapper_t
187+
selectedWrapperAddress = (contractData as any)?.wrapper_t
187188
}
188189

189190
try {
@@ -221,6 +222,7 @@ const useEvmDaoCreateStore = () => {
221222
: daoData.nonTransferable
222223
? "non-transferable"
223224
: "transferable"
225+
224226
console.error("No wrapper address found!", {
225227
factoryType,
226228
tokenDeploymentMechanism: daoData.tokenDeploymentMechanism,
@@ -237,7 +239,15 @@ const useEvmDaoCreateStore = () => {
237239
throw new Error("Wallet not connected. Please connect your wallet.")
238240
}
239241

240-
const selectedAbi = WrapperStandardAbi.abi
242+
// Select ABI based on flow; fall back to StandardFactoryAbi when a specific variant isn't available
243+
let selectedAbi: any
244+
if (daoData.tokenDeploymentMechanism === "wrapped") {
245+
selectedAbi = (StandardFactoryWAbi as any)?.abi
246+
} else if (daoData.nonTransferable) {
247+
selectedAbi = (StandardFactoryAbi as any)?.abi
248+
} else {
249+
selectedAbi = (StandardFactoryTAbi as any)?.abi
250+
}
241251

242252
// Preflight: verify contract code exists at address
243253
const onChainCode = await etherlink.provider.getCode(selectedWrapperAddress)
@@ -276,71 +286,29 @@ const useEvmDaoCreateStore = () => {
276286
let wrapper: any // This will be a TransactionResponse
277287

278288
if (daoData.tokenDeploymentMechanism === "wrapped") {
279-
// Deploy with wrapped token
280-
// Ensure registry is initialized
289+
// Deploy with wrapped token using the StandardFactoryWrapped tuple structure
281290
const registryKeys = Object.keys(daoData.registry || {})
282291
const registryValues = Object.values(daoData.registry || {}).map(v => String(v))
283292

284-
console.log("Registry data for wrapped token:", {
285-
registry: daoData.registry,
286-
keys: registryKeys,
287-
values: registryValues,
288-
keyTypes: registryKeys.map(k => typeof k),
289-
valueTypes: registryValues.map(v => typeof v)
290-
})
291-
292-
console.log("Preparing proposal threshold:", {
293-
proposalThreshold,
294-
proposalThresholdType: typeof proposalThreshold,
295-
proposalThresholdAsBigInt: BigInt(proposalThreshold || 0).toString()
296-
})
293+
const governanceSettings = [
294+
BigInt(proposalThreshold || 0),
295+
BigInt(Math.min(Math.max(votingDelayInMinutes, 0), 2 ** 48 - 1)), // voting delay (minutes)
296+
BigInt(Math.min(Math.max(votingDurationInMinutes, 0), 2 ** 32 - 1)), // voting period (minutes)
297+
BigInt(Math.min(Math.max(Number(quorumThreshold), 0), 100)) // quorum fraction percentage
298+
]
297299

298300
const wrappedDaoPayload = {
299-
daoName: daoData.name || "",
300-
wrappedTokenName: daoData.wrappedTokenName || `Wrapped ${daoData.wrappedTokenSymbol || "Token"}`,
301-
wrappedTokenSymbol: daoData.wrappedTokenSymbol || "",
301+
name: daoData.name || "",
302+
symbol: daoData.wrappedTokenSymbol || "",
302303
description: daoData.description || "",
303-
executionDelay: Math.floor(executationDelayinSeconds),
304+
executionDelay: BigInt(Math.max(Math.floor(executationDelayinSeconds), 0)),
304305
underlyingTokenAddress: daoData.underlyingTokenAddress,
305-
minsVotingDelay: Math.min(Math.max(votingDelayInMinutes, 0), 2 ** 48 - 1), // uint48
306-
minsVotingPeriod: Math.min(Math.max(votingDurationInMinutes, 0), 2 ** 32 - 1), // uint32
307-
proposalThreshold: BigInt(proposalThreshold || 0), // uint256 - raw token amount
308-
quorumFraction: Math.min(Math.max(Number(quorumThreshold), 0), 100), // uint8
309-
keys: Object.keys(daoData.registry || {}),
310-
values: Object.values(daoData.registry || {}).map(v => String(v))
306+
governanceSettings,
307+
keys: registryKeys,
308+
values: registryValues,
309+
transferrableStr: String(!daoData.nonTransferable).toLowerCase()
311310
}
312311

313-
// const wrappedDaoPayload = isUsingFallbackAddress
314-
// ? {
315-
// // Legacy structure without wrappedTokenName
316-
// daoName: daoData.name || "",
317-
// wrappedTokenSymbol: daoData.wrappedTokenSymbol || "",
318-
// description: daoData.description || "",
319-
// executionDelay: Math.floor(executationDelayinSeconds),
320-
// underlyingTokenAddress: daoData.underlyingTokenAddress,
321-
// minsVotingDelay: Math.min(Math.max(votingDelayInMinutes, 0), 2 ** 48 - 1), // uint48
322-
// minsVotingPeriod: Math.min(Math.max(votingDurationInMinutes, 0), 2 ** 32 - 1), // uint32
323-
// proposalThreshold: BigInt(proposalThreshold || 0), // uint256 - raw token amount
324-
// quorumFraction: Math.min(Math.max(Number(quorumThreshold), 0), 100), // uint8
325-
// keys: Object.keys(daoData.registry || {}),
326-
// values: Object.values(daoData.registry || {}).map(v => String(v))
327-
// }
328-
// : {
329-
// // New structure with wrappedTokenName
330-
// daoName: daoData.name || "",
331-
// wrappedTokenName: `Wrapped ${daoData.wrappedTokenSymbol || "Token"}`,
332-
// wrappedTokenSymbol: daoData.wrappedTokenSymbol || "",
333-
// description: daoData.description || "",
334-
// executionDelay: Math.floor(executationDelayinSeconds),
335-
// underlyingTokenAddress: daoData.underlyingTokenAddress,
336-
// minsVotingDelay: Math.min(Math.max(votingDelayInMinutes, 0), 2 ** 48 - 1), // uint48
337-
// minsVotingPeriod: Math.min(Math.max(votingDurationInMinutes, 0), 2 ** 32 - 1), // uint32
338-
// proposalThreshold: BigInt(proposalThreshold || 0), // uint256 - raw token amount
339-
// quorumFraction: Math.min(Math.max(Number(quorumThreshold), 0), 100), // uint8
340-
// keys: Object.keys(daoData.registry || {}),
341-
// values: Object.values(daoData.registry || {}).map(v => String(v))
342-
// }
343-
344312
console.log(
345313
"Deploying wrapped token DAO with payload:",
346314
JSON.stringify(wrappedDaoPayload, (key, value) => (typeof value === "bigint" ? value.toString() : value), 2)

0 commit comments

Comments
 (0)