// SPDX-License-Identifier: MITpragmasolidity 0.8.9;import { IAxelarGateway } from'./interfaces/IAxelarGateway.sol';
import { IBurnableMintableCappedERC20 } from'./interfaces/IBurnableMintableCappedERC20.sol';
import { MintableCappedERC20 } from'./MintableCappedERC20.sol';
import { DepositHandler } from'./DepositHandler.sol';
contractBurnableMintableCappedERC20isIBurnableMintableCappedERC20, MintableCappedERC20{
constructor(stringmemory name,
stringmemory symbol,
uint8 decimals,
uint256 capacity
) MintableCappedERC20(name, symbol, decimals, capacity) {}
functiondepositAddress(bytes32 salt) publicviewreturns (address) {
/* Convert a hash which is bytes32 to an address which is 20-byte long
according to https://docs.soliditylang.org/en/v0.8.1/control-structures.html?highlight=create2#salted-contract-creations-create2 */returnaddress(
uint160(
uint256(
keccak256(
abi.encodePacked(bytes1(0xff), owner, salt, keccak256(abi.encodePacked(type(DepositHandler).creationCode)))
)
)
)
);
}
functionburn(bytes32 salt) externalonlyOwner{
address account = depositAddress(salt);
_burn(account, balanceOf[account]);
}
functionburnFrom(address account, uint256 amount) externalonlyOwner{
uint256 _allowance = allowance[account][msg.sender];
if (_allowance !=type(uint256).max) {
_approve(account, msg.sender, _allowance - amount);
}
_burn(account, amount);
}
}
Contract Source Code
File 2 of 14: DepositHandler.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.9;contractDepositHandler{
errorIsLocked();
errorNotContract();
uint256internalconstant IS_NOT_LOCKED =uint256(1);
uint256internalconstant IS_LOCKED =uint256(2);
uint256internal _lockedStatus = IS_NOT_LOCKED;
modifiernoReenter() {
if (_lockedStatus == IS_LOCKED) revert IsLocked();
_lockedStatus = IS_LOCKED;
_;
_lockedStatus = IS_NOT_LOCKED;
}
functionexecute(address callee, bytescalldata data) externalnoReenterreturns (bool success, bytesmemory returnData) {
if (callee.code.length==0) revert NotContract();
(success, returnData) = callee.call(data);
}
// NOTE: The gateway should always destroy the `DepositHandler` in the same runtime context that deploys it.functiondestroy(address etherDestination) externalnoReenter{
selfdestruct(payable(etherDestination));
}
}
Contract Source Code
File 3 of 14: ERC20.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.9;import { IERC20 } from'./interfaces/IERC20.sol';
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin guidelines: functions revert instead
* of returning `false` on failure. This behavior is nonetheless conventional
* and does not conflict with the expectations of ERC20 applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/contractERC20isIERC20{
mapping(address=>uint256) publicoverride balanceOf;
mapping(address=>mapping(address=>uint256)) publicoverride allowance;
uint256publicoverride totalSupply;
stringpublic name;
stringpublic symbol;
uint8publicimmutable decimals;
/**
* @dev Sets the values for {name}, {symbol}, and {decimals}.
*/constructor(stringmemory name_,
stringmemory symbol_,
uint8 decimals_
) {
name = name_;
symbol = symbol_;
decimals = decimals_;
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/functiontransfer(address recipient, uint256 amount) externalvirtualoverridereturns (bool) {
_transfer(msg.sender, recipient, amount);
returntrue;
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/functionapprove(address spender, uint256 amount) externalvirtualoverridereturns (bool) {
_approve(msg.sender, spender, amount);
returntrue;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/functiontransferFrom(address sender,
address recipient,
uint256 amount
) externalvirtualoverridereturns (bool) {
uint256 _allowance = allowance[sender][msg.sender];
if (_allowance !=type(uint256).max) {
_approve(sender, msg.sender, _allowance - amount);
}
_transfer(sender, recipient, amount);
returntrue;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/functionincreaseAllowance(address spender, uint256 addedValue) externalvirtualreturns (bool) {
_approve(msg.sender, spender, allowance[msg.sender][spender] + addedValue);
returntrue;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/functiondecreaseAllowance(address spender, uint256 subtractedValue) externalvirtualreturns (bool) {
_approve(msg.sender, spender, allowance[msg.sender][spender] - subtractedValue);
returntrue;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/function_transfer(address sender,
address recipient,
uint256 amount
) internalvirtual{
if (sender ==address(0) || recipient ==address(0)) revert InvalidAccount();
balanceOf[sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `to` cannot be the zero address.
*/function_mint(address account, uint256 amount) internalvirtual{
if (account ==address(0)) revert InvalidAccount();
totalSupply += amount;
balanceOf[account] += amount;
emit Transfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/function_burn(address account, uint256 amount) internalvirtual{
if (account ==address(0)) revert InvalidAccount();
balanceOf[account] -= amount;
totalSupply -= amount;
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/function_approve(address owner,
address spender,
uint256 amount
) internalvirtual{
if (owner ==address(0) || spender ==address(0)) revert InvalidAccount();
allowance[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.9;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
errorInvalidAccount();
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 amount) externalreturns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(address sender,
address recipient,
uint256 amount
) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}