diff --git a/contracts/standard/arbitration/Linguo.sol b/contracts/standard/arbitration/Linguo.sol index f10164bc..17f685d8 100644 --- a/contracts/standard/arbitration/Linguo.sol +++ b/contracts/standard/arbitration/Linguo.sol @@ -25,6 +25,7 @@ contract Linguo is Arbitrable { using CappedMath for uint; /* *** Contract variables *** */ + uint8 public constant VERSION_ID = 0; // Value that represents the version of the contract. The value is incremented each time the new version is deployed. Range for LinguoETH: 0-127, LinguoToken: 128-255. uint public constant MULTIPLIER_DIVISOR = 10000; // Divisor parameter for multipliers. uint constant NOT_PAYABLE_VALUE = (2**256-2)/2; // A value depositor won't be able to pay. diff --git a/contracts/standard/arbitration/LinguoToken.sol b/contracts/standard/arbitration/LinguoToken.sol index f1350fc5..ab8dcd69 100644 --- a/contracts/standard/arbitration/LinguoToken.sol +++ b/contracts/standard/arbitration/LinguoToken.sol @@ -1,6 +1,6 @@ /** * @authors: [@unknownunknown1] - * @reviewers: [@remedcu] + * @reviewers: [@remedcu*] * @auditors: [] * @bounties: [] * @deployments: [] @@ -14,6 +14,12 @@ import "./Arbitrable.sol"; import "../../libraries/CappedMath.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; +interface IUniswapV2Pair { + + function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast); + +} + /** @title LinguoToken * Linguo is a decentralized platform where anyone can submit a document for translation and have it translated by freelancers. * It has no platform fees and disputes about translation quality are handled by Kleros jurors. @@ -27,6 +33,7 @@ contract LinguoToken is Arbitrable { using CappedMath for uint; /* *** Contract variables *** */ + uint8 public constant VERSION_ID = 128; // Value that represents the version of the contract. The value is incremented each time the new version is deployed. Range for LinguoToken: 128-255, LinguoETH: 0-127. uint public constant MULTIPLIER_DIVISOR = 10000; // Divisor parameter for multipliers. uint constant NOT_PAYABLE_VALUE = (2**256-2)/2; // A value depositor won't be able to pay. @@ -63,10 +70,12 @@ contract LinguoToken is Arbitrable { mapping(address => uint[3]) contributions; // Maps contributors to their contributions for each side. } + ERC20 public WETH; // Address of the wETH token contract. It's required for token -> ETH conversion. + address public uniswapFactory; // Address of the UniswapPair factory. It's required for token -> ETH conversion. + address public governor; // The governor of the contract. uint public reviewTimeout; // Time in seconds, during which the submitted translation can be challenged. - uint public translatorBaseDeposit; // The base deposit a translator must pay to self-assign a task, in wei. - uint public challengerBaseDeposit; // The base deposit a challenger must pay to challenge a translation, in wei. + uint public translationMultiplier; // Multiplier for calculating the value of the deposit translator must pay to self-assign a task. // All multipliers below are in basis points. uint public sharedStakeMultiplier; // Multiplier for calculating the appeal fee that must be paid by submitter in the case where there is no winner or loser (e.g. when the arbitrator ruled "refuse to arbitrate"). @@ -129,9 +138,10 @@ contract LinguoToken is Arbitrable { /** @dev Constructor. * @param _arbitrator The arbitrator of the contract. * @param _arbitratorExtraData Extra data for the arbitrator. + * @param _WETH Address of the WETH token contract. + * @param _uniswapFactory Address of the UniswapPair factory contract. * @param _reviewTimeout Time in seconds during which a translation can be challenged. - * @param _translatorBaseDeposit The base deposit that must be paid in order to self-assign the task, in wei. - * @param _challengerBaseDeposit The base deposit that must be paid in order to challenge the translation, in wei. + * @param _translationMultiplier Multiplier for calculating translator's deposit. In basis points. * @param _sharedStakeMultiplier Multiplier of the appeal cost that submitter must pay for a round when there is no winner/loser in the previous round. In basis points. * @param _winnerStakeMultiplier Multiplier of the appeal cost that the winner has to pay for a round. In basis points. * @param _loserStakeMultiplier Multiplier of the appeal cost that the loser has to pay for a round. In basis points. @@ -139,17 +149,19 @@ contract LinguoToken is Arbitrable { constructor( Arbitrator _arbitrator, bytes _arbitratorExtraData, + ERC20 _WETH, + address _uniswapFactory, uint _reviewTimeout, - uint _translatorBaseDeposit, - uint _challengerBaseDeposit, + uint _translationMultiplier, uint _sharedStakeMultiplier, uint _winnerStakeMultiplier, uint _loserStakeMultiplier ) public Arbitrable(_arbitrator, _arbitratorExtraData){ governor = msg.sender; + WETH = _WETH; + uniswapFactory = _uniswapFactory; reviewTimeout = _reviewTimeout; - translatorBaseDeposit = _translatorBaseDeposit; - challengerBaseDeposit = _challengerBaseDeposit; + translationMultiplier = _translationMultiplier; sharedStakeMultiplier = _sharedStakeMultiplier; winnerStakeMultiplier = _winnerStakeMultiplier; loserStakeMultiplier = _loserStakeMultiplier; @@ -173,18 +185,11 @@ contract LinguoToken is Arbitrable { reviewTimeout = _reviewTimeout; } - /** @dev Changes the base deposit for translator. - * @param _translatorBaseDeposit A new value of the base deposit required for self-assigning the task, in wei. + /** @dev Changes the multiplier for translator's deposit. + * @param _translationMultiplier A new value of the multiplier for calculating translator's deposit. In basis points. */ - function changeTranslatorBaseDeposit(uint _translatorBaseDeposit) public onlyGovernor { - translatorBaseDeposit = _translatorBaseDeposit; - } - - /** @dev Changes the base deposit for challenger. - * @param _challengerBaseDeposit A new value of the base deposit required for challenging, in wei. - */ - function changeChallengerBaseDeposit(uint _challengerBaseDeposit) public onlyGovernor { - challengerBaseDeposit = _challengerBaseDeposit; + function changeTranslationMultiplier(uint _translationMultiplier) public onlyGovernor { + translationMultiplier = _translationMultiplier; } /** @dev Changes the percentage of arbitration fees that must be paid by parties as a fee stake if there was no winner and loser in the previous round. @@ -253,8 +258,10 @@ contract LinguoToken is Arbitrable { require(now - task.lastInteraction <= task.submissionTimeout, "The deadline has already passed."); uint price = task.minPrice + (task.maxPrice - task.minPrice) * (now - task.lastInteraction) / task.submissionTimeout; + + uint priceETH = getTaskPriceInETH(_taskID); uint arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData); - uint translatorDeposit = arbitrationCost.addCap(translatorBaseDeposit); + uint translatorDeposit = arbitrationCost.addCap((translationMultiplier.mulCap(priceETH)) / MULTIPLIER_DIVISOR); require(task.status == Status.Created, "Task has already been assigned or reimbursed."); require(msg.value >= translatorDeposit, "Not enough ETH to reach the required deposit value."); @@ -264,7 +271,7 @@ contract LinguoToken is Arbitrable { // Update requester's deposit since we reimbursed him the difference between maximal and actual price. task.requesterDeposit = price; - task.sumDeposit += translatorDeposit; + task.sumDeposit = translatorDeposit; uint remainder = msg.value - translatorDeposit; msg.sender.send(remainder); @@ -301,7 +308,7 @@ contract LinguoToken is Arbitrable { uint sumDeposit = task.sumDeposit; task.requesterDeposit = 0; task.sumDeposit = 0; - // Requester gets his deposit back and also the deposit of the translator, if there was one. Note that sumDeposit can't contain challenger's deposit until the task is in DisputeCreated status. + // Requester gets his deposit back and also the deposit of the translator, if there was one. task.requester.send(sumDeposit); require(task.token.transfer(task.requester, requesterDeposit), "The token transfer was unsuccessful."); @@ -316,7 +323,7 @@ contract LinguoToken is Arbitrable { require(task.status == Status.AwaitingReview, "The task is in the wrong status."); require(now - task.lastInteraction > reviewTimeout, "The review phase hasn't passed yet."); task.status = Status.Resolved; - // Translator gets the price of the task and his deposit back. Note that sumDeposit can't contain challenger's deposit until the task is in DisputeCreated status. + // Translator gets the price of the task and his deposit back. address translator = task.parties[uint(Party.Translator)]; uint requesterDeposit = task.requesterDeposit; uint sumDeposit = task.sumDeposit; @@ -335,12 +342,12 @@ contract LinguoToken is Arbitrable { function challengeTranslation(uint _taskID, string _evidence) external payable { Task storage task = tasks[_taskID]; + // The challenger should only deposit the value of arbitration cost. uint arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData); - uint challengeDeposit = arbitrationCost.addCap(challengerBaseDeposit); require(task.status == Status.AwaitingReview, "The task is in the wrong status."); require(now - task.lastInteraction <= reviewTimeout, "The review phase has already passed."); - require(msg.value >= challengeDeposit, "Not enough ETH to cover challenge deposit."); + require(msg.value >= arbitrationCost, "Not enough ETH to cover challenge deposit."); task.status = Status.DisputeCreated; task.parties[uint(Party.Challenger)] = msg.sender; @@ -348,9 +355,9 @@ contract LinguoToken is Arbitrable { task.disputeID = arbitrator.createDispute.value(arbitrationCost)(2, arbitratorExtraData); disputeIDtoTaskID[task.disputeID] = _taskID; task.rounds.length++; - task.sumDeposit = task.sumDeposit.addCap(challengeDeposit).subCap(arbitrationCost); + // We don't change sumDeposit because adding challenger's deposit while subtracting arbitration fee will give 0 as a result. - uint remainder = msg.value - challengeDeposit; + uint remainder = msg.value - arbitrationCost; msg.sender.send(remainder); emit Dispute(arbitrator, task.disputeID, _taskID, _taskID); @@ -521,7 +528,7 @@ contract LinguoToken is Arbitrable { task.sumDeposit = 0; if(_ruling == uint(Party.None)){ - // The value of sumDeposit is split among parties in this case. If the sum is uneven the value of 1 wei can be burnt. + // The value of sumDeposit is split among parties in this case. If it's uneven the value of 1 wei can be burnt. sumDeposit = sumDeposit / 2; task.parties[uint(Party.Translator)].send(sumDeposit); task.parties[uint(Party.Challenger)].send(sumDeposit); @@ -592,8 +599,11 @@ contract LinguoToken is Arbitrable { if (now - task.lastInteraction > task.submissionTimeout || task.status != Status.Created) { deposit = NOT_PAYABLE_VALUE; } else { + uint priceETH = getTaskPriceInETH(_taskID); + uint arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData); - deposit = arbitrationCost.addCap(translatorBaseDeposit); + deposit = arbitrationCost.addCap((translationMultiplier.mulCap(priceETH)) / MULTIPLIER_DIVISOR); + } } @@ -606,12 +616,11 @@ contract LinguoToken is Arbitrable { if (now - task.lastInteraction > reviewTimeout || task.status != Status.AwaitingReview) { deposit = NOT_PAYABLE_VALUE; } else { - uint arbitrationCost = arbitrator.arbitrationCost(arbitratorExtraData); - deposit = arbitrationCost.addCap(challengerBaseDeposit); + deposit = arbitrator.arbitrationCost(arbitratorExtraData); } } - /** @dev Gets the current price of a specified task. + /** @dev Gets the current price of a specified task. Returns 0 if the task can no longer be assigned. * @param _taskID The ID of the task. * @return price The price of the task. */ @@ -624,6 +633,27 @@ contract LinguoToken is Arbitrable { } } + /** @dev Gets the current price of a specified task in ETH. Returns 0 if the task can no longer be assigned. + * @param _taskID The ID of the task. + * @return price The price of the task. + */ + function getTaskPriceInETH(uint _taskID) public view returns (uint priceETH) { + Task storage task = tasks[_taskID]; + uint tokenPrice = task.minPrice + (task.maxPrice - task.minPrice) * (now - task.lastInteraction) / task.submissionTimeout; + if (now - task.lastInteraction > task.submissionTimeout || task.status != Status.Created) + priceETH = 0; + else if (task.token == WETH) + priceETH = tokenPrice; + else { + (ERC20 token0, ERC20 token1) = task.token < WETH ? (task.token, WETH) : (WETH, task.token); + IUniswapV2Pair pair = IUniswapV2Pair(address(uint(keccak256(abi.encodePacked(hex"ff", uniswapFactory, keccak256(abi.encodePacked(token0, token1)), hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f"))))); + (uint reserve0, uint reserve1,) = pair.getReserves(); + (uint reserveA, uint reserveB) = token0 == task.token ? (reserve0, reserve1) : (reserve1, reserve0); + require(reserveA > 0 && reserveB > 0, "Could not calculate the price."); + priceETH = tokenPrice.mulCap(reserveB) / reserveA; + } + } + /** @dev Gets the total number of created tasks. * @return The number of created tasks. */ diff --git a/test/linguo-token.js b/test/linguo-token.js index 5c3681f3..a8951c46 100644 --- a/test/linguo-token.js +++ b/test/linguo-token.js @@ -22,12 +22,12 @@ contract('Linguo', function(accounts) { const translator = accounts[2] const challenger = accounts[3] const other = accounts[4] + const fakeFactory = accounts[5] const arbitrationFee = 1000 const arbitratorExtraData = 0x85 const appealTimeOut = 100 const reviewTimeout = 2400 - const translatorBaseDeposit = 3000 - const challengerBaseDeposit = 2000 + const translationMultiplier = 1000 const sharedMultiplier = 5000 const winnerMultiplier = 3000 const loserMultiplier = 7000 @@ -39,6 +39,7 @@ contract('Linguo', function(accounts) { const submissionTimeout = 3600 let arbitrator let linguo + let token let MULTIPLIER_DIVISOR let taskTx let currentTime @@ -54,25 +55,29 @@ contract('Linguo', function(accounts) { await arbitrator.changeArbitrator(arbitrator.address) + token = await ERC20Mock.new(requester, tokenBalance, { from: governor }) + linguo = await Linguo.new( arbitrator.address, arbitratorExtraData, + token.address, // WETH. + fakeFactory, // uniswapFactory. Can't test the uniswap getters because of the old compiler, so set it random value. reviewTimeout, - translatorBaseDeposit, - challengerBaseDeposit, + translationMultiplier, sharedMultiplier, winnerMultiplier, loserMultiplier, { from: governor } ) - token = await ERC20Mock.new(requester, tokenBalance, { from: governor }) await token.approve(linguo.address, 50000000, { from: requester }) MULTIPLIER_DIVISOR = (await linguo.MULTIPLIER_DIVISOR()).toNumber() currentTime = await latestTime() + + // Create the task using WETH token address, to test the simplest getPriceInETH scenario. taskTx = await linguo.createTask( currentTime + submissionTimeout, token.address, @@ -92,10 +97,11 @@ contract('Linguo', function(accounts) { it('Should set the correct values in constructor', async () => { assert.equal(await linguo.arbitrator(), arbitrator.address) assert.equal(await linguo.arbitratorExtraData(), arbitratorExtraData) + assert.equal(await linguo.WETH(), token.address) + assert.equal(await linguo.uniswapFactory(), fakeFactory) assert.equal(await linguo.governor(), governor) assert.equal(await linguo.reviewTimeout(), reviewTimeout) - assert.equal(await linguo.translatorBaseDeposit(), translatorBaseDeposit) - assert.equal(await linguo.challengerBaseDeposit(), challengerBaseDeposit) + assert.equal(await linguo.translationMultiplier(), translationMultiplier) assert.equal(await linguo.sharedStakeMultiplier(), sharedMultiplier) assert.equal(await linguo.winnerStakeMultiplier(), winnerMultiplier) assert.equal(await linguo.loserStakeMultiplier(), loserMultiplier) @@ -175,9 +181,9 @@ contract('Linguo', function(accounts) { ) }) - it('Should not be possible to deposit less than min price when creating a task', async () => { + it('Should not be possible for max price to be less than min price', async () => { currentTime = await latestTime() - // Invert max and min price to make sure it throws when less than min price is deposited. + // Invert max and min price to make sure it throws. await expectThrow( linguo.createTask( currentTime + submissionTimeout, @@ -218,10 +224,20 @@ contract('Linguo', function(accounts) { 'Contract returns incorrect task price' ) + const priceETH = (await linguo.getTaskPriceInETH(0)).toNumber() assert.equal( - (await linguo.getDepositValue(0)).toNumber(), - 4000, // Arbitration fee + translation base deposit (1000 + 3000). - 'Contract returns incorrect translator deposit' + priceETH, + priceLinguo.toNumber(), + 'Contract returns incorrect price in ETH' + ) + + const deposit = Math.floor( + arbitrationFee + (priceETH * translationMultiplier) / MULTIPLIER_DIVISOR + ) + const depositLinguo = await linguo.getDepositValue(0) + assert( + Math.abs(depositLinguo.toNumber() - deposit) <= deposit / 100, + 'Contract returns incorrect required deposit' ) }) @@ -233,6 +249,14 @@ contract('Linguo', function(accounts) { 0, 'Contract returns incorrect task price after submission timeout ended' ) + + const priceETH = await linguo.getTaskPriceInETH(0) + assert.equal( + priceETH.toNumber(), + 0, + 'Contract returns incorrect task price in ETH after submission timeout ended' + ) + const deposit = NOT_PAYABLE_VALUE const depositLinguo = await linguo.getDepositValue(0) assert.equal( @@ -246,7 +270,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) const expectedTaskPrice = 0 @@ -264,6 +288,13 @@ contract('Linguo', function(accounts) { expectedDeposit, 'Contract returns incorrect required deposit if status is not `created`' ) + + const priceETH = await linguo.getTaskPriceInETH(0) + assert.equal( + priceETH.toNumber(), + 0, + 'Contract returns incorrect task price in ETH if status is not `created`' + ) }) it('Should not be possible to pay less than required deposit value', async () => { @@ -280,7 +311,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() const assignTx = await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) assert.equal( @@ -297,7 +328,7 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) const newBalance = await token.balanceOf(requester) @@ -313,10 +344,10 @@ contract('Linguo', function(accounts) { translator, 'The translator was not set up properly' ) - assert.equal( - task[8].toNumber(), - 4000, - 'Translator deposit was not set up correctly' + + assert( + Math.abs(task[8].toNumber() - requiredDeposit) <= requiredDeposit / 100, + 'The translator deposit was not set up properly' ) }) @@ -324,7 +355,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await increaseTime(submissionTimeout - secondsPassed + 1) await expectThrow( @@ -338,7 +369,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await expectThrow( linguo.submitTranslation(0, 'ipfs:/X', { @@ -351,7 +382,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) submissionTx = await linguo.submitTranslation(0, 'ipfs:/X', { from: translator @@ -402,7 +433,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await increaseTime(submissionTimeout + 1) const oldBalance = await web3.eth.getBalance(requester) @@ -414,7 +445,7 @@ contract('Linguo', function(accounts) { const newTokenBalance = await token.balanceOf(requester) assert.equal( newBalance.toString(), - oldBalance.plus(requiredDeposit).toString(), + oldBalance.plus(task[8].toNumber()).toString(), 'The requester was not reimbursed correctly' ) assert.equal( @@ -429,7 +460,7 @@ contract('Linguo', function(accounts) { }) it('Should not be possible to reimburse if submission timeout has not passed', async () => { - await increaseTime(submissionTimeout - secondsPassed - 1) + await increaseTime(submissionTimeout - secondsPassed - 5) await expectThrow(linguo.reimburseRequester(0)) }) @@ -437,7 +468,7 @@ contract('Linguo', function(accounts) { const requiredDeposit = (await linguo.getDepositValue(0)).toNumber() await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) await increaseTime(reviewTimeout + 1) @@ -456,9 +487,7 @@ contract('Linguo', function(accounts) { assert.equal( newBalance.toString(), - oldBalance - .plus(4000) // Translator deposit - .toString(), + oldBalance.plus(task[8].toNumber()).toString(), 'The translator did not get his deposit back' ) assert.equal( @@ -476,12 +505,12 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) await expectThrow(linguo.acceptTranslation(0)) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit @@ -495,11 +524,11 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee // Check that reverts if the deposit is lower than expected await expectThrow( @@ -508,6 +537,11 @@ contract('Linguo', function(accounts) { value: challengerDeposit - 1 }) ) + + let task = await linguo.tasks(0) + const expectedSumDeposit = + challengerDeposit + task[8].toNumber() - arbitrationFee + const challengeTx = await linguo.challengeTranslation( 0, 'ChallengeEvidence', @@ -553,7 +587,7 @@ contract('Linguo', function(accounts) { 'The Evidence event has wrong evidence string' ) - const task = await linguo.tasks(0) + task = await linguo.tasks(0) const taskInfo = await linguo.getTaskParties(0) assert.equal( taskInfo[2], @@ -563,7 +597,7 @@ contract('Linguo', function(accounts) { assert.equal( task[8].toNumber(), - 6000, // Translator deposit + challenger deposit - arbitration fees: 4000 + 3000 - 1000 + expectedSumDeposit, 'The sum of translator and challenger deposits was not set up properly' ) @@ -586,10 +620,10 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await increaseTime(reviewTimeout + 1) await expectThrow( linguo.challengeTranslation(0, '', { @@ -604,17 +638,20 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) - let task = await linguo.tasks(0) + await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit }) + let task = await linguo.tasks(0) + const halfSumDeposit = Math.floor(task[8].toNumber() / 2) + const oldTokenBalanceRequester = await token.balanceOf(requester) const oldBalance1 = await web3.eth.getBalance(translator) @@ -637,13 +674,13 @@ contract('Linguo', function(accounts) { assert.equal( newBalance1.toString(), - oldBalance1.plus(3000).toString(), // 3000 is a half of the sum of the eth deposits. + oldBalance1.plus(halfSumDeposit).toString(), 'The translator was not paid correctly' ) assert.equal( newBalance2.toString(), - oldBalance2.plus(3000).toString(), + oldBalance2.plus(halfSumDeposit).toString(), 'The challenger was not paid correctly' ) @@ -658,17 +695,18 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) - let task = await linguo.tasks(0) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit }) + let task = await linguo.tasks(0) + const oldTokenBalanceRequester = await token.balanceOf(requester) const oldBalance1 = await web3.eth.getBalance(translator) const oldBalance2 = await web3.eth.getBalance(challenger) @@ -691,7 +729,7 @@ contract('Linguo', function(accounts) { assert.equal( newBalance1.toString(), - oldBalance1.plus(6000).toString(), + oldBalance1.plus(task[8].toNumber()).toString(), 'The translator was not paid correctly' ) assert.equal( @@ -715,17 +753,19 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) - let task = await linguo.tasks(0) + await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit }) + let task = await linguo.tasks(0) + const oldTokenBalanceRequester = await token.balanceOf(requester) const oldBalance1 = await web3.eth.getBalance(translator) const oldBalance2 = await web3.eth.getBalance(challenger) @@ -760,7 +800,7 @@ contract('Linguo', function(accounts) { assert.equal( newBalance2.toString(), - oldBalance2.plus(6000).toString(), + oldBalance2.plus(task[8].toNumber()).toString(), 'The challenger was not paid correctly' ) assert.equal( @@ -779,7 +819,7 @@ contract('Linguo', function(accounts) { await expectThrow( linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) ) }) @@ -790,11 +830,11 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit @@ -901,11 +941,11 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit @@ -943,7 +983,7 @@ contract('Linguo', function(accounts) { assert.equal( newBalance1.toString(), - oldBalance1.plus(6000).toString(), + oldBalance1.plus(task[8].toNumber()).toString(), 'The translator was not paid correctly' ) assert.equal( @@ -967,11 +1007,11 @@ contract('Linguo', function(accounts) { await linguo.assignTask(0, { from: translator, - value: requiredDeposit + value: requiredDeposit + 1000 }) await linguo.submitTranslation(0, 'ipfs:/X', { from: translator }) - const challengerDeposit = (await linguo.getChallengeValue(0)).toNumber() + const challengerDeposit = arbitrationFee await linguo.challengeTranslation(0, '', { from: challenger, value: challengerDeposit @@ -1076,35 +1116,20 @@ contract('Linguo', function(accounts) { 22, 'Incorrect review timeout value' ) - // translator deposit + // translationMultiplier await expectThrow( - linguo.changeTranslatorBaseDeposit(44, { + linguo.changeTranslationMultiplier(44, { from: other }) ) - await linguo.changeTranslatorBaseDeposit(44, { + await linguo.changeTranslationMultiplier(44, { from: governor }) assert.equal( - (await linguo.translatorBaseDeposit()).toNumber(), + (await linguo.translationMultiplier()).toNumber(), 44, - 'Incorrect translatorBaseDeposit value' - ) - // challenger deposit - await expectThrow( - linguo.changeChallengerBaseDeposit(88, { - from: other - }) - ) - await linguo.changeChallengerBaseDeposit(88, { - from: governor - }) - - assert.equal( - (await linguo.challengerBaseDeposit()).toNumber(), - 88, - 'Incorrect challengerBaseDeposit value' + 'Incorrect translationMultiplier value' ) // shared multiplier await expectThrow(