Skip to content

Commit

Permalink
Change exchange contract to UUPS upgradeable
Browse files Browse the repository at this point in the history
  • Loading branch information
weiqiushi committed Apr 29, 2024
1 parent 0bcfd4e commit 50abb82
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 36 deletions.
119 changes: 90 additions & 29 deletions contracts/exchange2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,70 @@ import "./dmc2.sol";
import "./gwt2.sol";
import "./dividend.sol";

contract Exchange2 {
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract Exchange2 is Initializable, UUPSUpgradeable, OwnableUpgradeable {
address dmcToken;
address gwtToken;
address fundationIncome;

// 当前周期,也可以看做周期总数
uint256 current_circle = 0;
uint256 current_circle;
uint256 current_mine_circle_start;

// 这个周期内还能mint多少DMC
uint256 remain_dmc_balance = 0;
uint256 remain_dmc_balance;

// 这个周期的能mint的DMC总量
uint256 current_circle_dmc_balance = 0;
uint256 current_finish_time = 0;
uint256 public dmc2gwt_rate = 210;
uint256 current_circle_dmc_balance;
uint256 current_finish_time;
uint256 public dmc2gwt_rate;

// 总共未mint的DMC总量,这个值会慢慢释放掉
uint256 total_addtion_dmc_balance = 0;
uint256 total_addtion_dmc_balance;

// 没有挖完的周期总数
uint256 addtion_circle_count = 0;
uint256 addtion_circle_count;

// 周期的最小时长
uint256 min_circle_time = 100;
uint256 min_circle_time;

//uint256 total_mine_period = 420;
uint256 adjust_period = 21;
uint256 initial_dmc_balance=768242.27 ether;
uint256 adjust_period;
uint256 initial_dmc_balance;

// DMC1到2的兑换
mapping(bytes32 => uint256) public dmc1_to_dmc2;

event newCycle(uint256 cycle_number, uint256 dmc_balance, uint256 start_time);
event gwtRateChanged(uint256 new_rate, uint256 old_rate);
event DMCMinted(uint256 amount, uint256 remain);

function initialize(address _dmcToken, address _gwtToken, address _fundationIncome, uint256 _min_circle_time) public initializer {
__UUPSUpgradeable_init();
__Ownable_init(msg.sender);
__Exchange2Upgradable_init(_dmcToken, _gwtToken, _fundationIncome, _min_circle_time);
}

constructor(address _dmcToken, address _gwtToken, address _fundationIncome, uint256 _min_circle_time) {
function __Exchange2Upgradable_init(address _dmcToken, address _gwtToken, address _fundationIncome, uint256 _min_circle_time) public onlyInitializing {
require(_min_circle_time > 0);
dmcToken = _dmcToken;
gwtToken = _gwtToken;
fundationIncome = _fundationIncome;
min_circle_time = _min_circle_time;

dmc2gwt_rate = 210;
adjust_period = 21;
initial_dmc_balance = 768242.27 ether;

_newCycle();
}

function getCircleBalance(uint256 circle) public view returns (uint256) {

uint256 adjust_times = (circle-1) / adjust_period;
uint256 balance = initial_dmc_balance;
for (uint i = 0; i < adjust_times; i++) {
Expand All @@ -70,26 +93,27 @@ contract Exchange2 {
}

current_circle_dmc_balance = remain_dmc_balance;
console.log("new cycle %d start at %d, dmc balance %d", current_circle, current_mine_circle_start, current_circle_dmc_balance);
emit newCycle(current_circle, current_circle_dmc_balance, current_mine_circle_start);
//console.log("new cycle %d start at %d, dmc balance %d", current_circle, current_mine_circle_start, current_circle_dmc_balance);
}

function adjustExchangeRate() internal {
if(block.timestamp >= current_mine_circle_start + min_circle_time) {
//结束当前挖矿周期

uint256 old_rate = dmc2gwt_rate;
if(remain_dmc_balance > 0) {
total_addtion_dmc_balance += remain_dmc_balance;
addtion_circle_count += 1;

console.log("prev cycle dmc balance left %d, total left %d, total left cycle %d", remain_dmc_balance, total_addtion_dmc_balance, addtion_circle_count);

//本周期未挖完,降低dmc2gwt_rate
uint256 old_rate = dmc2gwt_rate;
dmc2gwt_rate = dmc2gwt_rate * (1-remain_dmc_balance/current_circle_dmc_balance);
if(dmc2gwt_rate < 210) {
// 最低值为210
dmc2gwt_rate = 210;
}

console.log("decrease dmc2gwt_rate to %d", dmc2gwt_rate);
} else {
if (addtion_circle_count > 0) {
Expand All @@ -104,37 +128,72 @@ contract Exchange2 {
console.log("increase dmc2gwt_rate to %d", dmc2gwt_rate);
}

emit gwtRateChanged(dmc2gwt_rate, old_rate);

_newCycle();
} else {
console.log("keep cycle.");
require(remain_dmc_balance > 0, "no dmc balance in current circle");
}
}

function _decreaseDMCBalance(uint256 amount) internal returns (uint256, bool) {
bool is_empty = false;
uint256 real_amount = amount;
if(remain_dmc_balance > amount) {
remain_dmc_balance -= amount;
} else {
// 待确认:我将current_finish_time看作是一轮DMC释放完毕的时间,但这会导致gwt的汇率计算可能与GWT的实际兑换情况无关
current_finish_time = block.timestamp;

real_amount = remain_dmc_balance;
remain_dmc_balance = 0;
is_empty = true;
}

emit DMCMinted(real_amount, remain_dmc_balance);

return (real_amount, is_empty);
}

function registerDMC1(address recvAddress, string calldata cookie, uint256 dmc1Amount) onlyOwner public {
dmc1_to_dmc2[keccak256(abi.encodePacked(recvAddress, cookie))] = dmc1Amount;
}

function claimDMC2(string calldata cookie) public {
bytes32 key = keccak256(abi.encodePacked(msg.sender, cookie));
require(dmc1_to_dmc2[key] > 0, "no dmc1 amount");
uint256 dmc2Amount = dmc1_to_dmc2[key] * 4 / 5;
(uint256 claimAmount, bool is_empty) = _decreaseDMCBalance(dmc2Amount);
if (is_empty) {
dmc1_to_dmc2[key] -= claimAmount * 5 / 4;
} else {
dmc1_to_dmc2[key] = 0;
}

DMC2(dmcToken).mint(msg.sender, claimAmount);
}

function DMCtoGWT(uint256 amount) public {
DMC2(dmcToken).burnFrom(msg.sender, amount);
GWTToken2(gwtToken).mint(msg.sender, amount * dmc2gwt_rate * 6 / 5);
}

function GWTtoDMC(uint256 amount) public {
adjustExchangeRate();
uint256 real_dmc_count = 0;
uint256 dmc_count = amount / dmc2gwt_rate;
console.log("exchange dmc %d from amount %d, rate %d", dmc_count, amount, dmc2gwt_rate);
if(dmc_count >= remain_dmc_balance) {
current_finish_time = block.timestamp;

real_dmc_count = remain_dmc_balance;
remain_dmc_balance = 0;
//不用立刻转给分红合约,而是等积累一下
GWTToken2(gwtToken).transferFrom(msg.sender, address(this), real_dmc_count * dmc2gwt_rate);
DMC2(dmcToken).mint(msg.sender, real_dmc_count);
} else {
remain_dmc_balance -= dmc_count;
//不用立刻转给分红合约,而是等积累一下
GWTToken2(gwtToken).transferFrom(msg.sender, address(this), amount);
DMC2(dmcToken).mint(msg.sender, dmc_count);

(uint256 real_dmc_amount, bool is_empty) = _decreaseDMCBalance(dmc_count);
uint256 real_gwt_amount = amount;
if (is_empty) {
//current_finish_time = block.timestamp;
real_gwt_amount = real_dmc_amount * dmc2gwt_rate;
}

//不用立刻转给分红合约,而是等积累一下
GWTToken2(gwtToken).transferFrom(msg.sender, address(this), real_gwt_amount);
DMC2(dmcToken).mint(msg.sender, real_dmc_amount);
}

// 手工将累积的收入打给分红合约
Expand All @@ -146,4 +205,6 @@ contract Exchange2 {
function getCycleInfo() public view returns (uint256, uint256, uint256) {
return (current_circle, remain_dmc_balance, current_circle_dmc_balance);
}

function _authorizeUpgrade(address) internal override onlyOwner {}
}
15 changes: 8 additions & 7 deletions test/test_exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/signers';
import { expect } from "chai";
import { mine } from "@nomicfoundation/hardhat-network-helpers";

// 此测试运行的前提:每轮的释放DMC固定为210,汇率固定为210

describe("Exchange", function () {
let dmc: DMC2
let gwt: GWTToken2
Expand All @@ -17,17 +19,16 @@ describe("Exchange", function () {

dmc = await (await ethers.deployContract("DMC2", [ethers.parseEther("1000000000"), [signers[0].address], [ethers.parseEther("1000")]])).waitForDeployment()
gwt = await (await ethers.deployContract("GWTToken2")).waitForDeployment()
exchange = await(await ethers.deployContract("Exchange2", [await dmc.getAddress(), await gwt.getAddress(), ethers.ZeroAddress, 1000])).waitForDeployment()
console.log("exchange:", await exchange.getAddress())
/*
exchange = await (await upgrades.deployProxy(await ethers.getContractFactory("Exchange"),
[await dmc.getAddress(), await gwt.getAddress()],
//exchange = await(await ethers.deployContract("Exchange2", [await dmc.getAddress(), await gwt.getAddress(), ethers.ZeroAddress, 1000])).waitForDeployment();
exchange = await (await upgrades.deployProxy(await ethers.getContractFactory("Exchange2"),
[await dmc.getAddress(), await gwt.getAddress(), ethers.ZeroAddress, 1000],
{
initializer: "initialize",
kind: "uups",
timeout: 0
})).waitForDeployment() as unknown as Exchange;
*/
})).waitForDeployment() as unknown as Exchange2;
console.log("exchange:", await exchange.getAddress());

await (await gwt.enableMinter([await exchange.getAddress(), signers[0].address])).wait();
await (await dmc.enableMinter([await exchange.getAddress()])).wait();

Expand Down

0 comments on commit 50abb82

Please sign in to comment.