TokenImplementation.sol 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // contracts/TokenImplementation.sol
  2. // SPDX-License-Identifier: Apache 2
  3. pragma solidity ^0.8.0;
  4. import "./TokenState.sol";
  5. import "@openzeppelin/contracts/access/Ownable.sol";
  6. import "@openzeppelin/contracts/utils/Context.sol";
  7. import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
  8. // Based on the OpenZepplin ERC20 implementation, licensed under MIT
  9. contract TokenImplementation is TokenState, Context {
  10. event Transfer(address indexed from, address indexed to, uint256 value);
  11. event Approval(address indexed owner, address indexed spender, uint256 value);
  12. function initialize(
  13. string memory name_,
  14. string memory symbol_,
  15. uint8 decimals_,
  16. uint64 sequence_,
  17. address owner_,
  18. uint16 chainId_,
  19. bytes32 nativeContract_
  20. ) initializer public {
  21. _state.name = name_;
  22. _state.symbol = symbol_;
  23. _state.decimals = decimals_;
  24. _state.metaLastUpdatedSequence = sequence_;
  25. _state.owner = owner_;
  26. _state.chainId = chainId_;
  27. _state.nativeContract = nativeContract_;
  28. }
  29. function name() public view returns (string memory) {
  30. return string(abi.encodePacked(_state.name, " (Wormhole)"));
  31. }
  32. function symbol() public view returns (string memory) {
  33. return _state.symbol;
  34. }
  35. function owner() public view returns (address) {
  36. return _state.owner;
  37. }
  38. function decimals() public view returns (uint8) {
  39. return _state.decimals;
  40. }
  41. function totalSupply() public view returns (uint256) {
  42. return _state.totalSupply;
  43. }
  44. function chainId() public view returns (uint16) {
  45. return _state.chainId;
  46. }
  47. function nativeContract() public view returns (bytes32) {
  48. return _state.nativeContract;
  49. }
  50. function balanceOf(address account_) public view returns (uint256) {
  51. return _state.balances[account_];
  52. }
  53. function transfer(address recipient_, uint256 amount_) public returns (bool) {
  54. _transfer(_msgSender(), recipient_, amount_);
  55. return true;
  56. }
  57. function allowance(address owner_, address spender_) public view returns (uint256) {
  58. return _state.allowances[owner_][spender_];
  59. }
  60. function approve(address spender_, uint256 amount_) public returns (bool) {
  61. _approve(_msgSender(), spender_, amount_);
  62. return true;
  63. }
  64. function transferFrom(address sender_, address recipient_, uint256 amount_) public returns (bool) {
  65. _transfer(sender_, recipient_, amount_);
  66. uint256 currentAllowance = _state.allowances[sender_][_msgSender()];
  67. require(currentAllowance >= amount_, "ERC20: transfer amount exceeds allowance");
  68. _approve(sender_, _msgSender(), currentAllowance - amount_);
  69. return true;
  70. }
  71. function increaseAllowance(address spender_, uint256 addedValue_) public returns (bool) {
  72. _approve(_msgSender(), spender_, _state.allowances[_msgSender()][spender_] + addedValue_);
  73. return true;
  74. }
  75. function decreaseAllowance(address spender_, uint256 subtractedValue_) public returns (bool) {
  76. uint256 currentAllowance = _state.allowances[_msgSender()][spender_];
  77. require(currentAllowance >= subtractedValue_, "ERC20: decreased allowance below zero");
  78. _approve(_msgSender(), spender_, currentAllowance - subtractedValue_);
  79. return true;
  80. }
  81. function _transfer(address sender_, address recipient_, uint256 amount_) internal {
  82. require(sender_ != address(0), "ERC20: transfer from the zero address");
  83. require(recipient_ != address(0), "ERC20: transfer to the zero address");
  84. uint256 senderBalance = _state.balances[sender_];
  85. require(senderBalance >= amount_, "ERC20: transfer amount exceeds balance");
  86. _state.balances[sender_] = senderBalance - amount_;
  87. _state.balances[recipient_] += amount_;
  88. emit Transfer(sender_, recipient_, amount_);
  89. }
  90. function mint(address account_, uint256 amount_) public onlyOwner {
  91. _mint(account_, amount_);
  92. }
  93. function _mint(address account_, uint256 amount_) internal {
  94. require(account_ != address(0), "ERC20: mint to the zero address");
  95. _state.totalSupply += amount_;
  96. _state.balances[account_] += amount_;
  97. emit Transfer(address(0), account_, amount_);
  98. }
  99. function burn(address account_, uint256 amount_) public onlyOwner {
  100. _burn(account_, amount_);
  101. }
  102. function _burn(address account_, uint256 amount_) internal {
  103. require(account_ != address(0), "ERC20: burn from the zero address");
  104. uint256 accountBalance = _state.balances[account_];
  105. require(accountBalance >= amount_, "ERC20: burn amount exceeds balance");
  106. _state.balances[account_] = accountBalance - amount_;
  107. _state.totalSupply -= amount_;
  108. emit Transfer(account_, address(0), amount_);
  109. }
  110. function _approve(address owner_, address spender_, uint256 amount_) internal virtual {
  111. require(owner_ != address(0), "ERC20: approve from the zero address");
  112. require(spender_ != address(0), "ERC20: approve to the zero address");
  113. _state.allowances[owner_][spender_] = amount_;
  114. emit Approval(owner_, spender_, amount_);
  115. }
  116. function updateDetails(string memory name_, string memory symbol_, uint64 sequence_) public onlyOwner {
  117. require(_state.metaLastUpdatedSequence < sequence_, "current metadata is up to date");
  118. _state.name = name_;
  119. _state.symbol = symbol_;
  120. _state.metaLastUpdatedSequence = sequence_;
  121. }
  122. modifier onlyOwner() {
  123. require(owner() == _msgSender(), "caller is not the owner");
  124. _;
  125. }
  126. modifier initializer() {
  127. require(
  128. !_state.initialized,
  129. "Already initialized"
  130. );
  131. _state.initialized = true;
  132. _;
  133. }
  134. }