Skip to content

Commit

Permalink
fix: decoding events
Browse files Browse the repository at this point in the history
  • Loading branch information
coreyar committed Aug 3, 2024
1 parent 6d85442 commit 1b4be42
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 38 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:

- name: Run Matchstick tests
run: yarn test

integration-test-core-pool:
runs-on: ubuntu-20.04
needs: unit-test
Expand Down
16 changes: 1 addition & 15 deletions subgraphs/cross-chain-governance/src/operations/getOrCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,14 @@ import {
FunctionRegistry,
Governance,
GovernanceRoute,
TrustedRemote,
} from '../../generated/schema';
import { BIGINT_ZERO } from '../constants';
import {
omnichainExecutorOwnerAddress,
omnichainGovernanceOwnerAddress,
} from '../constants/addresses';
import { layerZeroChainId } from '../constants/config';
import {
getDestinationChainId,
getGovernanceId,
getGovernanceRouteId,
getRemoteChainId,
} from '../utilities/ids';
import { getDestinationChainId, getGovernanceId, getGovernanceRouteId } from '../utilities/ids';

export const getOrCreateFunctionRegistry = (signature: Bytes): FunctionRegistry => {
let functionRegistry = FunctionRegistry.load(signature);
Expand Down Expand Up @@ -69,11 +63,3 @@ export const getOrCreateDestinationChain = (destinationChainId: i32): Destinatio
}
return destinationChain;
};

export const getOrCreateTrustedRemote = (remoteChainId: i32): TrustedRemote => {
let trustedRemote = TrustedRemote.load(getRemoteChainId(remoteChainId));
if (!trustedRemote) {
trustedRemote = new TrustedRemote(getRemoteChainId(remoteChainId));
}
return trustedRemote;
};
2 changes: 0 additions & 2 deletions subgraphs/cross-chain-governance/src/utilities/ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,3 @@ export const getFailedPayloadId = (nonce: BigInt): string => nonce.toString();

export const getDestinationChainId = (destinationChainId: i32): Bytes =>
Bytes.fromI32(destinationChainId);

export const getRemoteChainId = (remoteChainId: i32): Bytes => Bytes.fromI32(remoteChainId);
4 changes: 2 additions & 2 deletions subgraphs/cross-chain-governance/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ dataSources:
- Governance
abis:
- name: OmnichainExecutorOwner
file: ../../artifacts/contracts/governance/contracts/Cross-chain/OmnichainExecutorOwner.sol/OmnichainExecutorOwner.json
file: ../../node_modules/@venusprotocol/governance-contracts/artifacts/contracts/Cross-chain/OmnichainExecutorOwner.sol/OmnichainExecutorOwner.json

eventHandlers:
- event: FunctionRegistryChanged(indexed string,bool)
Expand All @@ -43,7 +43,7 @@ dataSources:
- Proposal
abis:
- name: OmnichainGovernanceExecutor
file: ../../artifacts/contracts/governance/contracts/Cross-chain/OmnichainGovernanceExecutor.sol/OmnichainGovernanceExecutor.json
file: ../../node_modules/@venusprotocol/governance-contracts/artifacts/contracts/Cross-chain/OmnichainGovernanceExecutor.sol/OmnichainGovernanceExecutor.json
eventHandlers:
- event: NewGuardian(indexed address,indexed address)
handler: handleNewGuardian
Expand Down
2 changes: 1 addition & 1 deletion subgraphs/cross-chain-governance/tests/Owner/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('OmniGovernanceOwner', () => {
'FunctionRegistry',
Bytes.fromByteArray(ByteArray.fromUTF8('acceptAdmin(address)')).toHexString(),
'signature',
'acceptAdmin(address)',
'0x61636365707441646d696e286164647265737329',
);
assert.entityCount('FunctionRegistry', 1);
});
Expand Down
2 changes: 1 addition & 1 deletion subgraphs/venus-governance/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ type TrustedRemote @entity {
"Governance contract address on the trusted remote"
address: Bytes

"Array of proposals sent to teh remote"
"Array of proposals sent to the remote"
proposals: [RemoteProposal!]

"True if active, false if inactive"
Expand Down
6 changes: 5 additions & 1 deletion subgraphs/venus-governance/src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BigDecimal, BigInt } from '@graphprotocol/graph-ts';
import { BigDecimal, BigInt, Bytes } from '@graphprotocol/graph-ts';

export const BIGINT_ZERO = BigInt.fromI32(0);
export const BIGINT_ONE = BigInt.fromI32(1);
Expand All @@ -25,3 +25,7 @@ export const REVOKED = 'REVOKED';
export const EXECUTED = 'EXECUTED';
export const STORED = 'STORED';
export const WITHDRAWN = 'WITHDRAWN';

export const DYNAMIC_TUPLE_BYTES_PREFIX = Bytes.fromHexString(
'0x0000000000000000000000000000000000000000000000000000000000000020',
);
29 changes: 23 additions & 6 deletions subgraphs/venus-governance/src/operations/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
AGAINST,
BIGINT_ONE,
BIGINT_ZERO,
DYNAMIC_TUPLE_BYTES_PREFIX,
EXECUTED,
FOR,
NORMAL,
Expand Down Expand Up @@ -85,10 +86,17 @@ export function createRemoteProposal(event: ExecuteRemoteProposal): RemotePropos
remoteProposal.remoteChainId = event.params.remoteChainId;
remoteProposal.proposalId = event.params.proposalId;

const decoded = ethereum
.decode('((address[],uint[],string[],bytes[],uint8),uint256)', event.params.payload)!
const decoded = ethereum.decode(
'(bytes,uint256)',
DYNAMIC_TUPLE_BYTES_PREFIX.concat(event.params.payload),
);
const decodedTuple = decoded!.toTuple()!;
const payload = ethereum
.decode(
'(address[],uint256[],string[],bytes[],uint8)',
DYNAMIC_TUPLE_BYTES_PREFIX.concat(decodedTuple[0].toBytes()),
)!
.toTuple();
const payload = decoded[0].toTuple();

remoteProposal.targets = payload[0]
.toAddressArray()
Expand All @@ -106,10 +114,19 @@ export function createRemoteProposalFromPayload(event: StorePayload): RemoteProp
const remoteProposal = new RemoteProposal(getProposalId(event.params.proposalId));
remoteProposal.remoteChainId = event.params.remoteChainId;
remoteProposal.proposalId = event.params.proposalId;
const decoded = ethereum
.decode('((address[],uint[],string[],bytes[],uint8),uint256)', event.params.payload)!

const decoded = ethereum.decode(
'(bytes,uint256)',
DYNAMIC_TUPLE_BYTES_PREFIX.concat(event.params.payload),
);
const decodedTuple = decoded!.toTuple()!;
const payload = ethereum
.decode(
'(address[],uint256[],string[],bytes[],uint8)',
DYNAMIC_TUPLE_BYTES_PREFIX.concat(decodedTuple[0].toBytes()),
)!
.toTuple();
const payload = decoded[0].toTuple();

remoteProposal.targets = payload[0]
.toAddressArray()
.map<Bytes>(a => Bytes.fromHexString(a.toHexString()));
Expand Down
6 changes: 6 additions & 0 deletions subgraphs/venus-governance/subgraph-client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
PermissionsDocument,
ProposalByIdDocument,
ProposalsDocument,
RemoteProposalByIdDocument,
TrustedRemoteByIdDocument,
} from './.graphclient';

Expand Down Expand Up @@ -69,6 +70,11 @@ class SubgraphClient {
const result = await this.query(TrustedRemoteByIdDocument, { id: id.toString() });
return result;
}

async getRemoteProposal({ id }: { id: string }) {
const result = await this.query(RemoteProposalByIdDocument, { id: id.toString() });
return result;
}
}

export default new SubgraphClient(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import '@nomiclabs/hardhat-ethers';
import { expect } from 'chai';
import { Contract } from 'ethers';
import { ethers } from 'hardhat';
import { numberToByteId, waitForSubgraphToBeSynced } from 'venus-subgraph-utils';

import subgraphClient from '../../subgraph-client/index';
import { SYNC_DELAY } from './utils/constants';

const makePayload = async (
targets: string[],
values: number[],
signatures: string[],
calldatas: string[],
proposalType: number,
) => {
const payload = ethers.utils.defaultAbiCoder.encode(
['address[]', 'uint256[]', 'string[]', 'bytes[]', 'uint8'],
[targets, values, signatures, calldatas, proposalType],
);
return payload;
};

describe('OmnichainProposalSender', function () {
let omnichainProposalSender: Contract;
let normalTimeLock: Contract;
before(async function () {
await waitForSubgraphToBeSynced(SYNC_DELAY);
omnichainProposalSender = await ethers.getContract('OmnichainProposalSender');
normalTimeLock = await ethers.getContract('NormalTimelock');
});

it('should index SetTrustedRemoteAddress', async function () {
const omnichainProposalSender = await ethers.getContract('OmnichainProposalSender');
const omnichainExecutorOwner = await ethers.getContract('OmnichainExecutorOwner');
const accessControlManager = await ethers.getContract('AccessControlManager');
const [root] = await ethers.getSigners();
Expand All @@ -34,4 +51,48 @@ describe('OmnichainProposalSender', function () {
expect(trustedRemote.address).to.be.equal(omnichainExecutorOwner.address.toLowerCase());
expect(trustedRemote.proposals.length).to.be.equal(0);
});

it('should index execute remote proposal', async function () {
const calldata = ethers.utils.defaultAbiCoder.encode(['uint256'], [3600]);
const proposalType = 0;
const remoteChainId = 10102;
const payload = await makePayload(
[normalTimeLock.address],
[0],
['setDelay(uint256)'],
[calldata],
proposalType,
);
const adapterParams = ethers.utils.solidityPack(['uint16', 'uint256'], [1, 500000]);
const proposalId = +(await omnichainProposalSender.proposalCount()) + 1;

const payloadWithIdEncoded = ethers.utils.defaultAbiCoder.encode(
['bytes', 'uint256'],
[payload, proposalId],
);
const nativeFee = await omnichainProposalSender.estimateFees(
remoteChainId,
payloadWithIdEncoded,
false,
adapterParams,
);
await omnichainProposalSender.execute(10102, payload, '0x', ethers.constants.AddressZero, {
value: ethers.utils.parseEther((nativeFee[0] / 1e18 + 0.00001).toString()),
});

await waitForSubgraphToBeSynced(SYNC_DELAY);
const {
data: { remoteProposal },
} = await subgraphClient.getRemoteProposal({ id: proposalId });

expect(+remoteProposal.id).to.be.equal(proposalId);
expect(+remoteProposal.proposalId).to.be.equal(proposalId);
expect(remoteProposal.remoteChainId).to.be.equal(remoteChainId);
expect(remoteProposal.targets[0]).to.be.equal(normalTimeLock.address.toLowerCase());
expect(remoteProposal.values[0]).to.be.equal('0');
expect(remoteProposal.signatures[0]).to.be.equal('setDelay(uint256)');
expect(remoteProposal.calldatas[0]).to.be.equal(calldata);
expect(remoteProposal.proposalType).to.be.equal(0);
expect(remoteProposal.status).to.be.equal('STORED');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
query RemoteProposalById($id: ID!) {
remoteProposal(id: $id) {
id
proposalId
remoteChainId
targets
values
signatures
calldatas
proposalType
status
failedReason
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
StorePayload,
TrustedRemoteRemoved,
} from '../../../generated/OmnichainProposalSender/OmnichainProposalSender';
import { DYNAMIC_TUPLE_BYTES_PREFIX } from '../../../src/constants';
import { omnichainProposalSenderAddress } from '../../../src/constants/addresses';

export const createEncodedProposalPayload = (
Expand All @@ -27,14 +28,25 @@ export const createEncodedProposalPayload = (
ethereum.Value.fromBytesArray(calldatas),
ethereum.Value.fromI32(proposalType),
];
const payloadWithId = [
const encodePayload = ethereum.encode(
ethereum.Value.fromTuple(changetype<ethereum.Tuple>(payload)),
)!;

const payloadWithId = [
ethereum.Value.fromBytes(
Bytes.fromHexString(
encodePayload.toHexString().replace(DYNAMIC_TUPLE_BYTES_PREFIX.toHexString(), '0x'),
),
),
ethereum.Value.fromUnsignedBigInt(proposalId),
];
const encoded = ethereum.encode(
ethereum.Value.fromTuple(changetype<ethereum.Tuple>(payloadWithId)),
)!;
return encoded;

return Bytes.fromHexString(
encoded.toHexString().replace(DYNAMIC_TUPLE_BYTES_PREFIX.toHexString(), '0x'),
);
};

export const createSetTrustedRemoteAddressEvent = (
Expand Down Expand Up @@ -171,6 +183,7 @@ export const createStorePayloadEvent = (
proposalType,
proposalId,
);

const payloadParam = new ethereum.EventParam('payload', ethereum.Value.fromBytes(payload));
event.parameters.push(payloadParam);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,20 @@ describe('OmnichainProposalSender events', () => {

test('handles StorePayload event', () => {
const storePayloadEvent = createStorePayloadEvent(
13,
BigInt.fromI32(4),
[MOCK_CONTRACT_ADDRESS],
10102,
BigInt.fromI32(1),
[Address.fromString('0x4826533B4897376654Bb4d4AD88B7faFD0C98528')],
[BigInt.fromI32(0)],
['test()'],
[Bytes.fromUTF8('')],
['setDelay(uint256)'],
[Bytes.fromI32(3600)],
0,
Bytes.fromUTF8(''),
0,
Bytes.fromUTF8('Failed'),
);
handleStorePayload(storePayloadEvent);
const assertRemoteProposalDocument = (key: string, value: string): void => {
const id = getProposalId(BigInt.fromI32(4));
const id = getProposalId(BigInt.fromI32(1));
assert.fieldEquals('RemoteProposal', id, key, value);
};
assertRemoteProposalDocument('status', 'STORED');
Expand Down

0 comments on commit 1b4be42

Please sign in to comment.