Преглед изворни кода

add token migration contract

Change-Id: I2bc3fb4d99f5a08452bc2defd3597ec7ad300523
valentin пре 4 година
родитељ
комит
ffcdc3f3f2
2 измењених фајлова са 155 додато и 0 уклоњено
  1. 68 0
      ethereum/contracts/bridge/utils/Migrator.sol
  2. 87 0
      ethereum/test/tokenmigrator.js

+ 68 - 0
ethereum/contracts/bridge/utils/Migrator.sol

@@ -0,0 +1,68 @@
+// contracts/Messages.sol
+// SPDX-License-Identifier: Apache 2
+
+pragma solidity ^0.8.0;
+pragma experimental ABIEncoderV2;
+
+import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+
+contract Migrator is ERC20 {
+    IERC20 public fromAsset;
+    IERC20 public toAsset;
+    uint public fromDecimals;
+    uint public toDecimals;
+
+    constructor (
+        address _fromAsset,
+        address _toAsset
+    )
+    // LP shares track the underlying toToken amount
+    ERC20("Token Migration Pool", "Migrator-LP") {
+        fromAsset = IERC20(_fromAsset);
+        toAsset = IERC20(_toAsset);
+        fromDecimals = ERC20(_fromAsset).decimals();
+        toDecimals = ERC20(_toAsset).decimals();
+    }
+
+    // _amount denominated in toAsset
+    function add(uint _amount) external {
+        // deposit toAsset
+        SafeERC20.safeTransferFrom(toAsset, msg.sender, address(this), _amount);
+        // mint LP shares
+        _mint(msg.sender, _amount);
+    }
+
+    // _amount denominated in LP shares
+    function remove(uint _amount) external {
+        // burn LP shares
+        _burn(msg.sender, _amount);
+        // send out toAsset
+        SafeERC20.safeTransfer(toAsset, msg.sender, _amount);
+    }
+
+    // _amount denominated in LP shares
+    function claim(uint _amount) external {
+        // burn LP shares
+        _burn(msg.sender, _amount);
+        // send out fromAsset
+        SafeERC20.safeTransfer(fromAsset, msg.sender, adjustDecimals(toDecimals, fromDecimals, _amount));
+    }
+
+    // _amount denominated in fromToken
+    function migrate(uint _amount) external {
+        // deposit fromAsset
+        SafeERC20.safeTransferFrom(fromAsset, msg.sender, address(this), _amount);
+        // send out toAsset
+        SafeERC20.safeTransfer(toAsset, msg.sender, adjustDecimals(fromDecimals, toDecimals, _amount));
+    }
+
+    function adjustDecimals(uint _fromDecimals, uint _toDecimals, uint _amount) internal pure returns (uint) {
+        if (_fromDecimals > _toDecimals){
+            _amount /= 10 ** (_fromDecimals - _toDecimals);
+        } else if (_fromDecimals < _toDecimals) {
+            _amount *= 10 ** (_toDecimals - _fromDecimals);
+        }
+        return _amount;
+    }
+}

+ 87 - 0
ethereum/test/tokenmigrator.js

@@ -0,0 +1,87 @@
+const jsonfile = require('jsonfile');
+const BigNumber = require('bignumber.js');
+
+const Migrator = artifacts.require("Migrator");
+const TokenImplementation = artifacts.require("TokenImplementation");
+
+contract("Migrator", function (accounts) {
+    var migrator,
+        fromToken,
+        toToken,
+        fromDecimals = 8,
+        toDecimals = 18;
+
+    it("should deploy with the correct values", async function () {
+        fromToken = await TokenImplementation.new();
+        await fromToken.initialize(
+            "TestFrom",
+            "FROM",
+            fromDecimals,
+            0,
+            accounts[0],
+            0,
+            "0x00"
+        )
+        toToken = await TokenImplementation.new();
+        await toToken.initialize(
+            "TestTo",
+            "TO",
+            toDecimals,
+            0,
+            accounts[0],
+            0,
+            "0x00"
+        )
+
+        migrator = await Migrator.new(
+            fromToken.address,
+            toToken.address,
+        );
+
+        assert.equal(await migrator.fromAsset(), fromToken.address)
+        assert.equal(await migrator.toAsset(), toToken.address)
+        assert.equal((await migrator.fromDecimals()).toNumber(), fromDecimals)
+        assert.equal((await migrator.toDecimals()).toNumber(), toDecimals)
+    })
+
+    it("should give out LP tokens 1:1 for a toToken deposit", async function () {
+        await toToken.mint(accounts[0], "1000000000000000000")
+        await toToken.approve(migrator.address, "1000000000000000000")
+        await migrator.add("1000000000000000000")
+
+
+        assert.equal((await toToken.balanceOf(migrator.address)).toString(), "1000000000000000000")
+        assert.equal((await migrator.balanceOf(accounts[0])).toString(), "1000000000000000000")
+    })
+
+    it("should refund toToken for LP tokens", async function () {
+        await migrator.remove("500000000000000000")
+
+        assert.equal((await toToken.balanceOf(migrator.address)).toString(), "500000000000000000")
+        assert.equal((await toToken.balanceOf(accounts[0])).toString(), "500000000000000000")
+        assert.equal((await migrator.balanceOf(accounts[0])).toString(), "500000000000000000")
+    })
+
+    it("should redeem fromToken to toToken adjusting for decimals", async function () {
+        await fromToken.mint(accounts[1], "50000000")
+        await fromToken.approve(migrator.address, "50000000", {
+            from : accounts[1]
+        })
+        await migrator.migrate("50000000", {
+            from : accounts[1]
+        })
+
+        assert.equal((await toToken.balanceOf(accounts[1])).toString(), "500000000000000000")
+        assert.equal((await fromToken.balanceOf(accounts[1])).toString(), "0")
+        assert.equal((await fromToken.balanceOf(migrator.address)).toString(), "50000000")
+        assert.equal((await toToken.balanceOf(migrator.address)).toString(), "0")
+    })
+
+    it("fromToken should be claimable for LP tokens, adjusting for decimals", async function () {
+        await migrator.claim("500000000000000000")
+
+        assert.equal((await fromToken.balanceOf(migrator.address)).toString(), "0")
+        assert.equal((await fromToken.balanceOf(accounts[0])).toString(), "50000000")
+        assert.equal((await migrator.balanceOf(accounts[0])).toString(), "0")
+    })
+})