Adding price to deposits and add token transfers
This commit is contained in:
parent
1298b0d368
commit
0f35eec623
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ coverage.json
|
|||||||
#Hardhat files
|
#Hardhat files
|
||||||
cache
|
cache
|
||||||
artifacts/build-info
|
artifacts/build-info
|
||||||
|
artifacts/@openzeppelin
|
4
artifacts/contracts/mockToken.sol/MockToken.dbg.json
Normal file
4
artifacts/contracts/mockToken.sol/MockToken.dbg.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"_format": "hh-sol-dbg-1",
|
||||||
|
"buildInfo": "../../build-info/5f0db55f399477fd77a196dfab69a373.json"
|
||||||
|
}
|
292
artifacts/contracts/mockToken.sol/MockToken.json
Normal file
292
artifacts/contracts/mockToken.sol/MockToken.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"_format": "hh-sol-dbg-1",
|
"_format": "hh-sol-dbg-1",
|
||||||
"buildInfo": "../../build-info/e53d155f4d4e8ba3d5f49011e7166818.json"
|
"buildInfo": "../../build-info/5ce31c4ec8418c4fef71a52ed732efd0.json"
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
11
contracts/mockToken.sol
Normal file
11
contracts/mockToken.sol
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.9;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
|
|
||||||
|
contract MockToken is ERC20 {
|
||||||
|
|
||||||
|
constructor(uint256 supply) ERC20("MockBRL", "MBRL") {
|
||||||
|
_mint(msg.sender, supply);
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,14 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.8.9;
|
pragma solidity ^0.8.9;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
contract P2PIX {
|
contract P2PIX {
|
||||||
|
|
||||||
event DepositAdded(address indexed seller, bytes32 depositID, address token, uint256 amount);
|
event DepositAdded(address indexed seller, bytes32 depositID, address token, uint256 price, uint256 amount);
|
||||||
event DepositClosed(address indexed seller, bytes32 depositID);
|
event DepositClosed(address indexed seller, bytes32 depositID);
|
||||||
event DepositWithdrawn(address indexed seller, bytes32 depositID, uint256 amount);
|
event DepositWithdrawn(address indexed seller, bytes32 depositID, uint256 amount);
|
||||||
|
event DepositPriceChanged(bytes32 indexed depositID, uint256 price);
|
||||||
event LockAdded(address indexed buyer, bytes32 indexed lockID, bytes32 depositID, uint256 amount);
|
event LockAdded(address indexed buyer, bytes32 indexed lockID, bytes32 depositID, uint256 amount);
|
||||||
event LockReleased(address indexed buyer, bytes32 lockId);
|
event LockReleased(address indexed buyer, bytes32 lockId);
|
||||||
event LockReturned(address indexed buyer, bytes32 lockId);
|
event LockReturned(address indexed buyer, bytes32 lockId);
|
||||||
@ -14,6 +17,7 @@ contract P2PIX {
|
|||||||
address seller;
|
address seller;
|
||||||
address token; // ERC20 stable token address
|
address token; // ERC20 stable token address
|
||||||
uint256 remaining; // Remaining tokens available
|
uint256 remaining; // Remaining tokens available
|
||||||
|
uint256 price; // Price in R$ per token
|
||||||
bool valid; // Could be invalidated by the seller
|
bool valid; // Could be invalidated by the seller
|
||||||
string pixTarget; // The PIX account for the seller receive transactions
|
string pixTarget; // The PIX account for the seller receive transactions
|
||||||
}
|
}
|
||||||
@ -23,7 +27,8 @@ contract P2PIX {
|
|||||||
address targetAddress; // Where goes the tokens when validated
|
address targetAddress; // Where goes the tokens when validated
|
||||||
address relayerAddress; // Relayer address that facilitated this transaction
|
address relayerAddress; // Relayer address that facilitated this transaction
|
||||||
uint256 relayerPremium; // Amount to be paid for relayer
|
uint256 relayerPremium; // Amount to be paid for relayer
|
||||||
uint256 amount; // Amount to be transfered to buyer
|
uint256 amount; // Amount to be tranfered via PIX
|
||||||
|
uint256 locked; // Amount locked in tokens from deposit
|
||||||
uint256 expirationBlock; // If not paid at this block will be expired
|
uint256 expirationBlock; // If not paid at this block will be expired
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,15 +60,16 @@ contract P2PIX {
|
|||||||
function deposit(
|
function deposit(
|
||||||
address token,
|
address token,
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
|
uint256 price,
|
||||||
string calldata pixTarget
|
string calldata pixTarget
|
||||||
) public returns (bytes32 depositID){
|
) public returns (bytes32 depositID){
|
||||||
depositID = keccak256(abi.encodePacked(pixTarget, amount));
|
depositID = keccak256(abi.encodePacked(pixTarget, amount));
|
||||||
require(!mapDeposits[depositID].valid, 'P2PIX: Deposit already exist and it is still valid');
|
require(!mapDeposits[depositID].valid, 'P2PIX: Deposit already exist and it is still valid');
|
||||||
// TODO Prevent seller to use same depositID
|
IERC20 t = IERC20(token);
|
||||||
// TODO Transfer tokens to this address
|
t.transferFrom(msg.sender, address(this), amount);
|
||||||
Deposit memory d = Deposit(msg.sender, token, amount, true, pixTarget);
|
Deposit memory d = Deposit(msg.sender, token, amount, price, true, pixTarget);
|
||||||
mapDeposits[depositID] = d;
|
mapDeposits[depositID] = d;
|
||||||
emit DepositAdded(msg.sender, depositID, token, amount);
|
emit DepositAdded(msg.sender, depositID, token, price, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vendedor pode invalidar da ordem de venda impedindo novos locks na mesma (isso não afeta nenhum lock que esteja ativo).
|
// Vendedor pode invalidar da ordem de venda impedindo novos locks na mesma (isso não afeta nenhum lock que esteja ativo).
|
||||||
@ -89,7 +95,7 @@ contract P2PIX {
|
|||||||
unlockExpired(expiredLocks);
|
unlockExpired(expiredLocks);
|
||||||
Deposit storage d = mapDeposits[depositID];
|
Deposit storage d = mapDeposits[depositID];
|
||||||
require(d.valid, "P2PIX: Deposit not valid anymore");
|
require(d.valid, "P2PIX: Deposit not valid anymore");
|
||||||
require(d.remaining > amount, "P2PIX: Not enough remaining");
|
require(d.remaining > amount/d.price, "P2PIX: Not enough remaining");
|
||||||
lockID = keccak256(abi.encodePacked(depositID, amount, targetAddress));
|
lockID = keccak256(abi.encodePacked(depositID, amount, targetAddress));
|
||||||
require(
|
require(
|
||||||
mapLocks[lockID].expirationBlock < block.number,
|
mapLocks[lockID].expirationBlock < block.number,
|
||||||
@ -101,6 +107,7 @@ contract P2PIX {
|
|||||||
relayerAddress,
|
relayerAddress,
|
||||||
relayerPremium,
|
relayerPremium,
|
||||||
amount,
|
amount,
|
||||||
|
amount/d.price,
|
||||||
block.number+defaultLockBlocks
|
block.number+defaultLockBlocks
|
||||||
);
|
);
|
||||||
mapLocks[lockID] = l;
|
mapLocks[lockID] = l;
|
||||||
@ -120,6 +127,7 @@ contract P2PIX {
|
|||||||
// TODO Check if lockID exists and is enabled
|
// TODO Check if lockID exists and is enabled
|
||||||
// TODO **Prevenir que um Pix não relacionado ao APP seja usado pois tem o mesmo destino
|
// TODO **Prevenir que um Pix não relacionado ao APP seja usado pois tem o mesmo destino
|
||||||
Lock storage l = mapLocks[lockID];
|
Lock storage l = mapLocks[lockID];
|
||||||
|
Deposit storage d = mapDeposits[l.depositID];
|
||||||
bytes32 message = keccak256(abi.encodePacked(
|
bytes32 message = keccak256(abi.encodePacked(
|
||||||
mapDeposits[l.depositID].pixTarget,
|
mapDeposits[l.depositID].pixTarget,
|
||||||
l.amount,
|
l.amount,
|
||||||
@ -128,13 +136,21 @@ contract P2PIX {
|
|||||||
require(!usedTransactions[message], "Transaction already used to unlock payment.");
|
require(!usedTransactions[message], "Transaction already used to unlock payment.");
|
||||||
address signer = ecrecover(message, v, r, s);
|
address signer = ecrecover(message, v, r, s);
|
||||||
require(validBacenSigners[signer], "Signer is not a valid signer.");
|
require(validBacenSigners[signer], "Signer is not a valid signer.");
|
||||||
// TODO Transfer token to l.target
|
IERC20 t = IERC20(d.token);
|
||||||
// TODO Transfer relayer fees to relayer
|
t.transfer(l.targetAddress, l.locked-l.relayerPremium);
|
||||||
|
if (l.relayerPremium > 0) t.transfer(l.relayerAddress, l.relayerPremium);
|
||||||
l.amount = 0;
|
l.amount = 0;
|
||||||
usedTransactions[message] = true;
|
usedTransactions[message] = true;
|
||||||
emit LockReleased(l.targetAddress, lockID);
|
emit LockReleased(l.targetAddress, lockID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change price for deposit amount
|
||||||
|
function changeDepositPrice(bytes32 depositID, uint256 price) public {
|
||||||
|
Deposit storage d = mapDeposits[depositID];
|
||||||
|
d.price = price;
|
||||||
|
emit DepositPriceChanged(depositID, price);
|
||||||
|
}
|
||||||
|
|
||||||
// Unlock expired locks
|
// Unlock expired locks
|
||||||
function unlockExpired(bytes32[] calldata lockIDs) internal {
|
function unlockExpired(bytes32[] calldata lockIDs) internal {
|
||||||
uint256 locksSize = lockIDs.length;
|
uint256 locksSize = lockIDs.length;
|
||||||
@ -153,11 +169,13 @@ contract P2PIX {
|
|||||||
bytes32[] calldata expiredLocks
|
bytes32[] calldata expiredLocks
|
||||||
) public onlySeller(depositID) {
|
) public onlySeller(depositID) {
|
||||||
unlockExpired(expiredLocks);
|
unlockExpired(expiredLocks);
|
||||||
if (mapDeposits[depositID].valid) cancelDeposit(depositID);
|
Deposit storage d = mapDeposits[depositID];
|
||||||
// TODO Transfer remaining tokens back to the seller
|
if (d.valid) cancelDeposit(depositID);
|
||||||
|
IERC20 token = IERC20(d.token);
|
||||||
|
token.transfer(d.seller, d.remaining);
|
||||||
// Withdraw remaining tokens from mapDeposit[depositID]
|
// Withdraw remaining tokens from mapDeposit[depositID]
|
||||||
uint256 amount = mapDeposits[depositID].remaining;
|
uint256 amount = d.remaining;
|
||||||
mapDeposits[depositID].remaining = 0;
|
d.remaining = 0;
|
||||||
emit DepositWithdrawn(msg.sender, depositID, amount);
|
emit DepositWithdrawn(msg.sender, depositID, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
deploys/localhost.json
Normal file
8
deploys/localhost.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"signers": [
|
||||||
|
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||||
|
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
||||||
|
],
|
||||||
|
"p2pix": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
|
||||||
|
"token": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"
|
||||||
|
}
|
@ -3,4 +3,10 @@ require("@nomiclabs/hardhat-waffle");
|
|||||||
/** @type import('hardhat/config').HardhatUserConfig */
|
/** @type import('hardhat/config').HardhatUserConfig */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
solidity: "0.8.17",
|
solidity: "0.8.17",
|
||||||
|
networks: {
|
||||||
|
hardhat: {
|
||||||
|
blockGasLimit: 30000000,
|
||||||
|
//hardfork: 'london'
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -8,6 +8,9 @@
|
|||||||
"name": "p2pix-smart-contracts",
|
"name": "p2pix-smart-contracts",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@openzeppelin/contracts": "^4.7.3"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
@ -1756,6 +1759,11 @@
|
|||||||
"hardhat": "^2.0.0"
|
"hardhat": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@openzeppelin/contracts": {
|
||||||
|
"version": "4.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz",
|
||||||
|
"integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw=="
|
||||||
|
},
|
||||||
"node_modules/@resolver-engine/core": {
|
"node_modules/@resolver-engine/core": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz",
|
||||||
@ -17914,6 +17922,11 @@
|
|||||||
"@types/web3": "1.0.19"
|
"@types/web3": "1.0.19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@openzeppelin/contracts": {
|
||||||
|
"version": "4.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz",
|
||||||
|
"integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw=="
|
||||||
|
},
|
||||||
"@resolver-engine/core": {
|
"@resolver-engine/core": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz",
|
||||||
|
@ -20,5 +20,8 @@
|
|||||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"hardhat": "^2.12.0"
|
"hardhat": "^2.12.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@openzeppelin/contracts": "^4.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
scripts/1-deploy-p2pix.js
Normal file
31
scripts/1-deploy-p2pix.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const { network } = require("hardhat");
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
|
||||||
|
let deploysJson = {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = fs.readFileSync(`./deploys/${network.name}.json`, {encoding:"utf-8"});
|
||||||
|
deploysJson = JSON.parse(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Error loading Master address: ', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const P2PIX = await ethers.getContractFactory("P2PIX");
|
||||||
|
const p2pix = await P2PIX.deploy(2, deploysJson.signers);
|
||||||
|
await p2pix.deployed();
|
||||||
|
|
||||||
|
deploysJson.p2pix = p2pix.address
|
||||||
|
console.log("🚀 P2PIX Deployed:", p2pix.address);
|
||||||
|
|
||||||
|
fs.writeFileSync(`./deploys/${network.name}.json`, JSON.stringify(deploysJson, undefined, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
31
scripts/2-deploy-mockToken.js
Normal file
31
scripts/2-deploy-mockToken.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const { network } = require("hardhat");
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
|
||||||
|
let deploysJson = {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = fs.readFileSync(`./deploys/${network.name}.json`, {encoding:"utf-8"});
|
||||||
|
deploysJson = JSON.parse(data);
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Error loading Master address: ', err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ERC20Factory = await ethers.getContractFactory("MockToken");
|
||||||
|
const erc20 = await ERC20Factory.deploy(ethers.utils.parseEther('20000000', 'wei'));
|
||||||
|
await erc20.deployed();
|
||||||
|
|
||||||
|
deploysJson.token = erc20.address
|
||||||
|
console.log("🚀 Mock Token Deployed:", erc20.address);
|
||||||
|
|
||||||
|
fs.writeFileSync(`./deploys/${network.name}.json`, JSON.stringify(deploysJson, undefined, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
@ -5,33 +5,61 @@ describe("P2PIX deposit test", function () {
|
|||||||
|
|
||||||
let owner, wallet2, wallet3, wallet4;
|
let owner, wallet2, wallet3, wallet4;
|
||||||
let p2pix; // Contract instance
|
let p2pix; // Contract instance
|
||||||
|
let erc20; // Token instance
|
||||||
let depositID;
|
let depositID;
|
||||||
|
|
||||||
it("Will deploy contracts", async function () {
|
it("Will deploy contracts", async function () {
|
||||||
|
|
||||||
[owner, wallet2, wallet3, wallet4] = await ethers.getSigners();
|
[owner, wallet2, wallet3, wallet4] = await ethers.getSigners();
|
||||||
|
|
||||||
|
const ERC20Factory = await ethers.getContractFactory("MockToken");
|
||||||
|
erc20 = await ERC20Factory.deploy(ethers.utils.parseEther('20000000', 'wei'));
|
||||||
|
await erc20.deployed();
|
||||||
|
|
||||||
|
// Check initial balance
|
||||||
|
expect(await erc20.balanceOf(owner.address)).to.equal(ethers.utils.parseEther('20000000', 'wei'));
|
||||||
|
|
||||||
const P2PIX = await ethers.getContractFactory("P2PIX");
|
const P2PIX = await ethers.getContractFactory("P2PIX");
|
||||||
p2pix = await P2PIX.deploy(2, [owner.address, wallet2.address]);
|
p2pix = await P2PIX.deploy(2, [owner.address, wallet2.address]);
|
||||||
await p2pix.deployed();
|
await p2pix.deployed();
|
||||||
|
|
||||||
// Verify values at deployment
|
// Verify values at deployment
|
||||||
expect(await p2pix.validBacenSigners(owner.address)).to.equal(true);
|
expect(await p2pix.validBacenSigners(owner.address)).to.equal(true);
|
||||||
expect(await p2pix.validBacenSigners(wallet2.address)).to.equal(true);
|
expect(await p2pix.validBacenSigners(wallet2.address)).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should allow create a deposit", async function () {
|
it("Should allow create a deposit", async function () {
|
||||||
const transaction = await p2pix.deposit(ethers.constants.AddressZero, 1000, 'SELLER PIX KEY');
|
|
||||||
depositID = ethers.utils.solidityKeccak256(['string', 'uint256'], ['SELLER PIX KEY', 1000])
|
let transaction = await erc20.approve(p2pix.address,ethers.utils.parseEther('1000'));
|
||||||
|
await expect(transaction).to.emit(erc20, 'Approval').withArgs(
|
||||||
|
owner.address,
|
||||||
|
p2pix.address,
|
||||||
|
ethers.utils.parseEther('1000')
|
||||||
|
)
|
||||||
|
|
||||||
|
transaction = await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
ethers.utils.parseEther('1000'),
|
||||||
|
ethers.utils.parseEther('0.99'),
|
||||||
|
'SELLER PIX KEY'
|
||||||
|
);
|
||||||
|
depositID = ethers.utils.solidityKeccak256(['string', 'uint256'], ['SELLER PIX KEY', ethers.utils.parseEther('1000')])
|
||||||
await expect(transaction).to.emit(p2pix, 'DepositAdded').withArgs(
|
await expect(transaction).to.emit(p2pix, 'DepositAdded').withArgs(
|
||||||
owner.address,
|
owner.address,
|
||||||
depositID,
|
depositID,
|
||||||
ethers.constants.AddressZero,
|
erc20.address,
|
||||||
1000
|
ethers.utils.parseEther('0.99'),
|
||||||
|
ethers.utils.parseEther('1000')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Should prevent create same deposit", async function () {
|
it("Should prevent create same deposit", async function () {
|
||||||
await expect(p2pix.deposit(ethers.constants.AddressZero, 1000, 'SELLER PIX KEY'))
|
await expect(p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
ethers.utils.parseEther('1000'),
|
||||||
|
ethers.utils.parseEther('0.99'),
|
||||||
|
'SELLER PIX KEY'
|
||||||
|
))
|
||||||
.to.be.revertedWith('P2PIX: Deposit already exist and it is still valid');
|
.to.be.revertedWith('P2PIX: Deposit already exist and it is still valid');
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -44,13 +72,27 @@ describe("P2PIX deposit test", function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("Should allow recreate the deposit", async function () {
|
it("Should allow recreate the deposit", async function () {
|
||||||
const transaction = await p2pix.deposit(ethers.constants.AddressZero, 1000, 'SELLER PIX KEY');
|
|
||||||
depositID = ethers.utils.solidityKeccak256(['string', 'uint256'], ['SELLER PIX KEY', 1000])
|
let transaction = await erc20.approve(p2pix.address,ethers.utils.parseEther('1000'));
|
||||||
|
await expect(transaction).to.emit(erc20, 'Approval').withArgs(
|
||||||
|
owner.address,
|
||||||
|
p2pix.address,
|
||||||
|
ethers.utils.parseEther('1000')
|
||||||
|
)
|
||||||
|
|
||||||
|
transaction = await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
ethers.utils.parseEther('1000'),
|
||||||
|
ethers.utils.parseEther('0.99'),
|
||||||
|
'SELLER PIX KEY'
|
||||||
|
);
|
||||||
|
depositID = ethers.utils.solidityKeccak256(['string', 'uint256'], ['SELLER PIX KEY', ethers.utils.parseEther('1000')])
|
||||||
await expect(transaction).to.emit(p2pix, 'DepositAdded').withArgs(
|
await expect(transaction).to.emit(p2pix, 'DepositAdded').withArgs(
|
||||||
owner.address,
|
owner.address,
|
||||||
depositID,
|
depositID,
|
||||||
ethers.constants.AddressZero,
|
erc20.address,
|
||||||
1000
|
ethers.utils.parseEther('0.99'),
|
||||||
|
ethers.utils.parseEther('1000')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -67,7 +109,7 @@ describe("P2PIX deposit test", function () {
|
|||||||
await expect(transaction).to.emit(p2pix, 'DepositWithdrawn').withArgs(
|
await expect(transaction).to.emit(p2pix, 'DepositWithdrawn').withArgs(
|
||||||
owner.address,
|
owner.address,
|
||||||
depositID,
|
depositID,
|
||||||
1000
|
ethers.utils.parseEther('1000')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
78
test/2-lock-release.test.js
Normal file
78
test/2-lock-release.test.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const { expect } = require("chai");
|
||||||
|
const { ethers } = require("hardhat");
|
||||||
|
|
||||||
|
describe("P2PIX lock/release test", function () {
|
||||||
|
|
||||||
|
let owner, wallet2, wallet3, wallet4;
|
||||||
|
let p2pix; // Contract instance
|
||||||
|
let erc20; // Token instance
|
||||||
|
let depositID;
|
||||||
|
|
||||||
|
it("Will deploy contracts", async function () {
|
||||||
|
|
||||||
|
[owner, wallet2, wallet3, wallet4] = await ethers.getSigners();
|
||||||
|
|
||||||
|
const ERC20Factory = await ethers.getContractFactory("MockToken");
|
||||||
|
erc20 = await ERC20Factory.deploy(ethers.utils.parseEther('20000000', 'wei'));
|
||||||
|
await erc20.deployed();
|
||||||
|
|
||||||
|
// Check initial balance
|
||||||
|
expect(await erc20.balanceOf(owner.address)).to.equal(ethers.utils.parseEther('20000000', 'wei'));
|
||||||
|
|
||||||
|
const P2PIX = await ethers.getContractFactory("P2PIX");
|
||||||
|
p2pix = await P2PIX.deploy(2, [owner.address, wallet2.address]);
|
||||||
|
await p2pix.deployed();
|
||||||
|
|
||||||
|
// Verify values at deployment
|
||||||
|
expect(await p2pix.validBacenSigners(owner.address)).to.equal(true);
|
||||||
|
expect(await p2pix.validBacenSigners(wallet2.address)).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should allow create a deposit", async function () {
|
||||||
|
|
||||||
|
let transaction = await erc20.approve(p2pix.address,ethers.utils.parseEther('1000'));
|
||||||
|
await expect(transaction).to.emit(erc20, 'Approval').withArgs(
|
||||||
|
owner.address,
|
||||||
|
p2pix.address,
|
||||||
|
ethers.utils.parseEther('1000')
|
||||||
|
)
|
||||||
|
|
||||||
|
transaction = await p2pix.deposit(
|
||||||
|
erc20.address,
|
||||||
|
ethers.utils.parseEther('1000'),
|
||||||
|
ethers.utils.parseEther('0.99'),
|
||||||
|
'SELLER PIX KEY'
|
||||||
|
);
|
||||||
|
depositID = ethers.utils.solidityKeccak256(['string', 'uint256'], ['SELLER PIX KEY', ethers.utils.parseEther('1000')])
|
||||||
|
await expect(transaction).to.emit(p2pix, 'DepositAdded').withArgs(
|
||||||
|
owner.address,
|
||||||
|
depositID,
|
||||||
|
erc20.address,
|
||||||
|
ethers.utils.parseEther('0.99'),
|
||||||
|
ethers.utils.parseEther('1000')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Should allow create a new lock", async function () {
|
||||||
|
transaction = await p2pix.connect(wallet3).lock(
|
||||||
|
depositID,
|
||||||
|
wallet3.address,
|
||||||
|
ethers.constants.AddressZero,
|
||||||
|
'0',
|
||||||
|
ethers.utils.parseEther('100'),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
const lockID = ethers.utils.solidityKeccak256(['bytes32', 'uint256', 'address'], [
|
||||||
|
depositID,
|
||||||
|
ethers.utils.parseEther('100'),
|
||||||
|
wallet3.address
|
||||||
|
])
|
||||||
|
await expect(transaction).to.emit(p2pix, 'LockAdded').withArgs(
|
||||||
|
wallet3.address,
|
||||||
|
lockID,
|
||||||
|
depositID,
|
||||||
|
ethers.utils.parseEther('100')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user