Skip to content

Commit

Permalink
refactor(protocol): refactor vault code with minor improvement (#16797)
Browse files Browse the repository at this point in the history
Co-authored-by: Brecht Devos <[email protected]>
  • Loading branch information
dantaik and Brechtpd authored Apr 23, 2024
1 parent 75841ec commit e12b0fb
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 69 deletions.
29 changes: 4 additions & 25 deletions packages/protocol/contracts/tokenvault/BridgedERC20.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol";
import "./LibBridgedToken.sol";
Expand All @@ -11,12 +10,7 @@ import "./BridgedERC20Base.sol";
/// @notice An upgradeable ERC20 contract that represents tokens bridged from
/// another chain.
/// @custom:security-contact [email protected]
contract BridgedERC20 is
BridgedERC20Base,
IERC20MetadataUpgradeable,
ERC20SnapshotUpgradeable,
ERC20VotesUpgradeable
{
contract BridgedERC20 is BridgedERC20Base, ERC20SnapshotUpgradeable, ERC20VotesUpgradeable {
/// @dev Slot 1.
address public srcToken;

Expand Down Expand Up @@ -68,34 +62,19 @@ contract BridgedERC20 is

/// @notice Gets the name of the token.
/// @return The name.
function name()
public
view
override(ERC20Upgradeable, IERC20MetadataUpgradeable)
returns (string memory)
{
function name() public view override returns (string memory) {
return LibBridgedToken.buildName(super.name(), srcChainId);
}

/// @notice Gets the symbol of the bridged token.
/// @return The symbol.
function symbol()
public
view
override(ERC20Upgradeable, IERC20MetadataUpgradeable)
returns (string memory)
{
function symbol() public view override returns (string memory) {
return LibBridgedToken.buildSymbol(super.symbol());
}

/// @notice Gets the number of decimal places of the token.
/// @return The number of decimal places of the token.
function decimals()
public
view
override(ERC20Upgradeable, IERC20MetadataUpgradeable)
returns (uint8)
{
function decimals() public view override returns (uint8) {
return __srcDecimals;
}

Expand Down
18 changes: 8 additions & 10 deletions packages/protocol/contracts/tokenvault/ERC1155Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
revert VAULT_INTERFACE_NOT_SUPPORTED();
}

(bytes memory data, CanonicalNFT memory ctoken) = _handleMessage(msg.sender, _op);
(bytes memory data, CanonicalNFT memory ctoken) = _handleMessage(_op);

// Create a message to send to the destination chain
IBridge.Message memory message = IBridge.Message({
Expand Down Expand Up @@ -237,23 +237,20 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {

/// @dev Handles the message on the source chain and returns the encoded
/// call on the destination call.
/// @param _user The user's address.
/// @param _op BridgeTransferOp data.
/// @return msgData_ Encoded message data.
/// @return ctoken_ The canonical token.
function _handleMessage(
address _user,
BridgeTransferOp memory _op
)
function _handleMessage(BridgeTransferOp calldata _op)
private
returns (bytes memory msgData_, CanonicalNFT memory ctoken_)
{
unchecked {
// is a btoken, meaning, it does not live on this chain
if (bridgedToCanonical[_op.token].addr != address(0)) {
ctoken_ = bridgedToCanonical[_op.token];
CanonicalNFT storage _ctoken = bridgedToCanonical[_op.token];
if (_ctoken.addr != address(0)) {
ctoken_ = _ctoken;
for (uint256 i; i < _op.tokenIds.length; ++i) {
BridgedERC1155(_op.token).burn(_user, _op.tokenIds[i], _op.amounts[i]);
BridgedERC1155(_op.token).burn(msg.sender, _op.tokenIds[i], _op.amounts[i]);
}
} else {
// is a ctoken token, meaning, it lives on this chain
Expand Down Expand Up @@ -282,7 +279,8 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable {
}
}
msgData_ = abi.encodeCall(
this.onMessageInvocation, abi.encode(ctoken_, _user, _op.to, _op.tokenIds, _op.amounts)
this.onMessageInvocation,
abi.encode(ctoken_, msg.sender, _op.to, _op.tokenIds, _op.amounts)
);
}

Expand Down
37 changes: 14 additions & 23 deletions packages/protocol/contracts/tokenvault/ERC20Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ contract ERC20Vault is BaseVault {
if (btokenBlacklist[_op.token]) revert VAULT_BTOKEN_BLACKLISTED();

(bytes memory data, CanonicalERC20 memory ctoken, uint256 balanceChange) =
_handleMessage(msg.sender, _op.token, _op.to, _op.amount);
_handleMessage(_op);

IBridge.Message memory message = IBridge.Message({
id: 0, // will receive a new value
Expand Down Expand Up @@ -335,39 +335,30 @@ contract ERC20Vault is BaseVault {

/// @dev Handles the message on the source chain and returns the encoded
/// call on the destination call.
/// @param _user The user's address.
/// @param _token The token address.
/// @param _to To address.
/// @param _amount Amount to be sent.
/// @param _op The BridgeTransferOp object.
/// @return msgData_ Encoded message data.
/// @return ctoken_ The canonical token.
/// @return balanceChange_ User token balance actual change after the token
/// transfer. This value is calculated so we do not assume token balance
/// change is the amount of token transferred away.
function _handleMessage(
address _user,
address _token,
address _to,
uint256 _amount
)
function _handleMessage(BridgeTransferOp calldata _op)
private
returns (bytes memory msgData_, CanonicalERC20 memory ctoken_, uint256 balanceChange_)
{
// If it's a bridged token
if (bridgedToCanonical[_token].addr != address(0)) {
ctoken_ = bridgedToCanonical[_token];

CanonicalERC20 storage _ctoken = bridgedToCanonical[_op.token];
if (_ctoken.addr != address(0)) {
ctoken_ = _ctoken;
// Following the "transfer and burn" pattern, as used by USDC
IERC20(_token).safeTransferFrom(_user, address(this), _amount);
IBridgedERC20(_token).burn(_amount);

balanceChange_ = _amount;
IERC20(_op.token).safeTransferFrom(msg.sender, address(this), _op.amount);
IBridgedERC20(_op.token).burn(_op.amount);
balanceChange_ = _op.amount;
} else {
// If it's a canonical token
IERC20Metadata meta = IERC20Metadata(_token);
IERC20Metadata meta = IERC20Metadata(_op.token);
ctoken_ = CanonicalERC20({
chainId: uint64(block.chainid),
addr: _token,
addr: _op.token,
decimals: meta.decimals(),
symbol: meta.symbol(),
name: meta.name()
Expand All @@ -377,14 +368,14 @@ contract ERC20Vault is BaseVault {
// token transferred into this address, this is more accurate than
// simply using `amount` -- some contract may deduct a fee from the
// transferred amount.
IERC20 t = IERC20(_token);
IERC20 t = IERC20(_op.token);
uint256 _balance = t.balanceOf(address(this));
t.safeTransferFrom({ from: msg.sender, to: address(this), value: _amount });
t.safeTransferFrom(msg.sender, address(this), _op.amount);
balanceChange_ = t.balanceOf(address(this)) - _balance;
}

msgData_ = abi.encodeCall(
this.onMessageInvocation, abi.encode(ctoken_, _user, _to, balanceChange_)
this.onMessageInvocation, abi.encode(ctoken_, msg.sender, _op.to, balanceChange_)
);
}

Expand Down
19 changes: 8 additions & 11 deletions packages/protocol/contracts/tokenvault/ERC721Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver {
revert VAULT_INTERFACE_NOT_SUPPORTED();
}

(bytes memory data, CanonicalNFT memory ctoken) = _handleMessage(msg.sender, _op);
(bytes memory data, CanonicalNFT memory ctoken) = _handleMessage(_op);

IBridge.Message memory message = IBridge.Message({
id: 0, // will receive a new value
Expand Down Expand Up @@ -184,22 +184,19 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver {

/// @dev Handles the message on the source chain and returns the encoded
/// call on the destination call.
/// @param _user The user's address.
/// @param _op BridgeTransferOp data.
/// @return msgData_ Encoded message data.
/// @return ctoken_ The canonical token.
function _handleMessage(
address _user,
BridgeTransferOp memory _op
)
function _handleMessage(BridgeTransferOp calldata _op)
private
returns (bytes memory msgData_, CanonicalNFT memory ctoken_)
{
unchecked {
if (bridgedToCanonical[_op.token].addr != address(0)) {
ctoken_ = bridgedToCanonical[_op.token];
CanonicalNFT storage _ctoken = bridgedToCanonical[_op.token];
if (_ctoken.addr != address(0)) {
ctoken_ = _ctoken;
for (uint256 i; i < _op.tokenIds.length; ++i) {
BridgedERC721(_op.token).burn(_user, _op.tokenIds[i]);
BridgedERC721(_op.token).burn(msg.sender, _op.tokenIds[i]);
}
} else {
ERC721Upgradeable t = ERC721Upgradeable(_op.token);
Expand All @@ -212,13 +209,13 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver {
});

for (uint256 i; i < _op.tokenIds.length; ++i) {
t.safeTransferFrom(_user, address(this), _op.tokenIds[i]);
t.safeTransferFrom(msg.sender, address(this), _op.tokenIds[i]);
}
}
}

msgData_ = abi.encodeCall(
this.onMessageInvocation, abi.encode(ctoken_, _user, _op.to, _op.tokenIds)
this.onMessageInvocation, abi.encode(ctoken_, msg.sender, _op.to, _op.tokenIds)
);
}

Expand Down

0 comments on commit e12b0fb

Please sign in to comment.