Skip to content

Commit

Permalink
Add mint dmc logic to contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
weiqiushi committed Jan 4, 2024
1 parent 01072a1 commit cbd283b
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 20 deletions.
32 changes: 29 additions & 3 deletions contracts/dmc.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,35 @@
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract DMCToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Datamall Chain Token", "DMC") {
_mint(msg.sender, initialSupply);
contract DMCToken is ERC20, Ownable {
uint256 maxSupply;
mapping (address => bool) allow_minter;

modifier onlyMinter() {
require(allow_minter[msg.sender], "mint not allowed");
_;
}

constructor(uint256 _maxSupply) ERC20("Datamall Chain Token", "DMC") Ownable(msg.sender) {
maxSupply = _maxSupply;
}

function enableMinter(address[] calldata addresses) public onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
allow_minter[addresses[i]] = true;
}
}

function disableMinter(address[] calldata addresses) public onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
allow_minter[addresses[i]] = false;
}
}

function mint(address to, uint256 amount) public onlyMinter {
require(totalSupply() + amount <= maxSupply, "max supply exceeded");
_mint(to, amount);
}
}
44 changes: 44 additions & 0 deletions contracts/exchange.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,41 @@ pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

import "./dmc.sol";
import "./gwt.sol";

contract Exchange is Initializable, UUPSUpgradeable, OwnableUpgradeable {
DMCToken dmcToken;
GWTToken gwtToken;
bytes32 luckyMintRoot;
//mapping (address => bool) allow_dmcMint;
mapping (bytes32 => bool) luckyHashUsed;
mapping (address => uint256) mintAfter;

uint mintAfterTime;
/*
modifier onlyMinter() {
require(allow_dmcMint[msg.sender], "mint not allowed");
_;
}
function enableDMCMint(address[] calldata addresses) public onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
allow_dmcMint[addresses[i]] = true;
}
}
function disableDMCMint(address[] calldata addresses) public onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
allow_dmcMint[addresses[i]] = false;
}
}
*/
function initialize(address _dmcToken, address _gwtToken) public initializer {
__ExchangeUpgradable_init(_dmcToken, _gwtToken);
mintAfterTime = 1 days;
}

function __ExchangeUpgradable_init(address _dmcToken, address _gwtToken) internal onlyInitializing {
Expand All @@ -27,6 +52,12 @@ contract Exchange is Initializable, UUPSUpgradeable, OwnableUpgradeable {

}



function setLuckyMintRoot(bytes32 _luckyMintRoot) public onlyOwner {
luckyMintRoot = _luckyMintRoot;
}

function gwtRate() public pure returns(uint256) {
// 1 : 210
return 210;
Expand All @@ -43,4 +74,17 @@ contract Exchange is Initializable, UUPSUpgradeable, OwnableUpgradeable {
gwtToken.burnFrom(msg.sender, amount);
dmcToken.transfer(msg.sender, dmcAmount);
}

function mintDMC(bytes32 luckyHash, bytes32[] calldata luckyPath) public /*onlyMinter*/ {
require(mintAfter[msg.sender] < block.timestamp, "mint too often");
if (luckyHash != bytes32(0) && MerkleProof.verify(luckyPath, luckyMintRoot, luckyHash)) {
require(!luckyHashUsed[luckyHash], "lucky hash used");
dmcToken.mint(msg.sender, 2100 * 10 ** dmcToken.decimals());
luckyHashUsed[luckyHash] = true;
} else {
dmcToken.mint(msg.sender, 210 * 10 ** dmcToken.decimals());
}

mintAfter[msg.sender] = block.timestamp + mintAfterTime;
}
}
20 changes: 19 additions & 1 deletion scripts/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ethers, network, upgrades } from "hardhat";
import * as fs from "node:fs";
import { Exchange } from "../typechain-types";
import { Exchange, PublicDataStorage } from "../typechain-types";

async function main() {
const dmcContract = await (await ethers.deployContract("DMCToken", [ethers.parseEther("100000000")])).waitForDeployment();
Expand Down Expand Up @@ -36,6 +36,24 @@ async function main() {

await(await gwtContract.enableTransfer([publicDataStorageAddress])).wait();

let config = await publicDataStorage.sysConfig();
let setConfig: PublicDataStorage.SysConfigStruct = {
minDepositRatio: config.minDepositRatio,
minPublicDataStorageWeeks: config.minPublicDataStorageWeeks,
minLockWeeks: config.minLockWeeks,
blocksPerCycle: config.blocksPerCycle,
topRewards: config.topRewards,
lockAfterShow: config.lockAfterShow,
showTimeout: config.showTimeout,
maxNonceBlockDistance: config.maxNonceBlockDistance,
minRankingScore: config.minRankingScore,
minDataSize: config.minDataSize
};
setConfig.showTimeout = 720n;
setConfig.lockAfterShow = 720n;
setConfig.minRankingScore = 1n;
await (await publicDataStorage.setSysConfig(setConfig)).wait();

if (network.name !== "hardhat") {
fs.writeFileSync(`${network.name}-deployed.json`, JSON.stringify({
DMCToken: dmcAddress,
Expand Down
14 changes: 12 additions & 2 deletions test/test_exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe("Exchange", function () {
before(async () => {
signers = await ethers.getSigners()

dmc = await (await ethers.deployContract("DMCToken", [ethers.parseEther("10000000")])).waitForDeployment()
dmc = await (await ethers.deployContract("DMCToken", [ethers.parseEther("1000000000")])).waitForDeployment()
gwt = await (await ethers.deployContract("GWTToken")).waitForDeployment()
exchange = await (await upgrades.deployProxy(await ethers.getContractFactory("Exchange"),
[await dmc.getAddress(), await gwt.getAddress()],
Expand All @@ -23,10 +23,20 @@ describe("Exchange", function () {
})).waitForDeployment() as unknown as Exchange;

await (await gwt.enableMinter([await exchange.getAddress()])).wait();
await (await dmc.enableMinter([await exchange.getAddress()])).wait();

await (await dmc.transfer(signers[1].address, ethers.parseEther("1000"))).wait()
// await (await dmc.transfer(signers[1].address, ethers.parseEther("1000"))).wait()
})

it("mint dmc", async () => {
await expect(exchange.connect(signers[0]).mintDMC(ethers.ZeroHash, []))
.emit(dmc, "Transfer").withArgs(ethers.ZeroAddress, signers[0].address, ethers.parseEther("210"));

// 为了测试,将signers[0]直接加入dmc的minter,并给signers[1] mint 1000 dmc
await (await dmc.enableMinter([signers[0].address])).wait();
await (await dmc.connect(signers[0]).mint(signers[1].address, ethers.parseEther("1000"))).wait()
});

it("exchange dmc to gwt", async () => {
expect(await dmc.balanceOf(signers[1].address)).to.equal(ethers.parseEther("1000"))
let exchangeAddr = await exchange.getAddress();
Expand Down
36 changes: 22 additions & 14 deletions test/test_public_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ describe("PublicDataStorage", function () {
minDataSize: config.minDataSize
};
setConfig.showTimeout = 720n;
setConfig.lockAfterShow = 720n;
setConfig.minRankingScore = 1n;
await (await contract.setSysConfig(setConfig)).wait();

Expand Down Expand Up @@ -232,12 +233,12 @@ describe("PublicDataStorage", function () {
.emit(contract, "SupplierBalanceChanged").withArgs(signers[3].address, ethers.parseEther("10000"), 0);
});

async function showData(signer: HardhatEthersSigner): Promise<[Promise<ContractTransactionResponse>, number]> {
async function showData(signer: HardhatEthersSigner, showType: number): Promise<[Promise<ContractTransactionResponse>, number]> {
let nonce_block = await ethers.provider.getBlockNumber();
await mine();

let [min_index, path, leaf, proof] = await generateProof(TestDatas[0].data_file_path, nonce_block, TestDatas[0].merkle_file_path);
let tx = contract.connect(signer).showData(TestDatas[0].hash, nonce_block, min_index, path, leaf, 0);
let tx = contract.connect(signer).showData(TestDatas[0].hash, nonce_block, min_index, path, leaf, showType);
await expect(tx).emit(contract, "ShowDataProof").withArgs(signer.address, TestDatas[0].hash, nonce_block);

let proofInfo = await contract.getDataProof(TestDatas[0].hash, nonce_block);
Expand All @@ -246,44 +247,51 @@ describe("PublicDataStorage", function () {
return [tx, nonce_block];
}

it("show data immediately", async () => {
// Normal情况下,会锁定192 GWT,当balance / 10 * 2 > 192,即balance > 960时,才会有immediately show
let [tx, nonce_block] = await showData(signers[2], 1);
await expect(tx)
.emit(contract, "SupplierBalanceChanged").withArgs(signers[2].address, ethers.parseEther("9701.12"), ethers.parseEther("298.88"))
.emit(contract, "SupplierReward").withArgs(signers[2].address, TestDatas[0].hash, ethers.parseEther("149.44"));
await expect(tx).changeTokenBalance(gwtToken, signers[2].address, ethers.parseEther("149.44"));
});

it("show data and withdraw", async () => {
// 这个操作会锁定signers[2]的余额 1/8 GB * 24(周) * 64(倍) = 192 GWT
let [tx, nonce_block] = await showData(signers[2]);
await expect(tx).emit(contract, "SupplierBalanceChanged").withArgs(signers[2].address, ethers.parseEther("9808"), ethers.parseEther("192"));
let [tx, nonce_block] = await showData(signers[2], 0);
await expect(tx).emit(contract, "SupplierBalanceChanged").withArgs(signers[2].address, ethers.parseEther("9509.12"), ethers.parseEther("490.88"));

await mine((await contract.sysConfig()).showTimeout);


// signers[2]得到奖励, 奖励从data[0]的余额里扣除
// 得到的奖励:1494.4 * 0.1 = 149.44
// 余额扣除:1494.4 * 0.1 = 149.44
// 得到的奖励:1494.4 * 0.9 * 0.1 = 134.496
let tx2 = contract.connect(signers[2]).withdrawShow(TestDatas[0].hash, nonce_block);
await expect(tx2).emit(contract, "SupplierReward").withArgs(signers[2].address, TestDatas[0].hash, ethers.parseEther("149.44"))
await expect(tx2).changeTokenBalance(gwtToken, signers[2].address, ethers.parseEther("149.44"))
expect(await contract.dataBalance(TestDatas[0].hash)).to.equal(ethers.parseEther("1344.96"));
await expect(tx2).emit(contract, "SupplierReward").withArgs(signers[2].address, TestDatas[0].hash, ethers.parseEther("134.496"))
await expect(tx2).changeTokenBalance(gwtToken, signers[2].address, ethers.parseEther("134.496"))
expect(await contract.dataBalance(TestDatas[0].hash)).to.equal(ethers.parseEther("1210.464"));
});

it("show data again", async() => {
let [tx, nonce] = await showData(signers[3]);
let [tx, nonce] = await showData(signers[3], 0);
await expect(tx).emit(contract, "SupplierBalanceChanged").withArgs(signers[3].address, ethers.parseEther("9808"), ethers.parseEther("192"));

// 要提现后,cycle数据才更新
await mine((await contract.sysConfig()).showTimeout);
await contract.connect(signers[3]).withdrawShow(TestDatas[0].hash, nonce);
expect(await contract.getCurrectLastShowed(TestDatas[0].hash)).have.ordered.members([signers[2].address, signers[3].address]);
expect(await contract.getCurrectLastShowed(TestDatas[0].hash)).have.ordered.members([signers[2].address, signers[2].address, signers[3].address]);
});

it("several suppliers show data", async () => {
// 4, 5, 6, 7分别show这个数据
for (let i = 4; i < 8; i++){
await (expect(contract.connect(signers[i]).pledgeGwt(ethers.parseEther("10000"))))
.emit(contract, "SupplierBalanceChanged").withArgs(signers[i].address, ethers.parseEther("10000"), 0);
let [tx, nonce] = await showData(signers[i]);
let [tx, nonce] = await showData(signers[i], 0);
await mine((await contract.sysConfig()).showTimeout);
await (await contract.connect(signers[i]).withdrawShow(TestDatas[0].hash, nonce));
}

expect(await contract.getCurrectLastShowed(TestDatas[0].hash)).have.ordered.members([signers[7].address, signers[3].address, signers[4].address, signers[5].address, signers[6].address]);
expect(await contract.getCurrectLastShowed(TestDatas[0].hash)).have.ordered.members([signers[6].address, signers[7].address, signers[3].address, signers[4].address, signers[5].address]);
});

it("suppliers withdraw cycle reward", async () => {
Expand Down

0 comments on commit cbd283b

Please sign in to comment.