dx-mgn-pool
Version:
Smart contracts and migration scripts for the MGN-pool for trading at the dutch-Exchange
764 lines (608 loc) • 36.7 kB
JavaScript
const DxMgnPool = artifacts.require("DxMgnPool")
const DutchExchange = artifacts.require("DutchExchange")
const TokenFRT = artifacts.require("TokenFRT")
const abi = require("ethereumjs-abi")
const ERC20 = artifacts.require("ERC20")
const MockContract = artifacts.require("MockContract")
const truffleAssert = require("truffle-assertions")
const { increaseTimeBy } = require("./utilities")
contract("DxMgnPool", (accounts) => {
describe("deposit()", () => {
it("adds a particpation", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, 100)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(42)
await instance.deposit(10)
assert.equal(await instance.numberOfParticipations.call(accounts[0]), 1)
const participation = await instance.participationAtIndex.call(accounts[0], 0)
assert.equal(participation[1], 10)
assert.equal(await instance.totalDeposit.call(), 10)
assert.equal(await instance.totalPoolShares.call(), 10)
})
it("first participation index is always even", async () => {
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(42)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const postSellOrderResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, postSellOrderResponse)
await instance.deposit(10)
await instance.participateInAuction()
await instance.deposit(100)
assert.equal(await instance.numberOfParticipations.call(accounts[0]), 2)
let participationStruct = await instance.participationsByAddress(accounts[0], 0)
assert.equal(participationStruct.startAuctionCount, 0)
participationStruct = await instance.participationsByAddress(accounts[0], 1)
assert.equal(participationStruct.startAuctionCount, 2)
})
it("fails if transfer fails", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, 0)
await depositTokenMock.givenAnyReturnBool(false)
await dxMock.givenAnyReturnUint(42)
await truffleAssert.reverts(instance.deposit(10))
})
it("fails if pooling ended", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await increaseTimeBy(102, web3)
await depositTokenMock.givenAnyReturnBool(false)
await dxMock.givenAnyReturnUint(42)
await truffleAssert.reverts(instance.deposit(10), "Pooling is already over")
})
it("address can make deposit smaller than total deposit thus far", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(42)
await instance.deposit(10)
await instance.deposit(5)
assert.equal(await instance.numberOfParticipations.call(accounts[0]), 2)
const participation = await instance.participationAtIndex.call(accounts[0], 1)
assert.equal(participation[1], 5)
assert.equal(await instance.totalDeposit.call(), 15)
assert.equal(await instance.totalPoolShares.call(), 15)
})
})
describe("participateInAuction()", () => {
it("only owner can trigger it", async () => {
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(42)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const postSellOrderResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, postSellOrderResponse)
await instance.deposit(10)
await truffleAssert.reverts(instance.participateInAuction({ from: accounts[2] })) //ownable has no designated error messages
})
it("updates auctionCount and cummulative shares", async () => {
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(42)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const postSellOrderResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, postSellOrderResponse)
await instance.deposit(10)
await instance.participateInAuction()
assert.equal(await instance.auctionCount.call(), 1)
assert.equal(await instance.totalPoolSharesCummulative.call(), 10)
})
it("fails if pooling period is over", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 1
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await increaseTimeBy(100, web3)
await truffleAssert.reverts(instance.participateInAuction(), "Pooling period is over")
})
it("pooling period ends only after even amount of auctions", async () => {
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(1)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
let tupleResponse = (abi.rawEncode(["uint", "uint"], [1, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
await instance.deposit(10)
await instance.participateInAuction()
await increaseTimeBy(100, web3)
await dxMock.givenAnyReturnUint(2)
tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
await instance.participateInAuction()
await dxMock.givenAnyReturnUint(3)
await truffleAssert.reverts(instance.participateInAuction(), "Pooling period is over")
})
it("cannot participate twice with same auction id", async () => {
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(42)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [42, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
await instance.deposit(10)
await instance.participateInAuction()
await truffleAssert.reverts(instance.participateInAuction(), "Has to wait for new auction to start")
})
it("can participate in consecutive auction", async () => {
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const getAuctionIndex = dx.contract.methods.getAuctionIndex(accounts[0], accounts[0]).encodeABI()
await instance.deposit(10)
await dxMock.givenMethodReturnUint(getAuctionIndex, 2)
await instance.participateInAuction()
await instance.deposit(20)
await dxMock.givenMethodReturnUint(getAuctionIndex, 3)
await instance.participateInAuction()
assert.equal(await instance.auctionCount.call(), 2)
assert.equal(await instance.totalPoolSharesCummulative.call(), 40) // 2 * 10 from first deposit + 1 * 20 from second
})
})
describe("withdrawDeposit()", () => {
it("returns the original deposited amount", async () => {
const token = await ERC20.new()
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenAnyReturnBool(true)
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const reponseType = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, reponseType)
await instance.deposit(10)
await increaseTimeBy(100, web3)
await depositTokenMock.givenAnyReturnBool(true)
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await depositTokenMock.givenMethodReturnUint(balanceOf, 0)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawDeposit()
const depositTransfer = token.contract.methods.transfer(accounts[0], 10).encodeABI()
assert.equal(await depositTokenMock.invocationCountForCalldata.call(depositTransfer), 1)
})
it("returns all deposits of the sender in the same withdraw", async () => {
const token = await ERC20.new()
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenAnyReturnBool(true)
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await dxMock.givenAnyReturnUint(20)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
await instance.deposit(10)
await instance.deposit(10)
await increaseTimeBy(100, web3)
await depositTokenMock.givenAnyReturnBool(true)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await depositTokenMock.givenMethodReturnUint(balanceOf, 0)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawDeposit()
const depositTransfer = token.contract.methods.transfer(accounts[0], 20).encodeABI()
assert.equal(await depositTokenMock.invocationCountForCalldata.call(depositTransfer), 1)
})
it("cannot withdraw already withdrawn amount", async () => {
const token = await ERC20.new()
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenAnyReturnBool(true)
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const reponseType = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, reponseType)
await instance.deposit(10)
await increaseTimeBy(100, web3)
await depositTokenMock.givenAnyReturnBool(true)
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await depositTokenMock.givenMethodReturnUint(balanceOf, 0)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawDeposit()
await instance.withdrawDeposit()
const depositTransfer = token.contract.methods.transfer(accounts[0], 10).encodeABI()
assert.equal(await depositTokenMock.invocationCountForCalldata.call(depositTransfer), 1)
const emptyTransfer = token.contract.methods.transfer(accounts[0], 0).encodeABI()
assert.equal(await depositTokenMock.invocationCountForCalldata.call(emptyTransfer), 1)
})
it("cannot withdraw while pooling is running", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await truffleAssert.reverts(instance.withdrawDeposit(), "Funds not yet withdrawn from dx")
})
it("fails if deposit retransfer fails", async () => {
const token = await ERC20.new()
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenAnyReturnBool(true)
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const reponseType = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, reponseType)
await instance.deposit(10)
await increaseTimeBy(100, web3)
await depositTokenMock.givenAnyReturnBool(false)
await truffleAssert.reverts(instance.withdrawDeposit())
})
})
describe("triggerMGNunlockAndClaimTokens()", () => {
it("unlocksMGN, claims and withdraws depositToken", async () => {
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const token = await ERC20.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 1
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await dxMock.givenAnyReturnUint(42)
const tupleResponse = (abi.rawEncode(["uint", "uint"], [42, 0]))
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await increaseTimeBy(poolingTime, web3)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await instance.triggerMGNunlockAndClaimTokens()
await depositTokenMock.givenAnyReturnUint(0)
const withdraw = dx.contract.methods.withdraw(depositTokenMock.address, 42).encodeABI()
assert.equal(await dxMock.invocationCountForCalldata.call(withdraw), 1)
})
it("makes a deposit shortly before pooling ending and checks that it is accounted correctly", async () => {
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 10
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(10)
// return balance of 10
const tupleResponse = (abi.rawEncode(["uint", "uint"], [10, 0]))
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
// return the as balances another 10
await depositTokenMock.givenAnyReturnUint(10)
await increaseTimeBy(poolingTime, web3)
await instance.triggerMGNunlockAndClaimTokens()
assert.equal(await instance.totalDeposit.call(), 10+10)
})
it("fails if still pooling", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await truffleAssert.reverts(instance.triggerMGNunlockAndClaimTokens(), "Pooling period is not yet over.")
})
it("does not throw if pool has zero balance in dutchX", async () => {
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const token = await ERC20.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 0
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await dxMock.givenAnyReturnUint(42)
const tupleResponse = (abi.rawEncode(["uint", "uint"], [42, 0]))
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const balances = dx.contract.methods.balances(accounts[0], accounts[0]).encodeABI()
await dxMock.givenMethodReturnUint(balances, 0)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await instance.triggerMGNunlockAndClaimTokens()
})
it("checks that function can not be called twice", async () => {
const dx = await DutchExchange.new()
const mgn = await TokenFRT.new()
const token = await ERC20.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 0
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await dxMock.givenAnyReturnUint(42)
const tupleResponse = (abi.rawEncode(["uint", "uint"], [42, 0]))
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const balances = dx.contract.methods.balances(accounts[0], accounts[0]).encodeABI()
await dxMock.givenMethodReturnUint(balances, 0)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await instance.triggerMGNunlockAndClaimTokens()
await truffleAssert.reverts(instance.triggerMGNunlockAndClaimTokens(), "Pooling period is not yet over.")
})
it("fails if last auction still running", async () => {
const token = await ERC20.new()
const dx = await DutchExchange.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 1000
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
const balanceOf = token.contract.methods.balanceOf(accounts[0]).encodeABI()
await depositTokenMock.givenAnyReturnBool(true)
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await dxMock.givenAnyReturnUint(2)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
await instance.deposit(10)
await instance.participateInAuction()
await dxMock.givenAnyReturnUint(3)
await dxMock.givenMethodReturn(postSellOrder, abi.rawEncode(["uint", "uint"], [3, 0]))
await instance.participateInAuction()
await increaseTimeBy(1000, web3)
await truffleAssert.reverts(instance.triggerMGNunlockAndClaimTokens(), "Last auction is still running")
})
})
describe("withdrawUnlockedMagnoliaFromDx()", () => {
it("fails if still pooling", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await truffleAssert.reverts(instance.withdrawUnlockedMagnoliaFromDx(), "Unlocking not yet triggered")
})
it("checks that function can not be called twice", async () => {
const mgn = await TokenFRT.new()
const token = await ERC20.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const dx = await DutchExchange.new()
const poolingTime = 1000
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const balanceOf = mgn.contract.methods.balanceOf(accounts[0]).encodeABI()
await mgnTokenMock.givenAnyReturnBool(true)
await mgnTokenMock.givenMethodReturnUint(balanceOf, 100)
await instance.deposit(10)
await instance.participateInAuction()
await instance.participateInAuction()
await increaseTimeBy(poolingTime, web3)
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await depositTokenMock.givenMethodReturnUint(balanceOf, 2)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawUnlockedMagnoliaFromDx()
await truffleAssert.reverts(instance.withdrawUnlockedMagnoliaFromDx(), "Unlocking not yet triggered")
})
})
describe("withdrawMagnolia()", () => {
it("withdraws the right amount of MGN", async () => {
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const dx = await DutchExchange.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const balanceOf = mgn.contract.methods.balanceOf(accounts[0]).encodeABI()
await mgnTokenMock.givenAnyReturnBool(true)
await mgnTokenMock.givenMethodReturnUint(balanceOf, 100)
await instance.deposit(10)
await instance.participateInAuction()
await instance.participateInAuction()
await increaseTimeBy(101, web3)
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawUnlockedMagnoliaFromDx()
assert.equal(await instance.totalMgn.call(), 100)
await instance.withdrawDeposit()
await instance.withdrawMagnolia()
const mgnTransfer = mgn.contract.methods.transfer(accounts[0], 100).encodeABI()
assert.equal(await mgnTokenMock.invocationCountForCalldata.call(mgnTransfer), 1)
})
it("fails if Magnolia was not unlocked", async () => {
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await truffleAssert.reverts(instance.withdrawMagnolia(), "MGN has not been unlocked, yet")
})
it("fails if deposit was not withdrawn", async () => {
const mgn = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const dx = await DutchExchange.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
await mgnTokenMock.givenAnyReturnUint(100)
await instance.deposit(10)
await instance.participateInAuction()
await instance.participateInAuction()
await increaseTimeBy(100, web3)
await dxMock.givenAnyReturnUint(42)
const unlockTokens = mgn.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawUnlockedMagnoliaFromDx()
assert.equal(await instance.totalMgn.call(), 100)
await truffleAssert.reverts(instance.withdrawMagnolia(), "Withdraw deposits first")
})
it("fails if MGN transfer fails", async () => {
const mgnToken = await TokenFRT.new()
const depositTokenMock = await MockContract.new()
const secondaryTokenMock = await MockContract.new()
const mgnTokenMock = await MockContract.new()
const dxMock = await MockContract.new()
const dx = await DutchExchange.new()
const poolingTime = 100
const instance = await DxMgnPool.new(depositTokenMock.address, secondaryTokenMock.address, mgnTokenMock.address, dxMock.address, poolingTime)
await depositTokenMock.givenAnyReturnBool(true)
await dxMock.givenAnyReturnUint(10)
const postSellOrder = dx.contract.methods.postSellOrder(accounts[0], accounts[0], 0, 0).encodeABI()
const tupleResponse = (abi.rawEncode(["uint", "uint"], [2, 0]))
await dxMock.givenMethodReturn(postSellOrder, tupleResponse)
const claimSellerFunds = dx.contract.methods.claimSellerFunds(accounts[0], accounts[0], accounts[0], 0).encodeABI()
await dxMock.givenMethodReturn(claimSellerFunds, tupleResponse)
const balanceOf = mgnToken.contract.methods.balanceOf(accounts[0]).encodeABI()
await mgnTokenMock.givenAnyReturnBool(false)
await mgnTokenMock.givenMethodReturnUint(balanceOf, 100)
await instance.deposit(10)
await instance.participateInAuction()
await instance.participateInAuction()
await increaseTimeBy(100, web3)
const unlockTokens = mgnToken.contract.methods.unlockTokens().encodeABI()
await mgnTokenMock.givenMethodReturn(unlockTokens, tupleResponse)
await instance.triggerMGNunlockAndClaimTokens()
await instance.withdrawUnlockedMagnoliaFromDx()
await instance.withdrawDeposit()
await truffleAssert.reverts(instance.withdrawMagnolia())
})
})
})