├── .gitignore ├── scripts └── LaqiracePayment-script.js ├── contracts ├── mocks │ └── QuoteToken.sol ├── TransferHelper.sol └── LaqiracePayment.sol ├── package.json ├── hardhat.config.js └── test └── LaqiracePayment-test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | 7 | #Hardhat files 8 | cache 9 | artifacts 10 | -------------------------------------------------------------------------------- /scripts/LaqiracePayment-script.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | 3 | async function main() { 4 | } 5 | 6 | main() 7 | .then(() => process.exit(0)) 8 | .catch((error) => { 9 | console.error(error); 10 | process.exit(1); 11 | }); 12 | -------------------------------------------------------------------------------- /contracts/mocks/QuoteToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; 5 | 6 | contract QuoteToken is ERC20 { 7 | constructor(string memory _name, string memory _symbol, uint256 _initialSupply) ERC20(_name, _symbol) { 8 | mint(msg.sender, _initialSupply); 9 | } 10 | 11 | function mint(address _to, uint256 _amount) public { 12 | _mint(_to, _amount); 13 | } 14 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newProject", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@nomiclabs/hardhat-ethers": "^2.0.0", 14 | "@nomiclabs/hardhat-waffle": "^2.0.0", 15 | "@openzeppelin/test-helpers": "^0.5.15", 16 | "chai": "^4.2.0", 17 | "ethereum-waffle": "^3.0.0", 18 | "ethers": "^5.0.0", 19 | "hardhat": "^2.9.9" 20 | }, 21 | "dependencies": { 22 | "@openzeppelin/contracts": "^4.6.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | 3 | // This is a sample Hardhat task. To learn how to create your own go to 4 | // https://hardhat.org/guides/create-task.html 5 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 6 | const accounts = await hre.ethers.getSigners(); 7 | 8 | for (const account of accounts) { 9 | console.log(account.address); 10 | } 11 | }); 12 | 13 | // You need to export an object to set up your config 14 | // Go to https://hardhat.org/config/ to learn more 15 | 16 | /** 17 | * @type import('hardhat/config').HardhatUserConfig 18 | */ 19 | module.exports = { 20 | solidity: "0.8.4", 21 | }; 22 | -------------------------------------------------------------------------------- /contracts/TransferHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.7.0; 4 | 5 | // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false 6 | library TransferHelper { 7 | address public constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 8 | 9 | function safeTransfer( 10 | address token, 11 | address to, 12 | uint256 value 13 | ) internal { 14 | // bytes4(keccak256(bytes('transfer(address,uint256)'))); 15 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); 16 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); 17 | } 18 | 19 | function safeTransferFrom( 20 | address token, 21 | address from, 22 | address to, 23 | uint256 value 24 | ) internal { 25 | // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); 26 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); 27 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); 28 | } 29 | 30 | function safeTransferETH(address to, uint256 value) internal { 31 | (bool success, ) = to.call{value: value}(new bytes(0)); 32 | require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/LaqiracePayment.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import '@openzeppelin/contracts/access/Ownable.sol'; 5 | 6 | import './TransferHelper.sol'; 7 | 8 | interface IBEP20 { 9 | /** 10 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 11 | * 12 | * Returns a boolean value indicating whether the operation succeeded. 13 | * 14 | * Emits a {Transfer} event. 15 | */ 16 | 17 | function transfer(address recipient, uint256 amount) external returns (bool); 18 | } 19 | 20 | contract LaqiracePayment is Ownable { 21 | struct AssetStatus { 22 | bool isAvailable; 23 | uint256 minAmount; 24 | } 25 | 26 | struct ReqStatus { 27 | bool isPending; 28 | address player; 29 | address quoteToken; 30 | uint256 amount; 31 | } 32 | 33 | mapping(address => AssetStatus) private quoteToken; 34 | mapping(uint256 => ReqStatus) private withdrawReqs; 35 | 36 | address private paymentReceiver; 37 | uint256 private reqCounter; 38 | uint256[] private pendingReqs; 39 | uint256 private reqFee; 40 | address private operator; 41 | 42 | event DepositToken(address player, address quoteToken, uint256 amount); 43 | event WithdrawRequest(address player, address quoteToken, uint256 amount, uint256 reqCounter); 44 | event RequestConfirmed(address player, address quoteToken, uint256 amount, uint256 reqCounter); 45 | event RequestRejected(address player, address quoteToken, uint256 amount, uint256 reqCounter); 46 | 47 | constructor(address _paymentReceiver, uint256 _reqFee, address _operator) { 48 | paymentReceiver = _paymentReceiver; 49 | reqFee = _reqFee; 50 | operator = _operator; 51 | } 52 | 53 | function deposit(address _quoteToken, address _player, uint256 _amount) public payable returns (bool) { 54 | require(quoteToken[_quoteToken].isAvailable, 'Payment method is not allowed'); 55 | 56 | uint256 transferredAmount = msg.value; 57 | if (_quoteToken == TransferHelper.ETH_ADDRESS) { 58 | require(transferredAmount >= _amount, 'Insufficient paid amount'); 59 | uint256 diff = transferredAmount - _amount; 60 | if (diff > 0) 61 | TransferHelper.safeTransferETH(_msgSender(), diff); 62 | } else { 63 | require(transferredAmount == 0, 'Invalid payment method'); 64 | TransferHelper.safeTransferFrom(_quoteToken, _msgSender(), paymentReceiver, _amount); 65 | } 66 | emit DepositToken(_player, _quoteToken, _amount); 67 | return true; 68 | } 69 | 70 | function withdrawRequest(address _quoteToken, uint256 _amount) public payable returns (bool) { 71 | require(quoteToken[_quoteToken].isAvailable, 'Asset is not allowed'); 72 | require(_amount >= quoteToken[_quoteToken].minAmount, 'Amount is lower than minimum required'); 73 | uint256 transferredAmount = msg.value; 74 | require(transferredAmount >= reqFee, 'Insufficient request fee'); 75 | 76 | uint256 diff = transferredAmount - reqFee; 77 | if (diff > 0) 78 | TransferHelper.safeTransferETH(_msgSender(), diff); 79 | reqCounter++; 80 | withdrawReqs[reqCounter].isPending = true; 81 | withdrawReqs[reqCounter].player = _msgSender(); 82 | withdrawReqs[reqCounter].quoteToken = _quoteToken; 83 | withdrawReqs[reqCounter].amount = _amount; 84 | pendingReqs.push(reqCounter); 85 | emit WithdrawRequest(_msgSender(), _quoteToken, _amount, reqCounter); 86 | return true; 87 | } 88 | 89 | function confirmRequest(uint256 _reqNo) public returns (bool) { 90 | require(_msgSender() == operator || _msgSender() == owner(), 'Permission denied!'); 91 | require(withdrawReqs[_reqNo].isPending, 'Not a pending request'); 92 | address asset = withdrawReqs[_reqNo].quoteToken; 93 | if (asset == TransferHelper.ETH_ADDRESS) { 94 | TransferHelper.safeTransferETH(withdrawReqs[_reqNo].player, withdrawReqs[_reqNo].amount); 95 | } else { 96 | TransferHelper.safeTransfer(withdrawReqs[_reqNo].quoteToken, withdrawReqs[_reqNo].player, withdrawReqs[_reqNo].amount); 97 | } 98 | withdrawReqs[_reqNo].isPending = false; 99 | delUintFromArray(_reqNo, pendingReqs); 100 | emit RequestConfirmed(withdrawReqs[_reqNo].player, withdrawReqs[_reqNo].quoteToken, withdrawReqs[_reqNo].amount, _reqNo); 101 | return true; 102 | } 103 | 104 | function rejectRequest(uint256 _reqNo) public returns (bool) { 105 | require(_msgSender() == operator || _msgSender() == owner(), 'Permission denied!'); 106 | require(withdrawReqs[_reqNo].isPending, 'Not a pending request'); 107 | withdrawReqs[_reqNo].isPending = false; 108 | delUintFromArray(_reqNo, pendingReqs); 109 | emit RequestRejected(withdrawReqs[_reqNo].player, withdrawReqs[_reqNo].quoteToken, withdrawReqs[_reqNo].amount, _reqNo); 110 | return true; 111 | } 112 | 113 | function addQuoteToken(address _quoteToken, uint256 _minAmount) public onlyOwner returns (bool) { 114 | require(!quoteToken[_quoteToken].isAvailable, 'Asset already exists'); 115 | quoteToken[_quoteToken].isAvailable = true; 116 | quoteToken[_quoteToken].minAmount = _minAmount; 117 | return true; 118 | } 119 | 120 | function removeQuoteToken(address _quoteToken) public onlyOwner returns (bool) { 121 | require(quoteToken[_quoteToken].isAvailable, 'Asset already does not exist'); 122 | delete quoteToken[_quoteToken]; 123 | return true; 124 | } 125 | 126 | function updateMinAmount(address _quoteToken, uint256 _minAmount) public onlyOwner returns (bool) { 127 | quoteToken[_quoteToken].minAmount = _minAmount; 128 | return true; 129 | } 130 | 131 | function updatePaymentReceiver(address _paymentReceiver) public onlyOwner returns (bool) { 132 | paymentReceiver = _paymentReceiver; 133 | return true; 134 | } 135 | 136 | function updateReqFee(uint256 _reqFee) public onlyOwner returns (bool) { 137 | reqFee = _reqFee; 138 | return true; 139 | } 140 | 141 | function changeOperator(address _newOperator) public onlyOwner returns (bool) { 142 | operator = _newOperator; 143 | return true; 144 | } 145 | 146 | function transferAnyBEP20(address _tokenAddress, address _to, uint256 _amount) public virtual onlyOwner returns (bool) { 147 | IBEP20(_tokenAddress).transfer(_to, _amount); 148 | return true; 149 | } 150 | 151 | function adminWithdrawal(uint256 _amount) public virtual onlyOwner { 152 | address payable _owner = payable(owner()); 153 | _owner.transfer(_amount); 154 | } 155 | 156 | function getPaymentReceiver() public view returns (address) { 157 | return paymentReceiver; 158 | } 159 | 160 | function checkQuoteToken(address _quoteToken) public view returns (AssetStatus memory) { 161 | return quoteToken[_quoteToken]; 162 | } 163 | 164 | function getPendingReqs() public view returns (uint256[] memory) { 165 | return pendingReqs; 166 | } 167 | 168 | function getReqStatus(uint256 _reqNo) public view returns (ReqStatus memory) { 169 | return withdrawReqs[_reqNo]; 170 | } 171 | 172 | function getReqFee() public view returns (uint256) { 173 | return reqFee; 174 | } 175 | 176 | function getOperator() public view returns (address) { 177 | return operator; 178 | } 179 | 180 | function delUintFromArray( 181 | uint256 _element, 182 | uint256[] storage array 183 | ) internal virtual { 184 | // delete the element 185 | uint256 len = array.length; 186 | uint256 j = 0; 187 | for (uint256 i = 0; i <= len - 1; i++) { 188 | if (array[i] == _element) { 189 | j = i; 190 | break; 191 | } 192 | } 193 | for (j; j < len - 1; j++) { 194 | array[j] = array[j + 1]; 195 | } 196 | array.pop(); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /test/LaqiracePayment-test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require("chai"); 2 | const { ethers, waffle } = require("hardhat"); 3 | const { constants } = require('@openzeppelin/test-helpers'); 4 | const providerWaff = waffle.provider; 5 | 6 | describe("LaqiracePayment", function () { 7 | let laqiracePayment, LaqiracePaymentContract, quoteToken, QuoteToken; 8 | let paymentReceiver, player, requestFee, operator, owner, anotherAddress, minAmount; 9 | 10 | const ETH_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; 11 | 12 | requestFee = '20000000000000000'; 13 | minAmount = '2000000000000000000'; 14 | 15 | beforeEach(async function () { 16 | [ owner, operator, anotherAddress, player ] = await ethers.getSigners(); 17 | paymentReceiver = ethers.Wallet.createRandom(); 18 | 19 | laqiracePayment = await ethers.getContractFactory("LaqiracePayment"); 20 | quoteToken = await ethers.getContractFactory('QuoteToken'); 21 | 22 | QuoteToken = await quoteToken.deploy('Quote', 'QT', '10000000000000000000000000000'); 23 | LaqiracePaymentContract = await laqiracePayment.deploy(paymentReceiver.address, requestFee, operator.address); 24 | }); 25 | 26 | 27 | it('Constructor', async function () { 28 | // paymentReceiver 29 | expect(await LaqiracePaymentContract.getPaymentReceiver()).to.equal(paymentReceiver.address); 30 | // request fee 31 | expect(await LaqiracePaymentContract.getReqFee()).to.equal(requestFee); 32 | // operator 33 | expect(await LaqiracePaymentContract.getOperator()).to.equal(operator.address); 34 | }); 35 | 36 | describe('addQuoteToken', function() { 37 | it('Trigger', async function () { 38 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 39 | const result = await LaqiracePaymentContract.checkQuoteToken(QuoteToken.address); 40 | expect(result['isAvailable']).to.true; 41 | expect(result['minAmount']).to.equal(minAmount); 42 | }); 43 | 44 | it('ERRORS', async function () { 45 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 46 | await expect(LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount)).to.revertedWith('Asset already exists'); 47 | }); 48 | 49 | it('onlyOwner', async function () { 50 | await expect(LaqiracePaymentContract.connect(anotherAddress).addQuoteToken(QuoteToken.address, minAmount)).to.revertedWith('Ownable: caller is not the owner'); 51 | }); 52 | }); 53 | 54 | describe('removeQuoteToken', function () { 55 | it('Trigger', async function () { 56 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 57 | await LaqiracePaymentContract.removeQuoteToken(QuoteToken.address); 58 | const result = await LaqiracePaymentContract.checkQuoteToken(QuoteToken.address); 59 | expect(result['isAvailable']).to.false; 60 | expect(result['minAmount']).to.equal(0); 61 | }); 62 | 63 | it('ERRORS', async function () { 64 | expect((await LaqiracePaymentContract.checkQuoteToken(QuoteToken.address))['isAvailable']).to.false; 65 | await expect(LaqiracePaymentContract.removeQuoteToken(QuoteToken.address)).to.revertedWith('Asset already does not exist'); 66 | }); 67 | }); 68 | 69 | describe('updateMinAmount', function () { 70 | let newAmount = '5000000000000000000'; 71 | it('Trigger', async function () { 72 | await LaqiracePaymentContract.updateMinAmount(QuoteToken.address, newAmount); 73 | expect((await LaqiracePaymentContract.checkQuoteToken(QuoteToken.address))['minAmount']).to.equal(newAmount); 74 | }); 75 | }); 76 | 77 | describe('updatePaymentReceiver', function () { 78 | let newPaymentReceiver = ethers.Wallet.createRandom(); 79 | it('Trigger', async function () { 80 | await LaqiracePaymentContract.updatePaymentReceiver(newPaymentReceiver.address); 81 | expect(await LaqiracePaymentContract.getPaymentReceiver()).to.equal(newPaymentReceiver.address); 82 | }); 83 | 84 | it('Zero address', async function () { 85 | await LaqiracePaymentContract.updatePaymentReceiver(constants.ZERO_ADDRESS); 86 | expect(await LaqiracePaymentContract.getPaymentReceiver()).to.equal(constants.ZERO_ADDRESS); 87 | }); 88 | }); 89 | 90 | describe('deposit', function () { 91 | let invalidAmount = '20000'; 92 | it('Trigger -> Token', async function () { 93 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 94 | await QuoteToken.transfer(player.address, minAmount); 95 | await QuoteToken.connect(player).approve(LaqiracePaymentContract.address, minAmount); 96 | 97 | await expect(LaqiracePaymentContract.connect(player).deposit(QuoteToken.address, player.address, minAmount)).to.emit(LaqiracePaymentContract, 'DepositToken').withArgs(player.address, QuoteToken.address, minAmount); 98 | 99 | let contractBalance = await QuoteToken.balanceOf(LaqiracePaymentContract.address); 100 | let paymentReceiverBalance = await QuoteToken.balanceOf(paymentReceiver.address); 101 | expect(contractBalance).to.equal(0); 102 | expect(paymentReceiverBalance).to.equal(minAmount); 103 | }); 104 | 105 | it('Trigger -> BNB (payback)', async function () { 106 | let extraAmount = '5000000000000000000'; 107 | await LaqiracePaymentContract.addQuoteToken(ETH_ADDRESS, minAmount); 108 | await LaqiracePaymentContract.connect(player).deposit(ETH_ADDRESS, player.address, minAmount, {value: extraAmount}); 109 | expect(await providerWaff.getBalance(LaqiracePaymentContract.address)).to.equal(minAmount); 110 | }); 111 | 112 | it('ERRORS', async function () { 113 | await expect(LaqiracePaymentContract.deposit(QuoteToken.address, player.address, minAmount)).to.revertedWith('Payment method is not allowed'); 114 | await LaqiracePaymentContract.addQuoteToken(ETH_ADDRESS, minAmount); 115 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 116 | await expect(LaqiracePaymentContract.deposit(ETH_ADDRESS, player.address, minAmount, {value: invalidAmount})).to.revertedWith('Insufficient paid amount'); 117 | await expect(LaqiracePaymentContract.deposit(QuoteToken.address, player.address, minAmount, {value: minAmount})).to.revertedWith('Invalid payment method'); 118 | }); 119 | }); 120 | 121 | describe('withdrawRequest', async function () { 122 | let withdrawReqestAmount = minAmount; 123 | let expectedRequestId = 1; 124 | it('Trigger -> (BNB, Token)', async function () { 125 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 126 | await LaqiracePaymentContract.addQuoteToken(ETH_ADDRESS, minAmount); 127 | await expect(LaqiracePaymentContract.connect(player).withdrawRequest(QuoteToken.address, withdrawReqestAmount, {value: requestFee})).to.emit(LaqiracePaymentContract, 'WithdrawRequest').withArgs(player.address, QuoteToken.address, withdrawReqestAmount, expectedRequestId); 128 | let LaqiracePaymentContractBalance = await providerWaff.getBalance(LaqiracePaymentContract.address); 129 | expect(LaqiracePaymentContractBalance).to.equal(requestFee); 130 | 131 | let requestStatus = await LaqiracePaymentContract.getReqStatus(expectedRequestId); 132 | expect(requestStatus['isPending']).to.true; 133 | expect(requestStatus['player']).to.equal(player.address); 134 | expect(requestStatus['quoteToken']).to.equal(QuoteToken.address); 135 | expect(requestStatus['amount']).to.equal(withdrawReqestAmount); 136 | 137 | expect((await LaqiracePaymentContract.getPendingReqs()).length).to.equal(1); 138 | expect((await LaqiracePaymentContract.getPendingReqs())[0]).to.equal(1); 139 | 140 | await LaqiracePaymentContract.connect(player).withdrawRequest(ETH_ADDRESS, withdrawReqestAmount, {value: requestFee}); 141 | expect((await LaqiracePaymentContract.getPendingReqs()).length).to.equal(2); 142 | expect((await LaqiracePaymentContract.getPendingReqs())[1]).to.equal(2); 143 | }); 144 | 145 | it('ERRORS', async function () { 146 | let invalidAmount = '200000'; 147 | let insufficientRequestFeeAmount = '100'; 148 | await expect(LaqiracePaymentContract.connect(player).withdrawRequest(QuoteToken.address, withdrawReqestAmount, {value: requestFee})).to.revertedWith('Asset is not allowed'); 149 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 150 | await expect(LaqiracePaymentContract.connect(player).withdrawRequest(QuoteToken.address, invalidAmount, {value: requestFee})).to.revertedWith('Amount is lower than minimum required'); 151 | await expect(LaqiracePaymentContract.connect(player).withdrawRequest(QuoteToken.address, minAmount, {value: insufficientRequestFeeAmount})).to.revertedWith('Insufficient request fee'); 152 | }) 153 | }); 154 | 155 | describe('confirmRequest', function () { 156 | let expectedRequestId = 1; 157 | it('Trigger', async function () { 158 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 159 | await LaqiracePaymentContract.connect(player).withdrawRequest(QuoteToken.address, minAmount, {value: requestFee}); 160 | 161 | // player -> approve -> deposit -> withdrawRequest -> confirmRequest (admin) 162 | await QuoteToken.transfer(LaqiracePaymentContract.address, minAmount); 163 | let requestStatus = await LaqiracePaymentContract.getReqStatus(expectedRequestId); 164 | expect(await QuoteToken.balanceOf(player.address)).to.equal(0); 165 | await expect(LaqiracePaymentContract.connect(operator).confirmRequest(expectedRequestId)).to.emit(LaqiracePaymentContract, 'RequestConfirmed').withArgs(requestStatus['player'], requestStatus['quoteToken'], requestStatus['amount'], expectedRequestId); 166 | expect(await QuoteToken.balanceOf(player.address)).to.equal(minAmount); 167 | 168 | let newRequestStatus = await LaqiracePaymentContract.getReqStatus(expectedRequestId); 169 | expect(newRequestStatus['isPending']).to.false; 170 | expect(requestStatus['player']).to.equal(player.address); 171 | expect(requestStatus['quoteToken']).to.equal(QuoteToken.address); 172 | expect(requestStatus['amount']).to.equal(minAmount); 173 | 174 | expect((await LaqiracePaymentContract.getPendingReqs()).length).to.equal(0); 175 | }); 176 | 177 | it('ERRORS', async function () { 178 | let reqId = 1; 179 | await expect(LaqiracePaymentContract.connect(player).confirmRequest(reqId)).to.revertedWith('Permission denied!'); 180 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 181 | await QuoteToken.transfer(LaqiracePaymentContract.address, minAmount); 182 | await expect(LaqiracePaymentContract.connect(operator).confirmRequest(reqId)).to.revertedWith('Not a pending request'); 183 | }); 184 | }); 185 | 186 | describe('rejectRequest', function () { 187 | it('Trigger', async function () { 188 | let expectedRequestId = 1; 189 | await LaqiracePaymentContract.addQuoteToken(QuoteToken.address, minAmount); 190 | await LaqiracePaymentContract.connect(player).withdrawRequest(QuoteToken.address, minAmount, {value: requestFee}); 191 | 192 | let requestStatus = await LaqiracePaymentContract.getReqStatus(expectedRequestId); 193 | await expect(LaqiracePaymentContract.rejectRequest(expectedRequestId)).to.emit(LaqiracePaymentContract, 'RequestRejected').withArgs(requestStatus['player'], requestStatus['quoteToken'], requestStatus['amount'], '1'); 194 | 195 | let newRequestStatus = await LaqiracePaymentContract.getReqStatus(expectedRequestId); 196 | expect(newRequestStatus['isPending']).to.false; 197 | expect(requestStatus['player']).to.equal(player.address); 198 | expect(requestStatus['quoteToken']).to.equal(QuoteToken.address); 199 | expect(requestStatus['amount']).to.equal(minAmount); 200 | 201 | expect((await LaqiracePaymentContract.getPendingReqs()).length).to.equal(0); 202 | }); 203 | 204 | it('ERRORS', async function () { 205 | let reqId = 1; 206 | await expect(LaqiracePaymentContract.connect(player).rejectRequest(reqId)).to.revertedWith('Permission denied!'); 207 | await expect(LaqiracePaymentContract.connect(owner).rejectRequest(reqId)).to.revertedWith('Not a pending request'); 208 | }); 209 | }); 210 | }); --------------------------------------------------------------------------------