Storing the fraction of veOcean (#623)

* storing the fraction of veOcean

* Added moment.js

* Adding moment to package-lock.json

* Updating test

* Updating test

* Fixing failing transaction in test

* Increasing lock time

* Adding additional assert statements

* updating test

* Updating veDelegation test

* Updating query

* Updating test

* Updating test

* Making percentage update conditional

* Update handle extend boost

* Updating fraction amount

* Updating tests

* Adding comments

* Increasing sleep times

* Adding comment

* Revert "Increasing sleep times"

This reverts commit dc21fcdf8d.

* Removing comment

* Adding test

* Combining tests

* Updating test

* removing comments

* Remove comment

* Ensuring amountFraction is set to zero after burnBoost

* Changing bigInt to BigDecimal

* Updating test

* adding comment

* Setting zero value for new VeDelegation amountFraction

* Updating test query

* Updating tests

* Updating test

* Increase test sleep time

---------

Co-authored-by: idiom-bytes <69865342+idiom-bytes@users.noreply.github.com>
This commit is contained in:
Jamie Hewitt 2023-03-30 08:29:31 -04:00 committed by GitHub
parent 81eb7ea738
commit 0a3d513262
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 1 deletions

View File

@ -32,6 +32,7 @@
"test-ve": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/VeOcean.test.ts'", "test-ve": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/VeOcean.test.ts'",
"test-df": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/DFRewards.test.ts'", "test-df": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/DFRewards.test.ts'",
"test-dt": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/Datatoken.test.ts'", "test-dt": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/Datatoken.test.ts'",
"test-delegation": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/veDelegation.test.ts'",
"test-zend": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/ZEnding.test.ts'", "test-zend": "TS_NODE_PROJECT='test/integration/tsconfig.json' mocha --config=test/integration/.mocharc.json --node-env=test --exit 'test/integration/ZEnding.test.ts'",
"lint": "eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx .", "lint": "eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx .",
"lint:fix": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx . --fix", "lint:fix": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx . --fix",

View File

@ -465,6 +465,7 @@ type VeDelegation @entity {
receiver: VeOCEAN! receiver: VeOCEAN!
tokenId: BigInt! tokenId: BigInt!
amount: BigInt! amount: BigInt!
amountFraction: BigDecimal!
cancelTime: BigInt! cancelTime: BigInt!
expireTime: BigInt! expireTime: BigInt!
block: Int! block: Int!

View File

@ -129,6 +129,7 @@ export function getveDelegation(id: string): VeDelegation {
veDelegation.cancelTime = BigInt.zero() veDelegation.cancelTime = BigInt.zero()
veDelegation.expireTime = BigInt.zero() veDelegation.expireTime = BigInt.zero()
veDelegation.tokenId = BigInt.zero() veDelegation.tokenId = BigInt.zero()
veDelegation.amountFraction = BigDecimal.zero()
veDelegation.amount = BigInt.zero() veDelegation.amount = BigInt.zero()
veDelegation.receiver = '' veDelegation.receiver = ''
veDelegation.delegator = '' veDelegation.delegator = ''

View File

@ -1,4 +1,4 @@
import { BigInt } from '@graphprotocol/graph-ts' import { BigDecimal, BigInt } from '@graphprotocol/graph-ts'
import { import {
BurnBoost, BurnBoost,
DelegateBoost, DelegateBoost,
@ -18,6 +18,12 @@ export function handleDelegation(event: DelegateBoost): void {
const veDelegation = getveDelegation(_tokenId.toHex()) const veDelegation = getveDelegation(_tokenId.toHex())
veDelegation.delegator = _delegator veDelegation.delegator = _delegator
getveOCEAN(_receiver) getveOCEAN(_receiver)
const delegatorVeOcean = getveOCEAN(_delegator)
if (_amount && delegatorVeOcean.lockedAmount) {
veDelegation.amountFraction = _amount.divDecimal(
delegatorVeOcean.lockedAmount
)
}
veDelegation.receiver = _receiver veDelegation.receiver = _receiver
veDelegation.tokenId = _tokenId veDelegation.tokenId = _tokenId
veDelegation.amount = _amount veDelegation.amount = _amount
@ -36,6 +42,12 @@ export function handleExtendBoost(event: ExtendBoost): void {
const _expireTime = event.params._expire_time const _expireTime = event.params._expire_time
const veDelegation = getveDelegation(_tokenId.toHex()) const veDelegation = getveDelegation(_tokenId.toHex())
const delegatorVeOcean = getveOCEAN(_delegator)
if (_amount && delegatorVeOcean.lockedAmount) {
veDelegation.amountFraction = _amount.divDecimal(
delegatorVeOcean.lockedAmount
)
}
veDelegation.delegator = _delegator veDelegation.delegator = _delegator
veDelegation.receiver = _receiver veDelegation.receiver = _receiver
veDelegation.tokenId = _tokenId veDelegation.tokenId = _tokenId
@ -59,5 +71,6 @@ export function handleBurnBoost(event: BurnBoost): void {
// delete // delete
const veDelegation = getveDelegation(_tokenId.toHex()) const veDelegation = getveDelegation(_tokenId.toHex())
veDelegation.amountFraction = BigDecimal.zero()
veDelegation.amount = BigInt.zero() veDelegation.amount = BigInt.zero()
} }

View File

@ -16,6 +16,7 @@ import Web3 from 'web3'
import { homedir } from 'os' import { homedir } from 'os'
import fs from 'fs' import fs from 'fs'
import { fetch } from 'cross-fetch' import { fetch } from 'cross-fetch'
import veDelegation from '@oceanprotocol/contracts/artifacts/contracts/ve/veDelegation.vy/veDelegation.json'
const data = JSON.parse( const data = JSON.parse(
fs.readFileSync( fs.readFileSync(
@ -87,6 +88,7 @@ const minAbi = [
describe('veOcean tests', async () => { describe('veOcean tests', async () => {
let nftFactory let nftFactory
let veOcean: VeOcean let veOcean: VeOcean
let delegateContract
let veAllocate: VeAllocate let veAllocate: VeAllocate
let veFeeDistributor: VeFeeDistributor let veFeeDistributor: VeFeeDistributor
let ownerAccount: string let ownerAccount: string
@ -103,6 +105,10 @@ describe('veOcean tests', async () => {
ownerAccount = accounts[0] ownerAccount = accounts[0]
Alice = accounts[1] Alice = accounts[1]
Bob = accounts[2] Bob = accounts[2]
delegateContract = new web3.eth.Contract(
veDelegation.abi as AbiItem[],
addresses.veDelegation
)
const tokenContract = new web3.eth.Contract(minAbi, addresses.Ocean) const tokenContract = new web3.eth.Contract(minAbi, addresses.Ocean)
const estGas = await calculateEstimatedGas( const estGas = await calculateEstimatedGas(
@ -546,4 +552,124 @@ describe('veOcean tests', async () => {
await evmIncreaseTime(60 * 60 * 24 * 7) await evmIncreaseTime(60 * 60 * 24 * 7)
await veOcean.withdraw(Alice) await veOcean.withdraw(Alice)
}) })
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 + 30 * 86400
console.log('unlock time', unlockTime)
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
}
}`
}
await sleep(2000)
const initialResponse = await fetch(subgraphUrl, {
method: 'POST',
body: JSON.stringify(initialQuery)
})
await sleep(2000)
const info = (await initialResponse.json()).data.veOCEANs
assert(info[0].id === Alice.toLowerCase(), 'ID is incorrect')
assert(info[0].lockedAmount === currentBalance, 'LockedAmount is incorrect')
assert(info[0].unlockTime === currentLock, 'Unlock time is not correct')
const lockTime = await veOcean.lockEnd(Alice)
const extLockTime = Number(lockTime) + 31556926
await delegateContract.methods.setApprovalForAll(Alice, true).send({
from: Alice
})
await veOcean.increaseUnlockTime(Alice, extLockTime)
const estGas = await calculateEstimatedGas(
Alice,
delegateContract.methods.create_boost,
Alice,
Bob,
10000,
0,
extLockTime,
0
)
const tx3 = await sendTx(
Alice,
estGas,
web3,
1,
delegateContract.methods.create_boost,
Alice,
Bob,
10000,
0,
extLockTime,
0
)
assert(tx3, 'Transaction failed')
assert(tx3.events.DelegateBoost, 'No Delegate boost event')
sleep(4000)
const delegateQuery = {
query: `query {
veDelegations{
id,
delegator {
id
},
receiver {
id
},
tokenId,
amount,
amountFraction,
cancelTime,
expireTime
}
}`
}
const delegateResponse = await fetch(subgraphUrl, {
method: 'POST',
body: JSON.stringify(delegateQuery)
})
const json = await delegateResponse.json()
console.log('json', json)
console.log('json?.data?.veDelegations', json?.data?.veDelegations)
assert(json?.data?.veDelegations, 'No veDelegations')
})
}) })