Developers Forum for XinFin XDC Network

Discussion on: [Feedback] The Pitfalls of Developing on XDC Network: A Critical Assessment

Collapse
annondev profile image
AnnonDEV Author • Edited on

Lets start with this, deploy this on mainnet withour using ANKR RPC. (one RPC in whole blockchain works with this):

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

/// @title Migration contract
/// @author FreezyEx (github.com/FreezyEx)
/// @notice A contract to migrate from old to new token version

abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender);
}

function _msgData() internal view virtual returns (bytes memory) {
    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    return msg.data;
}
Enter fullscreen mode Exit fullscreen mode

}

interface IERC20 {
function decimals() external view returns (uint256);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}

/// github.com/OpenZeppelin/openzeppel...
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;

uint256 private _status;

constructor() {
    _status = _NOT_ENTERED;
}

modifier nonReentrant() {
    require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
    _status = _ENTERED;
    _;
    _status = _NOT_ENTERED;
}
Enter fullscreen mode Exit fullscreen mode

}

contract Ownable is Context {
address private _owner;
address private _previousOwner;

event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

constructor () {
    address msgSender = _msgSender();
    _owner = msgSender;
    emit OwnershipTransferred(address(0), msgSender);
}

function owner() public view returns (address) {
    return _owner;
}

modifier onlyOwner() {
    require(_owner == _msgSender(), "Ownable: caller is not the owner");
    _;
}

function renounceOwnership() public virtual onlyOwner {
    emit OwnershipTransferred(_owner, address(0));
    _owner = address(0);
}

function transferOwnership(address newOwner) public virtual onlyOwner {
    require(newOwner != address(0), "Ownable: new owner is the zero address");
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
}
Enter fullscreen mode Exit fullscreen mode

}

contract Migrate is ReentrancyGuard, Context, Ownable{

// we want to track who has already migrated to V2
mapping(address => bool) private claimed;
address public immutable deadWallet = 0x000000000000000000000000000000000000dEaD;

IERC20 public tokenV1; //address of the old version
IERC20 public tokenV2; //address of the new version
uint256 public rate; // 1 token V1 ---> 1 * rate token V2

bool public migrationStarted;

/// @notice Emits event every time someone migrates
event MigrateToV2(address addr, uint256 amount);

/// @param tokenAddressV1 The address of old version
/// @param tokenAddressV2 The address of new version
/// @param _rate The rate between old and new version
constructor(IERC20 tokenAddressV1, IERC20 tokenAddressV2, uint256 _rate) {
    tokenV2 = tokenAddressV2;
    tokenV1 = tokenAddressV1;
    rate = _rate;
}

/// @notice Enables the migration
function startMigration() external onlyOwner{
    require(migrationStarted == false, "Migration is already enabled");
    migrationStarted = true;
}

/// @notice Disable the migration
function stopMigration() external onlyOwner{
    require(migrationStarted == true, "Migration is already disabled");
    migrationStarted = false;
}

/// @notice Updates "tokenV1", "tokenV2" and the "rate"
/// @param tokenV1addr The address of old version
/// @param tokenV2addr The address of new version
/// @param _rate The rate between old and new version
function setTokenV1andV2(IERC20 tokenV1addr, IERC20 tokenV2addr, uint256 _rate) external onlyOwner{
    tokenV1 = tokenV1addr;
    tokenV2 = tokenV2addr;
    rate = _rate;
}

/// @notice Withdraws remaining tokens
function withdrawTokens(uint256 amount) external onlyOwner{
    require(migrationStarted == false, "Impossible to withdraw tokens if migration still enabled");
    tokenV2.transfer(msg.sender, amount * 10**(tokenV2.decimals()));
}

/// @param v1amount The amount of tokens to migrate
/// @notice Migrates from old version to new one
///   User must call "approve" function on tokenV1 contract
///   passing this contract address as "sender".
///   Old tokens will be sent to burn
function migrateToV2(uint256 v1amount) public nonReentrant(){
    require(migrationStarted == true, 'Migration not started yet');
    uint256 amount = v1amount * 10 ** tokenV1.decimals();
    uint256 userV1Balance = tokenV1.balanceOf(msg.sender);
    require(userV1Balance >= amount, 'You must hold V1 tokens to migrate');
    uint256 amtToMigrate = v1amount * rate * 10 ** tokenV2.decimals();
    require(tokenV2.balanceOf(address(this)) >= amtToMigrate, 'No enough V2 liquidity');
    tokenV1.transferFrom(msg.sender, deadWallet, amount);
    tokenV2.transfer(msg.sender, amtToMigrate);
    emit MigrateToV2(msg.sender, amtToMigrate);
}
Enter fullscreen mode Exit fullscreen mode

}

Collapse
ruslan_wing profile image
ruslan wing

Here is the list of the Public RPC on XDC Network you need to select the RPC according to your smart contract if you are using Hardhat, metamask, Truffle, Ethereum remix or any other tool which require 0x prefix address output then you need to use ERPC and if you want 0x prefix address output you can use any public RPC

All the RPC are available on XDC Network according to the Developer requirement. User just need to select the correct RPC

Link to the detail guide xdc.dev/ruslan_wing/exploring-xdc-...