Skip to content

Instantly share code, notes, and snippets.

@publu
Last active June 9, 2023 10:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save publu/3707ad4c26eb99cdba104fddb4194c31 to your computer and use it in GitHub Desktop.
Save publu/3707ad4c26eb99cdba104fddb4194c31 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
/**
* @title TokenWrapper
* @dev A contract that allows users to wrap and unwrap an ERC20 token.
* It provides a bridging functionality with Axelar using POL (Protocol-Owned Liquidity),
* and an additional layer of security for users in case of bridge issues.
* Users and the protocol can wrap the MAI token into the Axelar ecosystem to bridge
* it across various chains available in the Axelar bridge.
*/
contract TokenWrapper is ERC20, Ownable2Step, Pausable {
IERC20 public constant token = IERC20(0x8D6CeBD76f18E1558D4DB88138e2DeFB3909fAD6); // MAI on ETH
event Deposit(address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
/**
* @dev Initializes the TokenWrapper contract.
*/
constructor() ERC20("Wrapped MAI", "WMAI") {}
/**
* @dev Allows users to deposit tokens into the contract and receive wrapped tokens in return.
* @param amount The amount of tokens to deposit.
*/
function deposit(uint256 amount) public whenNotPaused {
// Transfers tokens from the user to the contract
bool transferSuccessful = token.transferFrom(_msgSender(), address(this), amount);
require(transferSuccessful, "Token transfer was not successful.");
_mint(_msgSender(), amount); // Mints wrapped tokens to the user
emit Deposit(_msgSender(), amount); // Emits the Deposit event
}
/**
* @dev Allows users to withdraw wrapped tokens and receive the underlying tokens in return.
* @param amount The amount of wrapped tokens to withdraw.
*/
function withdraw(uint256 amount) public whenNotPaused {
_burn(_msgSender(), amount); // Burns the wrapped tokens from the user
// Transfers the underlying tokens to the user
bool transferSuccessful = token.transfer(_msgSender(), amount);
require(transferSuccessful, "Token transfer was not successful.");
emit Withdrawal(_msgSender(), amount); // Emits the Withdrawal event
}
/**
* @dev Allows the owner of the contract to pause token transfers.
* Only the contract owner can call this function.
*/
function pause() public onlyOwner {
_pause(); // Pauses token transfers
}
/**
* @dev Allows the owner of the contract to unpause token transfers.
* Only the contract owner can call this function.
*/
function unpause() public onlyOwner {
_unpause(); // Unpauses token transfers
}
/**
* @dev Allows the owner to withdraw any ERC20 tokens sent here accidentally.
* @param _tokenAddress The address of the token to withdraw.
* @param _amount The amount of the token to withdraw.
*/
function withdrawLostTokens(address _tokenAddress, uint256 _amount) public onlyOwner {
IERC20 _token = IERC20(_tokenAddress);
require(_token != token, "Cannot withdraw the wrapped token");
require(_token.balanceOf(address(this)) >= _amount, "Not enough balance");
_token.transfer(_msgSender(), _amount);
}
/**
* @dev Allows the owner to withdraw any extra balance of the underlying token.
*/
function withdrawExtraBalance() public onlyOwner {
uint256 extraBalance = token.balanceOf(address(this)) - totalSupply();
require(extraBalance > 0, "No extra balance to withdraw");
token.transfer(_msgSender(), extraBalance);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment