From 08ac6f1feae796b6a21d6fdd2205b686590ae718 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Fri, 10 Mar 2023 18:11:45 +0300 Subject: [PATCH] storing the fraction of veOcean --- schema.graphql | 1 + src/mappings/veDelegation.ts | 8 ++ test/integration/veDelegation.test.ts | 170 ++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 test/integration/veDelegation.test.ts diff --git a/schema.graphql b/schema.graphql index 1905595..3d2a64a 100644 --- a/schema.graphql +++ b/schema.graphql @@ -465,6 +465,7 @@ type VeDelegation @entity { receiver: VeOCEAN! tokenId: BigInt! amount: BigInt! + amountFraction: BigDecimal! cancelTime: BigInt! expireTime: BigInt! block: Int! diff --git a/src/mappings/veDelegation.ts b/src/mappings/veDelegation.ts index b69bc7c..fe1a5b1 100644 --- a/src/mappings/veDelegation.ts +++ b/src/mappings/veDelegation.ts @@ -18,6 +18,10 @@ export function handleDelegation(event: DelegateBoost): void { const veDelegation = getveDelegation(_tokenId.toHex()) veDelegation.delegator = _delegator getveOCEAN(_receiver) + const delegatorVeOcean = getveOCEAN(_delegator) + veDelegation.amountFraction = _amount.divDecimal( + delegatorVeOcean.lockedAmount + ) veDelegation.receiver = _receiver veDelegation.tokenId = _tokenId veDelegation.amount = _amount @@ -36,6 +40,10 @@ export function handleExtendBoost(event: ExtendBoost): void { const _expireTime = event.params._expire_time const veDelegation = getveDelegation(_tokenId.toHex()) + const delegatorVeOcean = getveOCEAN(_delegator) + veDelegation.amountFraction = _amount.divDecimal( + delegatorVeOcean.lockedAmount + ) veDelegation.delegator = _delegator veDelegation.receiver = _receiver veDelegation.tokenId = _tokenId diff --git a/test/integration/veDelegation.test.ts b/test/integration/veDelegation.test.ts new file mode 100644 index 0000000..38be14e --- /dev/null +++ b/test/integration/veDelegation.test.ts @@ -0,0 +1,170 @@ +import { + VeOcean, + calculateEstimatedGas, + sendTx, + approve, + ConfigHelper, + sleep +} from '@oceanprotocol/lib' +import { AbiItem } from 'web3-utils' +import { assert } from 'chai' +import Web3 from 'web3' +import { homedir } from 'os' +import fs from 'fs' +import { fetch } from 'cross-fetch' +import veDelegation from '@oceanprotocol/contracts/artifacts/contracts/ve/veDelegation.vy/veDelegation.json' +import moment from 'moment' + +const data = JSON.parse( + fs.readFileSync( + process.env.ADDRESS_FILE || + `${homedir}/.ocean/ocean-contracts/artifacts/address.json`, + 'utf8' + ) +) + +const addresses = data.development +const web3 = new Web3('http://127.0.0.1:8545') + +const subgraphUrl = + 'http://127.0.0.1:9000/subgraphs/name/oceanprotocol/ocean-subgraph' + +const minAbi = [ + { + constant: false, + inputs: [ + { name: 'to', type: 'address' }, + { name: 'value', type: 'uint256' } + ], + name: 'mint', + outputs: [{ name: '', type: 'bool' }], + payable: false, + stateMutability: 'nonpayable', + type: 'function' + } +] as AbiItem[] + +describe('veOcean tests', async () => { + let veOcean: VeOcean + let ownerAccount: string + let Alice: string + let Bob: string + let delegateContract + const configHelper = new ConfigHelper() + const config = configHelper.getConfig('development') + + before(async () => { + const accounts = await web3.eth.getAccounts() + ownerAccount = accounts[0] + Alice = accounts[1] + Bob = accounts[2] + delegateContract = new web3.eth.Contract( + veDelegation.abi as AbiItem[], + addresses.veDelegation + ) + + const tokenContract = new web3.eth.Contract(minAbi, addresses.Ocean) + const estGas = await calculateEstimatedGas( + ownerAccount, + tokenContract.methods.mint, + Alice, + web3.utils.toWei('100000') + ) + await sendTx( + ownerAccount, + estGas, + web3, + 1, + tokenContract.methods.mint, + Alice, + web3.utils.toWei('100000') + ) + await sendTx( + ownerAccount, + estGas, + web3, + 1, + tokenContract.methods.mint, + Bob, + web3.utils.toWei('100000') + ) + veOcean = new VeOcean(addresses.veOCEAN, web3) + }) + + it('Alice should lock 100 Ocean and Delegate them to Bob', async () => { + // since we can only lock once, we test if tx fails or not + // so if there is already a lock, skip it + let currentBalance = await veOcean.getLockedAmount(Alice) + let currentLock = await veOcean.lockEnd(Alice) + const amount = '100' + await approve( + web3, + config, + Alice, + addresses.Ocean, + addresses.veOCEAN, + amount + ) + const timestamp = Math.floor(Date.now() / 1000) + const unlockTime = timestamp + 7 * 86400 + + if (parseInt(currentBalance) > 0 || currentLock > 0) { + // we already have some locked tokens, so our transaction should fail + try { + await veOcean.lockTokens(Alice, amount, unlockTime) + assert(false, 'This should fail!') + } catch (e) { + // do nothing + } + } else { + await veOcean.lockTokens(Alice, amount, unlockTime) + } + currentBalance = await veOcean.getLockedAmount(Alice) + currentLock = await veOcean.lockEnd(Alice) + await sleep(2000) + const initialQuery = { + query: `query { + veOCEANs(id:"${Alice.toLowerCase()}"){ + id, + lockedAmount, + unlockTime + } + }` + } + const initialResponse = await fetch(subgraphUrl, { + method: 'POST', + body: JSON.stringify(initialQuery) + }) + const info = (await initialResponse.json()).data.veOCEANs + assert(info[0].id === Alice.toLowerCase()) + assert(info[0].lockedAmount === currentBalance) + assert(info[0].unlockTime === currentLock) + + console.log('Alice', Alice) + + const estGas = await calculateEstimatedGas( + Alice, + delegateContract.methods.setApprovalForAll, + Alice, + 0 + ) + console.log('estGas', estGas) + console.log('info[0].unlockTime.unix', moment().unix()) + const lockTime = await veOcean.lockEnd(Alice) + console.log('lockTime', lockTime) + + const tx1 = await delegateContract.methods + .setApprovalForAll(Alice, true) + .send({ + from: Alice + }) + console.log('TX1: ', tx1) + + const tx = await delegateContract.methods + .create_boost(Bob, Alice, 1000, 0, lockTime, 0) + .send({ + from: Bob + }) + console.log('TX: ', tx) + }) +})