* Add IntelliJ IDE config to .gitignore * Fix variable name in ERC20 function comments * Fix typos in Arrays function comment * Fix typos in ownership test names * Fix typo in Pausable test name * Fix grammar in Ownable function comment * Fix grammar in Crowdsale contract comment * Fix typo in Counters contract comment * Fix typo in ERC721Enumerable comment * Fix typo in ERC721PausedToken test name * Fix typo in Crowdsale function comment * Fix typo in IncreasingPriceCrowdsale function comment * Fix grammar in IncreasingPriceCrowdsale test name * Fix typo in AllowanceCrowdsale test name * Fix typo in RefundEscrow function comment * Fix typo in ERC20Migrator contract comment * Fix typos in SignatureBouncer comments * Fix typo in SignedSafeMath test name * Fix typo in TokenVesting contract comment * Move Ownable comment from @notice section to @dev The Ownable contract has a comment explaining that renouncing ownership will prevent execution of functions with the onlyOwner modifier. This commit moves that comment to the @dev section and replaces it with a description suitable for a generic user. * Clarify purpose of ERC20 transfer function * Clarify registration of ERC721Enumerable interface * Clarify purpose of AllowanceCrowdsale test * Increase specificity of inheritance comments FinalizableCrowdsale and RefundableCrowsale both have comments indicating that they are extensions of the Crowdsale contract. This commit refines those comments to the most immediate ancestor ( TimedCrowdsale and RefundableCrowdsale respectively ) * Remove unused parameter in PaymentSplitter test * Rename parameter in SignatureBouncer functions The SignatureBouncer contract has modifiers to validate the message sender is authorised to perform an action. They pass msg.sender to internal functions as the variable `account`, but the function comments refer to the variable as `sender` This commit changes the variable name to `sender` * Clarify comments in SignatureBouncer functions The SignatureBouncer has comments that use the description `sender` to refer to the variable `account`. This commit updates the comments for consistency. Maintainer Note: this reverts changes in the previous commit, which renamed the variable `account` instead.
101 lines
3.7 KiB
Solidity
101 lines
3.7 KiB
Solidity
pragma solidity ^0.5.2;
|
|
|
|
import "../token/ERC20/IERC20.sol";
|
|
import "../token/ERC20/ERC20Mintable.sol";
|
|
import "../token/ERC20/SafeERC20.sol";
|
|
import "../math/Math.sol";
|
|
|
|
/**
|
|
* @title ERC20Migrator
|
|
* @dev This contract can be used to migrate an ERC20 token from one
|
|
* contract to another, where each token holder has to opt-in to the migration.
|
|
* To opt-in, users must approve for this contract the number of tokens they
|
|
* want to migrate. Once the allowance is set up, anyone can trigger the
|
|
* migration to the new token contract. In this way, token holders "turn in"
|
|
* their old balance and will be minted an equal amount in the new token.
|
|
* The new token contract must be mintable. For the precise interface refer to
|
|
* OpenZeppelin's ERC20Mintable, but the only functions that are needed are
|
|
* `isMinter(address)` and `mint(address, amount)`. The migrator will check
|
|
* that it is a minter for the token.
|
|
* The balance from the legacy token will be transferred to the migrator, as it
|
|
* is migrated, and remain there forever.
|
|
* Although this contract can be used in many different scenarios, the main
|
|
* motivation was to provide a way to migrate ERC20 tokens into an upgradeable
|
|
* version of it using ZeppelinOS. To read more about how this can be done
|
|
* using this implementation, please follow the official documentation site of
|
|
* ZeppelinOS: https://docs.zeppelinos.org/docs/erc20_onboarding.html
|
|
* Example of usage:
|
|
* ```
|
|
* const migrator = await ERC20Migrator.new(legacyToken.address);
|
|
* await newToken.addMinter(migrator.address);
|
|
* await migrator.beginMigration(newToken.address);
|
|
* ```
|
|
*/
|
|
contract ERC20Migrator {
|
|
using SafeERC20 for IERC20;
|
|
|
|
/// Address of the old token contract
|
|
IERC20 private _legacyToken;
|
|
|
|
/// Address of the new token contract
|
|
ERC20Mintable private _newToken;
|
|
|
|
/**
|
|
* @param legacyToken address of the old token contract
|
|
*/
|
|
constructor (IERC20 legacyToken) public {
|
|
require(address(legacyToken) != address(0));
|
|
_legacyToken = legacyToken;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the legacy token that is being migrated.
|
|
*/
|
|
function legacyToken() public view returns (IERC20) {
|
|
return _legacyToken;
|
|
}
|
|
|
|
/**
|
|
* @dev Returns the new token to which we are migrating.
|
|
*/
|
|
function newToken() public view returns (IERC20) {
|
|
return _newToken;
|
|
}
|
|
|
|
/**
|
|
* @dev Begins the migration by setting which is the new token that will be
|
|
* minted. This contract must be a minter for the new token.
|
|
* @param newToken_ the token that will be minted
|
|
*/
|
|
function beginMigration(ERC20Mintable newToken_) public {
|
|
require(address(_newToken) == address(0));
|
|
require(address(newToken_) != address(0));
|
|
require(newToken_.isMinter(address(this)));
|
|
|
|
_newToken = newToken_;
|
|
}
|
|
|
|
/**
|
|
* @dev Transfers part of an account's balance in the old token to this
|
|
* contract, and mints the same amount of new tokens for that account.
|
|
* @param account whose tokens will be migrated
|
|
* @param amount amount of tokens to be migrated
|
|
*/
|
|
function migrate(address account, uint256 amount) public {
|
|
_legacyToken.safeTransferFrom(account, address(this), amount);
|
|
_newToken.mint(account, amount);
|
|
}
|
|
|
|
/**
|
|
* @dev Transfers all of an account's allowed balance in the old token to
|
|
* this contract, and mints the same amount of new tokens for that account.
|
|
* @param account whose tokens will be migrated
|
|
*/
|
|
function migrateAll(address account) public {
|
|
uint256 balance = _legacyToken.balanceOf(account);
|
|
uint256 allowance = _legacyToken.allowance(account, address(this));
|
|
uint256 amount = Math.min(balance, allowance);
|
|
migrate(account, amount);
|
|
}
|
|
}
|