1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

add more Pool tests

This commit is contained in:
lacoop6tu 2021-10-27 16:29:13 -05:00
parent 2728dc3c68
commit 6e135231d3
3 changed files with 252 additions and 50 deletions

View File

@ -14,7 +14,7 @@ const MaxUint256 =
/** /**
* Provides an interface to Ocean friendly fork from Balancer BPool * Provides an interface to Ocean friendly fork from Balancer BPool
*/ */
// TODO: Add decimals handling
export class Pool { export class Pool {
public poolABI: AbiItem | AbiItem[] public poolABI: AbiItem | AbiItem[]
public web3: Web3 public web3: Web3
@ -35,12 +35,12 @@ export class Pool {
* @param {String} spender * @param {String} spender
*/ */
public async allowance( public async allowance(
tokenAdress: string, tokenAddress: string,
owner: string, owner: string,
spender: string spender: string
): Promise<string> { ): Promise<string> {
const tokenAbi = defaultERC20ABI.abi as AbiItem[] const tokenAbi = defaultERC20ABI.abi as AbiItem[]
const datatoken = new this.web3.eth.Contract(tokenAbi, tokenAdress, { const datatoken = new this.web3.eth.Contract(tokenAbi, tokenAddress, {
from: spender from: spender
}) })
const trxReceipt = await datatoken.methods.allowance(owner, spender).call() const trxReceipt = await datatoken.methods.allowance(owner, spender).call()
@ -391,7 +391,7 @@ export class Pool {
minAmountOut: string, minAmountOut: string,
maxPrice: string, maxPrice: string,
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -488,7 +488,7 @@ export class Pool {
amountOut: string, amountOut: string,
maxPrice?: string, maxPrice?: string,
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -579,7 +579,7 @@ export class Pool {
poolAmountOut: string, poolAmountOut: string,
maxAmountsIn: string[], maxAmountsIn: string[],
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -657,7 +657,7 @@ export class Pool {
poolAmountIn: string, poolAmountIn: string,
minAmountsOut: string[], minAmountsOut: string[],
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -696,13 +696,12 @@ export class Pool {
weiMinAmountsOut.push(this.web3.utils.toWei(amount)) weiMinAmountsOut.push(this.web3.utils.toWei(amount))
} }
let result = null let result = null
const estGas = this.estExitPool( const estGas = await this.estExitPool(
account, account,
poolAddress, poolAddress,
this.web3.utils.toWei(poolAmountIn), this.web3.utils.toWei(poolAmountIn),
weiMinAmountsOut weiMinAmountsOut
) )
try { try {
result = await pool.methods result = await pool.methods
.exitPool(this.web3.utils.toWei(poolAmountIn), weiMinAmountsOut) .exitPool(this.web3.utils.toWei(poolAmountIn), weiMinAmountsOut)
@ -730,7 +729,7 @@ export class Pool {
tokenAmountIn: string, tokenAmountIn: string,
minPoolAmountOut: string, minPoolAmountOut: string,
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -794,7 +793,7 @@ export class Pool {
} }
/** /**
* Estimate gas cost for joinswapExternAmountOut * Estimate gas cost for joinswapPoolAmountOut
* @param {String} address * @param {String} address
* @param {String} poolAddress * @param {String} poolAddress
* @param {String} tokenIn * @param {String} tokenIn
@ -803,14 +802,14 @@ export class Pool {
* @param {Contract} contractInstance optional contract instance * @param {Contract} contractInstance optional contract instance
* @return {Promise<number>} * @return {Promise<number>}
*/ */
public async estJoinswapExternAmountOut( public async estJoinswapPoolAmountOut(
address: string, address: string,
poolAddress: string, poolAddress: string,
tokenIn: string, tokenIn: string,
poolAmountOut: string, poolAmountOut: string,
maxAmountIn: string, maxAmountIn: string,
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -819,13 +818,16 @@ export class Pool {
let estGas let estGas
try { try {
estGas = await poolContract.methods estGas = await poolContract.methods
.joinswapExternAmountOut(tokenIn, poolAmountOut, maxAmountIn) .joinswapPoolAmountOut(tokenIn, poolAmountOut, maxAmountIn)
.estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas)) .estimateGas({ from: address }, (err, estGas) => (err ? gasLimitDefault : estGas))
} catch (e) { } catch (e) {
estGas = gasLimitDefault estGas = gasLimitDefault
} }
return estGas return estGas
} }
/** /**
* Specify poolAmountOut pool shares that you want to get, and a token tokenIn to pay with. This costs tokenAmountIn tokens (these went into the pool). * Specify poolAmountOut pool shares that you want to get, and a token tokenIn to pay with. This costs tokenAmountIn tokens (these went into the pool).
* @param {String} account * @param {String} account
@ -845,7 +847,7 @@ export class Pool {
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
let result = null let result = null
const estGas = await this.estJoinswapExternAmountOut( const estGas = await this.estJoinswapPoolAmountOut(
account, account,
poolAddress, poolAddress,
tokenIn, tokenIn,
@ -887,7 +889,7 @@ export class Pool {
poolAmountIn: string, poolAmountIn: string,
minTokenAmountOut: string, minTokenAmountOut: string,
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -965,7 +967,7 @@ export class Pool {
tokenAmountOut: string, tokenAmountOut: string,
maxPoolAmountIn: string, maxPoolAmountIn: string,
contractInstance?: Contract contractInstance?: Contract
) { ) :Promise<number>{
const poolContract = const poolContract =
contractInstance || contractInstance ||
new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress) new this.web3.eth.Contract(this.poolABI as AbiItem[], poolAddress)
@ -1086,10 +1088,10 @@ export class Pool {
let amount = null let amount = null
// if (new Decimal(tokenAmountOut).gte(tokenBalanceOut)) return null // if (new Decimal(tokenAmountOut).gte(tokenBalanceOut)) return null
try { try {
const result = await pool.methods const result = await pool.methods
.getAmountInExactOut(tokenIn, tokenOut, tokenAmountOut) .getAmountInExactOut(tokenIn, tokenOut, tokenAmountOut)
.call() .call()
// amount = this.web3.utils.fromWei(result) amount = this.web3.utils.fromWei(result)
} catch (e) { } catch (e) {
this.logger.error('ERROR: Failed to calcInGivenOut') this.logger.error('ERROR: Failed to calcInGivenOut')
} }
@ -1102,17 +1104,18 @@ export class Pool {
tokenOut: string, tokenOut: string,
tokenAmountIn: string tokenAmountIn: string
): Promise<string> { ): Promise<string> {
// TODO: solve decimals issue FIRST
const pool = new this.web3.eth.Contract(this.poolABI, poolAddress) const pool = new this.web3.eth.Contract(this.poolABI, poolAddress)
const tokenInContract = new this.web3.eth.Contract( const tokenInContract = new this.web3.eth.Contract(
defaultERC20ABI.abi as AbiItem[], defaultERC20ABI.abi as AbiItem[],
tokenIn tokenIn
) )
let amountInFormatted let amountInFormatted
let tokenInDecimals let tokenInDecimals = 18
try { try {
tokenInDecimals = await tokenInContract.methods.decimals().call() tokenInDecimals = await tokenInContract.methods.decimals().call()
} catch (e) { } catch (e) {
this.logger.error('ERROR: FAILED TO CALL DECIMALS()') this.logger.error('ERROR: FAILED TO CALL DECIMALS(), USING 18')
} }
//const tokenInDecimals = await tokenInContract.methods.decimals().call() //const tokenInDecimals = await tokenInContract.methods.decimals().call()
if (tokenInDecimals == 18) { if (tokenInDecimals == 18) {
@ -1125,7 +1128,12 @@ export class Pool {
const result = await pool.methods const result = await pool.methods
.getAmountOutExactIn(tokenIn, tokenOut, amountInFormatted) .getAmountOutExactIn(tokenIn, tokenOut, amountInFormatted)
.call() .call()
amount = this.web3.utils.fromWei(result) if (tokenInDecimals == 18){
amount = this.web3.utils.fromWei(result)
}
else{
amount = parseInt(result) / (10**tokenInDecimals)
}
} catch (e) { } catch (e) {
this.logger.error('ERROR: Failed to calcOutGivenIn') this.logger.error('ERROR: Failed to calcOutGivenIn')
} }

View File

@ -1,2 +1 @@
export * from './PoolFactory' export * from './Pool'
export * from './OceanPool'

View File

@ -78,11 +78,9 @@ describe('Pool unit test', () => {
}) })
it('should initiate Pool instance', async () => { it('should initiate Pool instance', async () => {
pool = new Pool(web3, LoggerInstance,PoolTemplate.abi as AbiItem[]) pool = new Pool(web3, LoggerInstance, PoolTemplate.abi as AbiItem[])
}) })
it('#create a pool', async () => { it('#create a pool', async () => {
// CREATE A POOL // CREATE A POOL
// we prepare transaction parameters objects // we prepare transaction parameters objects
@ -139,41 +137,238 @@ describe('Pool unit test', () => {
erc20Token = txReceipt.events.TokenCreated.returnValues.newTokenAddress erc20Token = txReceipt.events.TokenCreated.returnValues.newTokenAddress
poolAddress = txReceipt.events.NewPool.returnValues.poolAddress poolAddress = txReceipt.events.NewPool.returnValues.poolAddress
erc20Contract = new web3.eth.Contract(ERC20Template.abi as AbiItem[], erc20Token)
erc20Contract = new web3.eth.Contract(
ERC20Template.abi as AbiItem[],
erc20Token
)
// user2 has no dt1 // user2 has no dt1
expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal('0') expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal('0')
}) })
it('#getCurrentTokens - should return current pool tokens', async () => { it('#sharesBalance - should return user shares balance (datatoken balance, LPT balance, etc) ', async () => {
const currentTokens = await pool.getCurrentTokens(poolAddress) expect(await daiContract.methods.balanceOf(user2).call()).to.equal(
expect(currentTokens[0]).to.equal(erc20Token) await pool.sharesBalance(user2, contracts.daiAddress)
expect(currentTokens[1]).to.equal(contracts.daiAddress) )
})
it('#getNumTokens - should return num of tokens in pool (2)', async () => {
expect(await pool.getNumTokens(poolAddress)).to.equal('2')
})
it('#getPoolSharesTotalSupply - should return totalSupply of LPT', async () => {
// dt owner which added liquidity has half of pool shares (the rest is in the sidestaking contracta)
const dtOwnerLPTBalance = await pool.sharesBalance(contracts.accounts[0], poolAddress)
expect(await pool.sharesBalance(contracts.accounts[0], poolAddress)).to.equal(
await pool.sharesBalance(contracts.sideStakingAddress, poolAddress)
)
// total supply is twice the dtOwner balance
expect(await pool.getPoolSharesTotalSupply(poolAddress)).to.equal(
(2 * Number(dtOwnerLPTBalance)).toString()
)
})
it('#getCurrentTokens - should return current pool tokens', async () => {
const currentTokens = await pool.getCurrentTokens(poolAddress)
expect(currentTokens[0]).to.equal(erc20Token)
expect(currentTokens[1]).to.equal(contracts.daiAddress)
})
it('#getFinalTokens - should return final pool tokens', async () => {
const finalTokens = await pool.getFinalTokens(poolAddress)
expect(finalTokens[0]).to.equal(erc20Token)
expect(finalTokens[1]).to.equal(contracts.daiAddress)
})
it('#getController - should return the pool controller (sideStaking address)', async () => {
expect(await pool.getController(poolAddress)).to.equal(contracts.sideStakingAddress)
})
it('#isBound - should return true if token is bound into the pool', async () => {
expect(await pool.isBound(poolAddress, contracts.daiAddress)).to.equal(true)
expect(await pool.isBound(poolAddress, contracts.oceanAddress)).to.equal(false)
})
it('#getReserve - should return final pool tokens', async () => {
expect(await pool.getReserve(poolAddress, contracts.daiAddress)).to.equal('2000') // base token initial liquidity
// rate is 1 so we have the same amount of DTs
expect(await pool.getReserve(poolAddress, erc20Token)).to.equal('2000')
})
it('#isFinalized - should return true if pool is finalized', async () => {
expect(await pool.isFinalized(poolAddress)).to.equal(true)
expect(await pool.isFinalized(contracts.oceanAddress)).to.equal(null)
})
it('#getSwapFee - should return the swap fee', async () => {
expect(await pool.getSwapFee(poolAddress)).to.equal('0.001')
})
it('#getNormalizedWeight - should return the normalized weight', async () => {
expect(await pool.getNormalizedWeight(poolAddress, contracts.daiAddress)).to.equal(
'0.5'
)
expect(await pool.getNormalizedWeight(poolAddress, erc20Token)).to.equal('0.5')
})
it('#getDenormalizedWeight - should return the swap fee', async () => {
expect(await pool.getDenormalizedWeight(poolAddress, contracts.daiAddress)).to.equal(
'5'
)
expect(await pool.getDenormalizedWeight(poolAddress, erc20Token)).to.equal('5')
}) })
it('#swapExactAmountIn - should swap', async () => { it('#swapExactAmountIn - should swap', async () => {
await daiContract.methods.transfer(user2,web3.utils.toWei('100')).send({from:contracts.accounts[0]}) await daiContract.methods
expect(await daiContract.methods.balanceOf(user2).call()).to.equal(web3.utils.toWei('100')) .transfer(user2, web3.utils.toWei('1000'))
.send({ from: contracts.accounts[0] })
expect(await daiContract.methods.balanceOf(user2).call()).to.equal(
web3.utils.toWei('1000')
)
expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal('0') expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal('0')
await pool.approve(user2,contracts.daiAddress,poolAddress,web3.utils.toWei('100')) await pool.approve(user2, contracts.daiAddress, poolAddress, web3.utils.toWei('100'))
const tx = await pool.swapExactAmountIn(user2,poolAddress,contracts.daiAddress,'10',erc20Token,'1') const tx = await pool.swapExactAmountIn(
expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal(tx.events.LOG_SWAP.returnValues.tokenAmountOut) user2,
poolAddress,
contracts.daiAddress,
'10',
erc20Token,
'1'
)
expect(await erc20Contract.methods.balanceOf(user2).call()).to.equal(
tx.events.LOG_SWAP.returnValues.tokenAmountOut
)
}) })
it('#swapExactAmountOut - should swap', async () => { it('#swapExactAmountOut - should swap', async () => {
// await pool.approve(contracts.accounts[0],contracts.daiAddress,poolAddress,web3.utils.toWei('100')) // await pool.approve(contracts.accounts[0],contracts.daiAddress,poolAddress,web3.utils.toWei('100'))
expect(await daiContract.methods.balanceOf(user2).call()).to.equal(web3.utils.toWei('90')) expect(await daiContract.methods.balanceOf(user2).call()).to.equal(
await pool.swapExactAmountOut(user2,poolAddress,contracts.daiAddress,'10',erc20Token,'1') web3.utils.toWei('990')
)
}) const tx = await pool.swapExactAmountOut(
user2,
poolAddress,
contracts.daiAddress,
'100',
erc20Token,
'50'
)
assert(tx != null)
})
it('#joinPool- user2 should add liquidity, receiving LP tokens', async () => {
const BPTAmountOut = '0.01'
const maxAmountsIn = [
'50', // Amounts IN
'50' // Amounts IN
]
await pool.approve(user2, erc20Token, poolAddress, web3.utils.toWei('1000'))
await pool.approve(user2, contracts.daiAddress, poolAddress, '1000')
const tx = await pool.joinPool(user2, poolAddress, BPTAmountOut, maxAmountsIn)
assert(tx != null)
expect(await pool.sharesBalance(user2, poolAddress)).to.equal(BPTAmountOut)
expect(tx.events.LOG_JOIN.event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
//console.log(tx)
// console.log(tx.events.LOG_JOIN)
// console.log(tx.events.LOG_BPT)
})
it('#joinswapExternAmountIn- user2 should add liquidity, receiving LP tokens', async () => {
const daiAmountIn = '100'
const minBPTOut = '0.1'
await pool.approve(user2, contracts.daiAddress, poolAddress, web3.utils.toWei('1000'))
const tx = await pool.joinswapExternAmountIn(
user2,
poolAddress,
contracts.daiAddress,
daiAmountIn,
minBPTOut
)
assert(tx != null)
expect(tx.events.LOG_JOIN[0].event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
// 2 JOIN EVENTS BECAUSE SIDE STAKING ALSO STAKED DTs, TODO: we should add to whom has been sent in the LOG_BPT event
expect(tx.events.LOG_JOIN[0].returnValues.bptAmount).to.equal(
tx.events.LOG_JOIN[0].returnValues.bptAmount
)
})
it('#joinswapPoolAmountOut- user2 should add liquidity, receiving LP tokens', async () => {
const BPTAmountOut = '0.1'
const maxDAIIn = '100'
await pool.approve(user2, contracts.daiAddress, poolAddress, web3.utils.toWei('1000'))
const tx = await pool.joinswapPoolAmountOut(
user2,
poolAddress,
contracts.daiAddress,
BPTAmountOut,
maxDAIIn
)
assert(tx != null)
expect(tx.events.LOG_JOIN[0].event === 'LOG_JOIN')
expect(tx.events.LOG_BPT.event === 'LOG_BPT')
// 2 JOIN EVENTS BECAUSE SIDE STAKING ALSO STAKED DTs, TODO: we should add to whom has been sent in the LOG_BPT event
expect(tx.events.LOG_JOIN[0].returnValues.bptAmount).to.equal(
tx.events.LOG_JOIN[0].returnValues.bptAmount
)
})
it('#exitPool- user2 exit the pool receiving both tokens, burning LP', async () => {
const BPTAmountIn = '0.5'
const minAmountOut = [
'1', // min amount out for OCEAN AND DT
'1'
]
const tx = await pool.exitPool(user2, poolAddress, BPTAmountIn, minAmountOut)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(erc20Token)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(contracts.daiAddress)
})
it('#exitswapPoolAmountIn- user2 exit the pool receiving only DAI', async () => {
const BPTAmountIn = '0.5'
const minDAIOut = '0.5'
const tx = await pool.exitswapPoolAmountIn(
user2,
poolAddress,
contracts.daiAddress,
BPTAmountIn,
minDAIOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.daiAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(erc20Token)
})
it('#exitswapExternAmountOut- user2 exit the pool receiving only DAI', async () => {
const maxBTPIn = "0.5"
const exactDAIOut = "1"
const tx = await pool.exitswapPoolAmountIn(
user2,
poolAddress,
contracts.daiAddress,
maxBTPIn,
exactDAIOut
)
assert(tx != null)
expect(tx.events.LOG_EXIT[0].returnValues.tokenOut).to.equal(contracts.daiAddress)
// DTs were also unstaked in the same transaction (went to the staking contract)
expect(tx.events.LOG_EXIT[1].returnValues.tokenOut).to.equal(erc20Token)
})
}) })