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;
}
}
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);
}
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
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);
}
}
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;
}
contract Ownable is Context {
address private _owner;
address private _previousOwner;
}
contract Migrate is ReentrancyGuard, Context, Ownable{
}
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-...