Skip to content

Commit

Permalink
Merge pull request #303 from JoinColony/feat/colony-added-event
Browse files Browse the repository at this point in the history
[Proxy colonies] Feat: Add create event details to colony model
  • Loading branch information
bassgeta authored Jan 16, 2025
2 parents d843a62 + cea3572 commit bcab4c7
Show file tree
Hide file tree
Showing 5 changed files with 1,902 additions and 3,080 deletions.
20 changes: 18 additions & 2 deletions apps/main-chain/src/handlers/colonies/colonyAdded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import { getColonyContributorId } from '~utils/contributors';
import { tryFetchGraphqlQuery } from '~utils/graphql';
import { createUniqueColony } from './helpers/createUniqueColony';
import { output } from '@joincolony/utils';
import rpcProvider from '~provider';
import networkClient from '~networkClient';
import { getTransactionSignerAddress } from '~utils/transactions';
import { getColonyCreationSalt } from './helpers/validateCreationSalt';

export default async (event: ContractEvent): Promise<void> => {
const { transactionHash, args, blockNumber } = event;
Expand Down Expand Up @@ -70,13 +74,22 @@ export default async (event: ContractEvent): Promise<void> => {
0,
ContractEventsSignatures.ColonyRoleSet.indexOf('('),
);

const {
args: { user: colonyFounderAddress },
} = events.find((event) => event?.name === ColonyRoleSetEventName) ?? {
args: { user: '' },
};

let generatedColonySalt = '';

// We don't really want to block colony creation if there's something wrong with salt calculation
try {
generatedColonySalt =
(await getColonyCreationSalt(blockNumber, transactionHash)) || '';
} catch (error) {
// Most likely there was an error retrieving this transaction
}

try {
/*
* Create the colony entry in the database
Expand All @@ -86,7 +99,10 @@ export default async (event: ContractEvent): Promise<void> => {
tokenAddress: utils.getAddress(tokenAddress),
transactionHash,
initiatorAddress: utils.getAddress(colonyFounderAddress),
createdAtBlock: blockNumber,
colonyCreateEvent: {
blockNumber,
creationSalt: generatedColonySalt,
},
});
} catch (error) {
console.error(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
GetTokenFromEverywhereDocument,
GetTokenFromEverywhereQuery,
GetTokenFromEverywhereQueryVariables,
ColonyCreateEvent,
} from '@joincolony/graphql';
import rpcProvider from '~provider';
import { getCachedColonyClient } from '~utils/clients/colony';
Expand All @@ -47,13 +48,13 @@ export const createUniqueColony = async ({
tokenAddress,
transactionHash,
initiatorAddress,
createdAtBlock,
colonyCreateEvent,
}: {
colonyAddress: string;
tokenAddress: string;
transactionHash: string;
initiatorAddress: string;
createdAtBlock: number;
colonyCreateEvent: ColonyCreateEvent;
}): Promise<void> => {
/*
* Validate Colony and Token addresses
Expand Down Expand Up @@ -217,7 +218,7 @@ export const createUniqueColony = async ({
chainMetadata: {
chainId,
},
createdAtBlock,
colonyCreateEvent,
version: version.toNumber(),
status: {
nativeToken: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { verbose } from '@joincolony/utils';
import { utils } from 'ethers';
import rpcProvider from '~provider';
import networkClient from '~networkClient';
import { getTransactionSignerAddress } from '~utils/transactions';

const ContractCreationEvents = {
Create3ProxyContractCreation: 'Create3ProxyContractCreation(address,bytes32)',
};

export const getColonyCreationSalt = async (
blockNumber: number,
transactionHash: string,
): Promise<string | null> => {
const create3ProxyLogs = await rpcProvider.getProviderInstance().getLogs({
fromBlock: blockNumber,
toBlock: blockNumber,
topics: [utils.id(ContractCreationEvents.Create3ProxyContractCreation)],
});

if (create3ProxyLogs.length === 0) {
verbose(`Couldn't fetch colony proxy contract creation events`);
return null;
}

const create3ProxySalt = create3ProxyLogs[0].topics[2];

if (!create3ProxySalt) {
verbose(
`The Create3ProxyContractCreation log doesn't have the salt data: ${JSON.stringify(create3ProxyLogs[0], null, 2)}`,
);
return null;
}

const transaction = await rpcProvider
.getProviderInstance()
.getTransaction(transactionHash);

const signerAddress = getTransactionSignerAddress(transaction);

if (!signerAddress) {
verbose(
`Couldn't find the signer for transaction with txHash: ${transactionHash}`,
);
return null;
}

const generatedColonySalt = await networkClient.getColonyCreationSalt({
blockTag: blockNumber,
from: signerAddress,
});

const guardedSalt = utils.keccak256(
utils.defaultAbiCoder.encode(
['bytes32', 'bytes32'],
[
utils.hexZeroPad(networkClient.address, 32),
generatedColonySalt, // Actual salt
],
),
);

if (guardedSalt !== create3ProxySalt) {
verbose(
`The network salt doesn't match the salt used when creating the colony!`,
);
return null;
}

return generatedColonySalt;
};
23 changes: 23 additions & 0 deletions apps/main-chain/src/utils/transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { utils, Transaction } from 'ethers';

const MetatransactionInterface = new utils.Interface([
'function executeMetaTransaction(address userAddress, bytes memory payload, bytes32 sigR, bytes32 sigS, uint8 sigV) external payable returns (bytes memory)',
]);

export const getTransactionSignerAddress = (
transaction: Transaction,
): string | undefined => {
let signerAddress = transaction.from;

try {
const metaTx = MetatransactionInterface.parseTransaction({
data: transaction.data,
value: transaction.value,
});
signerAddress = metaTx.args[0];
} catch (error) {
// if it's an error, it just means it's not a metatransaction
}

return signerAddress;
};
Loading

0 comments on commit bcab4c7

Please sign in to comment.