UNPKG

quasvel

Version:

Access and interact with Aragon Organizations and their apps.

432 lines (361 loc) 17.1 kB
import { ethereum, BigInt, Address } from '@graphprotocol/graph-ts' import { ERC20 } from '../generated/schema' import { ERC20 as ERC20Contract } from '../generated/templates/Agreement/ERC20' import { Staking as StakingContract } from '../generated/templates/Agreement/Staking' import { StakingFactory as StakingFactoryContract } from '../generated/templates/Agreement/StakingFactory' import { Agreement, Action, Signature, Version, Disputable, Challenge, Dispute, Evidence, Signer, CollateralRequirement, ArbitratorFee, StakingMovement, Staking } from '../generated/schema' import { Agreement as AgreementContract, ActionSubmitted, ActionChallenged, ActionSettled, ActionDisputed, ActionAccepted, ActionVoided, ActionRejected, ActionClosed, EvidenceSubmitted, SettingChanged, Signed, DisputableAppActivated, DisputableAppDeactivated, CollateralRequirementChanged } from '../generated/templates/Agreement/Agreement' /* eslint-disable @typescript-eslint/no-use-before-define */ export function handleSettingChanged(event: SettingChanged): void { const agreementApp = AgreementContract.bind(event.address) const settingData = agreementApp.getSetting(event.params.settingId) const agreement = loadOrCreateAgreement(event.address) const currentVersionId = buildVersionId(event.address, event.params.settingId) const version = new Version(currentVersionId) version.agreement = event.address.toHexString() version.versionId = event.params.settingId version.arbitrator = settingData.value0 version.appFeesCashier = settingData.value1 version.title = settingData.value2 version.content = settingData.value3 version.effectiveFrom = event.block.timestamp version.save() agreement.currentVersion = currentVersionId agreement.save() } export function handleSigned(event: Signed): void { const signer = loadOrCreateSigner(event.address, event.params.signer) signer.save() const signature = new Signature(event.transaction.hash.toHexString()) signature.signer = buildSignerId(event.address, event.params.signer) signature.version = buildVersionId(event.address, event.params.settingId) signature.createdAt = event.block.timestamp signature.save() } export function handleDisputableAppActivated(event: DisputableAppActivated): void { const agreementApp = AgreementContract.bind(event.address) const disputableData = agreementApp.getDisputableInfo(event.params.disputable) const disputable = loadOrCreateDisputable(event.address, event.params.disputable) disputable.activated = true disputable.currentCollateralRequirement = buildCollateralRequirementId(event.address, event.params.disputable, disputableData.value1) disputable.save() updateCollateralRequirement(event.address, event.params.disputable, disputableData.value1) } export function handleDisputableAppDeactivated(event: DisputableAppDeactivated): void { const disputable = loadOrCreateDisputable(event.address, event.params.disputable) disputable.activated = false disputable.save() } export function handleCollateralRequirementChanged(event: CollateralRequirementChanged): void { updateCollateralRequirement(event.address, event.params.disputable, event.params.collateralRequirementId) } export function handleActionSubmitted(event: ActionSubmitted): void { const actionId = buildActionId(event.address, event.params.actionId) const agreementApp = AgreementContract.bind(event.address) const action = new Action(actionId) const actionData = agreementApp.getAction(event.params.actionId) action.agreement = event.address.toHexString() action.actionId = event.params.actionId action.disputable = buildDisputableId(event.address, actionData.value0) action.disputableActionId = actionData.value1 action.collateralRequirement = buildCollateralRequirementId(event.address, actionData.value0, actionData.value2) action.version = buildVersionId(event.address, actionData.value3) action.submitter = buildSignerId(event.address, actionData.value4) action.closed = actionData.value5 action.context = actionData.value6 action.createdAt = event.block.timestamp action.save() createStakingMovement(event.address, event.params.actionId, 'new', event) } export function handleActionClosed(event: ActionClosed): void { const action = Action.load(buildActionId(event.address, event.params.actionId))! action.closed = true action.save() createStakingMovement(event.address, event.params.actionId, 'closed', event) } export function handleActionChallenged(event: ActionChallenged): void { const actionId = buildActionId(event.address, event.params.actionId) const challengeId = buildChallengeId(event.address, event.params.challengeId) const agreementApp = AgreementContract.bind(event.address) const action = Action.load(actionId)! action.lastChallenge = challengeId action.save() const challenge = new Challenge(challengeId) const challengeData = agreementApp.getChallenge(event.params.challengeId) challenge.action = buildActionId(event.address, event.params.actionId) challenge.challengeId = event.params.challengeId challenge.challenger = challengeData.value1 challenge.endDate = challengeData.value2 challenge.context = challengeData.value3 challenge.settlementOffer = challengeData.value4 challenge.state = castChallengeState(challengeData.value5) challenge.createdAt = event.block.timestamp const challengerArbitratorFeeId = challengeId + 'challenger-arbitrator-fee' const challengeArbitratorFeesData = agreementApp.getChallengeArbitratorFees(event.params.challengeId) createArbitratorFee(event.address, challengerArbitratorFeeId, challengeArbitratorFeesData.value2, challengeArbitratorFeesData.value3) challenge.challengerArbitratorFee = challengerArbitratorFeeId challenge.save() createStakingMovement(event.address, event.params.actionId, 'challenged', event) } export function handleActionSettled(event: ActionSettled): void { updateChallengeState(event.address, event.params.challengeId) createStakingMovement(event.address, event.params.actionId, 'settled', event) } export function handleActionDisputed(event: ActionDisputed): void { updateChallengeState(event.address, event.params.challengeId) const dispute = loadOrCreateDispute(event.address, event.params.challengeId, event) dispute.save() const challengeId = buildChallengeId(event.address, event.params.challengeId) const agreementApp = AgreementContract.bind(event.address) const challengeArbitratorFeesData = agreementApp.getChallengeArbitratorFees(event.params.challengeId) const submitterArbitratorFeeId = challengeId + 'submitter-arbitrator-fee' createArbitratorFee(event.address, submitterArbitratorFeeId, challengeArbitratorFeesData.value0, challengeArbitratorFeesData.value1) const challenge = Challenge.load(challengeId)! challenge.submitterArbitratorFee = submitterArbitratorFeeId challenge.save() } export function handleActionAccepted(event: ActionAccepted): void { updateChallengeState(event.address, event.params.challengeId) updateDisputeState(event.address, event.params.challengeId, event) } export function handleActionVoided(event: ActionVoided): void { updateChallengeState(event.address, event.params.challengeId) updateDisputeState(event.address, event.params.challengeId, event) } export function handleActionRejected(event: ActionRejected): void { updateChallengeState(event.address, event.params.challengeId) updateDisputeState(event.address, event.params.challengeId, event) createStakingMovement(event.address, event.params.actionId, 'rejected', event) } export function handleEvidenceSubmitted(event: EvidenceSubmitted): void { const evidenceId = buildId(event) const evidence = new Evidence(evidenceId) evidence.data = event.params.evidence evidence.dispute = buildDisputeId(event.address, event.params.disputeId) evidence.submitter = event.params.submitter evidence.createdAt = event.block.timestamp evidence.save() } function loadOrCreateAgreement(agreementAddress: Address): Agreement { let agreement = Agreement.load(agreementAddress.toHexString()) if (agreement === null) { const agreementApp = AgreementContract.bind(agreementAddress) const stakingFactoryAddress = agreementApp.stakingFactory() agreement = new Agreement(agreementAddress.toHexString()) agreement.dao = agreementApp.kernel() agreement.stakingFactory = stakingFactoryAddress } return agreement! } function loadOrCreateSigner(agreement: Address, signerAddress: Address): Signer { const signerId = buildSignerId(agreement, signerAddress) let signer = Signer.load(signerId) if (signer === null) { signer = new Signer(signerId) signer.agreement = agreement.toHexString() signer.address = signerAddress } return signer! } function loadOrCreateDisputable(agreement: Address, disputableAddress: Address): Disputable { const disputableId = buildDisputableId(agreement, disputableAddress) let disputable = Disputable.load(disputableId) if (disputable === null) { disputable = new Disputable(disputableId) disputable.agreement = agreement.toHexString() disputable.address = disputableAddress } return disputable! } function loadOrCreateDispute(agreement: Address, challengeId: BigInt, event: ethereum.Event): Dispute { const agreementApp = AgreementContract.bind(agreement) const challengeData = agreementApp.getChallenge(challengeId) const disputeId = buildDisputeId(agreement, challengeData.value8) let dispute = Dispute.load(disputeId) if (dispute === null) { dispute = new Dispute(disputeId) dispute.ruling = challengeData.value9 dispute.disputeId = challengeData.value8 dispute.challenge = buildChallengeId(agreement, challengeId) dispute.submitterFinishedEvidence = challengeData.value6 dispute.challengerFinishedEvidence = challengeData.value7 dispute.createdAt = event.block.timestamp } return dispute! } function updateChallengeState(agreement: Address, challengeId: BigInt): void { const agreementApp = AgreementContract.bind(agreement) const challengeData = agreementApp.getChallenge(challengeId) const challenge = Challenge.load(buildChallengeId(agreement, challengeId))! challenge.state = castChallengeState(challengeData.value5) challenge.save() } function updateDisputeState(agreement: Address, challengeId: BigInt, event: ethereum.Event): void { const agreementApp = AgreementContract.bind(agreement) const challengeData = agreementApp.getChallenge(challengeId) const dispute = loadOrCreateDispute(agreement, challengeId, event) dispute.ruling = challengeData.value9 dispute.submitterFinishedEvidence = challengeData.value6 dispute.challengerFinishedEvidence = challengeData.value7 dispute.save() } function updateCollateralRequirement(agreement: Address, disputable: Address, collateralRequirementId: BigInt): void { const agreementApp = AgreementContract.bind(agreement) const requirementId = buildCollateralRequirementId(agreement, disputable, collateralRequirementId) const requirement = new CollateralRequirement(requirementId) const requirementData = agreementApp.getCollateralRequirement(disputable, collateralRequirementId) requirement.disputable = buildDisputableId(agreement, disputable) requirement.token = buildERC20(agreement, requirementData.value0) requirement.challengeDuration = requirementData.value1 requirement.actionAmount = requirementData.value2 requirement.challengeAmount = requirementData.value3 requirement.save() } function createStakingMovement(agreement: Address, actionId: BigInt, type: string, event: ethereum.Event): void { const agreementApp = AgreementContract.bind(agreement) const actionData = agreementApp.getAction(actionId) const collateralData = agreementApp.getCollateralRequirement(actionData.value0, actionData.value2) const user = actionData.value4 const token = collateralData.value0 const collateralAmount = collateralData.value2 if (collateralAmount.equals(BigInt.fromI32(0))) { return } const factory = StakingFactoryContract.bind(agreementApp.stakingFactory()) const stakingAddress = factory.getInstance(token) const staking = updateStaking(stakingAddress, token, user) const id = buildStakingMovementId(token, user, buildId(event)) const movement = new StakingMovement(id) movement.staking = staking.id movement.agreement = agreement.toHexString() movement.action = buildActionId(agreement, actionId) movement.createdAt = event.block.timestamp if (type == 'new') { movement.amount = collateralAmount movement.actionState = 'Scheduled' movement.collateralState = 'Locked' } else if (type == 'challenged') { movement.amount = collateralAmount movement.actionState = 'Challenged' movement.collateralState = 'Challenged' staking.challenged = staking.challenged.plus(collateralAmount) } else if (type == 'settled') { const challengeData = agreementApp.getChallenge(actionData.value7) movement.amount = challengeData.value4 movement.actionState = 'Settled' movement.collateralState = 'Slashed' staking.challenged = staking.challenged.minus(collateralAmount) } else if (type == 'rejected') { movement.amount = collateralAmount movement.actionState = 'Cancelled' movement.collateralState = 'Slashed' staking.challenged = staking.challenged.minus(collateralAmount) } else { // closed movement.amount = collateralAmount movement.actionState = 'Completed' movement.collateralState = 'Available' staking.challenged = staking.challenged.minus(collateralAmount) } staking.save() movement.save() } function updateStaking(stakingAddress: Address, token: Address, user: Address): Staking { const stakingApp = StakingContract.bind(stakingAddress) const balance = stakingApp.getBalancesOf(user) const staking = loadOrCreateStaking(token, user) staking.total = balance.value0 staking.locked = balance.value1 staking.available = staking.total.minus(staking.locked) staking.save() return staking } function loadOrCreateStaking(token: Address, user: Address): Staking { const id = buildStakingId(token, user) let staking = Staking.load(id) if (staking === null) { staking = new Staking(id) staking.user = user staking.token = token.toHexString() staking.total = BigInt.fromI32(0) staking.locked = BigInt.fromI32(0) staking.available = BigInt.fromI32(0) staking.challenged = BigInt.fromI32(0) } return staking! } function createArbitratorFee(agreement: Address, id: string, feeToken: Address, feeAmount: BigInt): void { const arbitratorFee = new ArbitratorFee(id) arbitratorFee.amount = feeAmount arbitratorFee.token = buildERC20(agreement, feeToken) arbitratorFee.save() } export function buildERC20(agreement: Address, address: Address): string { const id = address.toHexString() let token = ERC20.load(id) if (token === null) { const tokenContract = ERC20Contract.bind(address) token = new ERC20(id) token.name = tokenContract.name() token.symbol = tokenContract.symbol() token.decimals = tokenContract.decimals() token.save() } return token.id } function buildSignerId(agreement: Address, signer: Address): string { return agreement.toHexString() + "-signer-" + signer.toHexString() } function buildDisputableId(agreement: Address, disputable: Address): string { return agreement.toHexString() + "-disputable-" + disputable.toHexString() } export function buildActionId(agreement: Address, actionId: BigInt): string { return agreement.toHexString() + "-action-" + actionId.toString() } function buildChallengeId(agreement: Address, challengeId: BigInt): string { return agreement.toHexString() + "-challenge-" + challengeId.toString() } function buildDisputeId(agreement: Address, disputeId: BigInt): string { return agreement.toHexString() + "-dispute-" + disputeId.toString() } function buildVersionId(agreement: Address, versionId: BigInt): string { return agreement.toHexString() + "-version-" + versionId.toString() } function buildCollateralRequirementId(agreement: Address, disputable: Address, collateralRequirementId: BigInt): string { return buildDisputableId(agreement, disputable) + "-collateral-requirement-" + collateralRequirementId.toString() } function buildStakingId(token: Address, user: Address): string { return token.toHexString() + "-staking-" + user.toHexString() } function buildStakingMovementId(token: Address, user: Address, id: string): string { return buildStakingId(token, user) + "-movement-" + id } function buildId(event: ethereum.Event): string { return event.transaction.hash.toHexString() + event.logIndex.toString() } function castChallengeState(state: i32): string { switch (state) { case 0: return 'Waiting' case 1: return 'Settled' case 2: return 'Disputed' case 3: return 'Rejected' case 4: return 'Accepted' case 5: return 'Voided' default: return 'Unknown' } }