From 039c6a17b2dd50b679bdbf1b1eda045b2eed4f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Keszey=20D=C3=A1niel?= Date: Sat, 10 Feb 2024 20:34:24 +0530 Subject: [PATCH] Add votes and snapshot plugin --- .../contracts/tokenvault/BridgedERC20.sol | 76 +++++++++++++++++-- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/packages/protocol/contracts/tokenvault/BridgedERC20.sol b/packages/protocol/contracts/tokenvault/BridgedERC20.sol index bd7d8792c4c..bae0aad5f54 100644 --- a/packages/protocol/contracts/tokenvault/BridgedERC20.sol +++ b/packages/protocol/contracts/tokenvault/BridgedERC20.sol @@ -17,23 +17,39 @@ pragma solidity 0.8.24; import "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; import "lib/openzeppelin-contracts/contracts/utils/Strings.sol"; - +import + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol"; +import + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; import "./LibBridgedToken.sol"; import "./BridgedERC20Base.sol"; /// @title BridgedERC20 /// @notice An upgradeable ERC20 contract that represents tokens bridged from /// another chain. -contract BridgedERC20 is BridgedERC20Base, IERC20MetadataUpgradeable, ERC20Upgradeable { +contract BridgedERC20 is + BridgedERC20Base, + IERC20MetadataUpgradeable, + ERC20SnapshotUpgradeable, + ERC20VotesUpgradeable +{ address public srcToken; // slot 1 uint8 private srcDecimals; uint256 public srcChainId; // slot 2 + address public snapshooter; // slot 3 - uint256[48] private __gap; + uint256[47] private __gap; error BTOKEN_CANNOT_RECEIVE(); error BTOKEN_INVALID_PARAMS(); + error BTOKEN_UNAUTHORIZED(); + + modifier onlyOwnerOrSnapshooter { + if (msg.sender != owner() && msg.sender != snapshooter) + revert BTOKEN_UNAUTHORIZED(); + _; + } /// @notice Initializes the contract. /// @dev Different BridgedERC20 Contract is deployed per unique _srcToken /// (e.g., one for USDC, one for USDT, etc.). @@ -65,6 +81,9 @@ contract BridgedERC20 is BridgedERC20Base, IERC20MetadataUpgradeable, ERC20Upgra // Initialize OwnerUUPSUpgradable and ERC20Upgradeable __Essential_init(_addressManager); __ERC20_init({ name_: _name, symbol_: _symbol }); + __ERC20Snapshot_init(); + __ERC20Votes_init(); + __ERC20Permit_init(_name); // Set contract properties srcToken = _srcToken; @@ -72,6 +91,16 @@ contract BridgedERC20 is BridgedERC20Base, IERC20MetadataUpgradeable, ERC20Upgra srcDecimals = _decimals; } + /// @notice Set the snapshoter address. + function setSnapshoter(address _snapshooter) external onlyOwner { + snapshooter = _snapshooter; + } + + /// @notice Creates a new token snapshot. + function snapshot() external onlyOwnerOrSnapshooter { + _snapshot(); + } + /// @notice Gets the name of the token. /// @return The name. function name() @@ -119,16 +148,49 @@ contract BridgedERC20 is BridgedERC20Base, IERC20MetadataUpgradeable, ERC20Upgra _burn(from, amount); } + /// @dev For ERC20SnapshotUpgradeable and ERC20VotesUpgradeable, need to implement the following + /// functions function _beforeTokenTransfer( - address, /*from*/ + address from, address to, - uint256 /*amount*/ + uint256 amount ) internal - virtual - override + override(ERC20Upgradeable, ERC20SnapshotUpgradeable) { if (to == address(this)) revert BTOKEN_CANNOT_RECEIVE(); if (paused()) revert INVALID_PAUSE_STATUS(); + super._beforeTokenTransfer(from, to, amount); + } + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) + internal + override(ERC20Upgradeable, ERC20VotesUpgradeable) + { + super._afterTokenTransfer(from, to, amount); + } + + function _mint( + address to, + uint256 amount + ) + internal + override(ERC20Upgradeable, ERC20VotesUpgradeable) + { + super._mint(to, amount); + } + + function _burn( + address from, + uint256 amount + ) + internal + override(ERC20Upgradeable, ERC20VotesUpgradeable) + { + super._burn(from, amount); } }