-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(fix) Check that the remote token manager exists before trying to use…
… it.
- Loading branch information
1 parent
92ad6aa
commit bec51bf
Showing
4 changed files
with
484 additions
and
0 deletions.
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
...ts/contracts/periphery/TokenManagerV4/LockAndReleaseOrNativeTokenManagerUpgradeableV4.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import {TokenManagerUpgradeableV3, ITokenManager} from "contracts/periphery/TokenManagerV4/TokenManagerUpgradeableV4.sol"; | ||
import {IERC20} from "contracts/periphery/LockAndReleaseTokenManagerUpgradeable.sol"; | ||
import {IRelayer, CallMetadata} from "contracts/core/Relayer.sol"; | ||
|
||
interface ILockAndReleaseOrNativeTokenManager { | ||
event Locked(address indexed token, address indexed from, uint amount); | ||
event Released( | ||
address indexed token, | ||
address indexed recipient, | ||
uint amount | ||
); | ||
} | ||
|
||
contract LockAndReleaseOrNativeTokenManagerUpgradeableV3 is | ||
ILockAndReleaseOrNativeTokenManager, | ||
TokenManagerUpgradeableV3 | ||
{ | ||
address public constant NATIVE_ASSET_HASH = address(0); | ||
|
||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
/// @dev Allow this contract to receive native tokens. | ||
receive() external payable {} | ||
|
||
// Outgoing | ||
function _handleTransfer( | ||
address token, | ||
address from, | ||
uint amount | ||
) internal override { | ||
if (token == NATIVE_ASSET_HASH) { | ||
(bool success, ) = payable(this).call{ value: amount }(""); | ||
require(success, "Native asset transfer failed"); | ||
} else { | ||
IERC20(token).transferFrom(from, address(this), amount); | ||
} | ||
emit Locked(token, from, amount); | ||
} | ||
|
||
// Incoming | ||
function _handleAccept( | ||
address token, | ||
address recipient, | ||
uint amount | ||
) internal override { | ||
if (token == NATIVE_ASSET_HASH) { | ||
(bool success, ) = recipient.call{value: amount}(""); | ||
require(success, "Native asset transfer failed"); | ||
} else { | ||
IERC20(token).transfer(recipient, amount); | ||
} | ||
emit Released(token, recipient, amount); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
smart-contracts/contracts/periphery/TokenManagerV4/LockProxyTokenManagerUpgradeableV4.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import {TokenManagerUpgradeableV4, ITokenManager} from "contracts/periphery/TokenManagerV3/TokenManagerUpgradeableV4.sol"; | ||
import {BridgedToken} from "contracts/periphery/BridgedToken.sol"; | ||
import {IERC20} from "contracts/periphery/LockAndReleaseTokenManagerUpgradeable.sol"; | ||
import { ILockProxyTokenManagerStorage, LockProxyTokenManagerStorage } from "contracts/periphery/LockProxyTokenManagerStorage.sol"; | ||
import { ILockProxyExtensionTransfer } from "contracts/periphery/ILockProxyExtensionTransfer.sol"; | ||
|
||
interface ILockProxyTokenManager is ILockProxyTokenManagerStorage { | ||
// Args in this order to match other token managers. | ||
event SentToLockProxy(address indexed token, address indexed sender, uint amount); | ||
event WithdrawnFromLockProxy(address indexed token, address indexed receipient, uint amount); | ||
} | ||
|
||
// This is the lock proxy token manager that runs on EVM chains. It talks to an EVM LockProxy. | ||
contract LockProxyTokenManagerUpgradeableV4 is TokenManagerUpgradeableV4, ILockProxyTokenManager, LockProxyTokenManagerStorage { | ||
address public constant NATIVE_ASSET_HASH = address(0); | ||
|
||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function reinitialize(uint fees) external reinitializer(2) { | ||
_setFees(fees); | ||
} | ||
|
||
// Incoming currency - transfer into the lock proxy (directly!) | ||
function _handleTransfer(address token, address from, uint amount) internal override { | ||
address lockProxyAddress = getLockProxy(); | ||
// Just transfer value to the lock proxy. | ||
if (token == NATIVE_ASSET_HASH) { | ||
(bool success, ) = lockProxyAddress.call{value: amount}(""); | ||
emit SentToLockProxy(token, from, amount); | ||
require(success, "Transfer failed"); | ||
return; | ||
} | ||
|
||
IERC20 erc20token = IERC20(token); | ||
erc20token.transferFrom(from, address(lockProxyAddress), amount); | ||
emit SentToLockProxy(token, from, amount); | ||
} | ||
|
||
// Withdrawals are processed via the lockProxyProxy. | ||
function _handleAccept(address token, address recipient, uint amount) internal override { | ||
address lockProxyProxyAddress = getLockProxyProxy(); | ||
address lockProxyAddress = getLockProxy(); | ||
ILockProxyExtensionTransfer lp = ILockProxyExtensionTransfer(payable(lockProxyProxyAddress)); | ||
// Sadly, extensionTransfer() takes the same arguments as the withdrawn event but in a | ||
// different order. This will automagically transfer native token if token==0. | ||
|
||
// Native tokens are transferred by the call; for everyone else, it sets an allowance and we | ||
// then do the transfer from here. | ||
if (token == address(0)) { | ||
lp.extensionTransfer(recipient, address(0), amount); | ||
} else { | ||
lp.extensionTransfer(address(this), token, amount); | ||
IERC20 erc20token = IERC20(token); | ||
// Although the lockProxyProxy is the registered extension, the tokens are held by the actual | ||
// lockProxy | ||
erc20token.transferFrom(lockProxyAddress, recipient, amount); | ||
} | ||
emit WithdrawnFromLockProxy(token, recipient, amount); | ||
} | ||
|
||
function setLockProxyData(address lockProxy, address lockProxyProxy) external onlyOwner { | ||
_setLockProxyData(lockProxy, lockProxyProxy); | ||
} | ||
|
||
} |
120 changes: 120 additions & 0 deletions
120
smart-contracts/contracts/periphery/TokenManagerV4/MintAndBurnTokenManagerUpgradeableV4.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity ^0.8.20; | ||
|
||
import {TokenManagerUpgradeableV4, ITokenManager} from "contracts/periphery/TokenManagerV3/TokenManagerUpgradeableV4.sol"; | ||
import {BridgedToken} from "contracts/periphery/BridgedToken.sol"; | ||
|
||
interface IMintAndBurnTokenManager { | ||
event Minted(address indexed token, address indexed recipient, uint amount); | ||
event Burned(address indexed token, address indexed from, uint amount); | ||
event BridgedTokenDeployed( | ||
address token, | ||
address remoteToken, | ||
address remoteTokenManager, | ||
uint remoteChainId | ||
); | ||
} | ||
|
||
contract MintAndBurnTokenManagerUpgradeableV3 is | ||
IMintAndBurnTokenManager, | ||
TokenManagerUpgradeableV3 | ||
{ | ||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function deployToken( | ||
string calldata name, | ||
string calldata symbol, | ||
uint8 decimals, | ||
address remoteToken, | ||
address tokenManager, | ||
uint remoteChainId | ||
) external returns (BridgedToken) { | ||
return | ||
_deployToken( | ||
name, | ||
symbol, | ||
decimals, | ||
remoteToken, | ||
tokenManager, | ||
remoteChainId | ||
); | ||
} | ||
|
||
function deployToken( | ||
string calldata name, | ||
string calldata symbol, | ||
address remoteToken, | ||
address tokenManager, | ||
uint remoteChainId | ||
) external returns (BridgedToken) { | ||
return | ||
_deployToken( | ||
name, | ||
symbol, | ||
18, | ||
remoteToken, | ||
tokenManager, | ||
remoteChainId | ||
); | ||
} | ||
|
||
function _deployToken( | ||
string calldata name, | ||
string calldata symbol, | ||
uint8 decimals, | ||
address remoteToken, | ||
address tokenManager, | ||
uint remoteChainId | ||
) internal onlyOwner returns (BridgedToken) { | ||
// TODO: deployed counterfactually | ||
BridgedToken bridgedToken = new BridgedToken(name, symbol, decimals); | ||
RemoteToken memory remoteTokenStruct = RemoteToken( | ||
remoteToken, | ||
tokenManager, | ||
remoteChainId | ||
); | ||
|
||
_registerToken(address(bridgedToken), remoteTokenStruct); | ||
|
||
emit BridgedTokenDeployed( | ||
address(bridgedToken), | ||
remoteToken, | ||
tokenManager, | ||
remoteChainId | ||
); | ||
|
||
return bridgedToken; | ||
} | ||
|
||
function transferTokenOwnership( | ||
address localToken, | ||
uint remoteChainId, | ||
address newOwner | ||
) external onlyOwner { | ||
BridgedToken(localToken).transferOwnership(newOwner); | ||
_removeToken(localToken, remoteChainId); | ||
} | ||
|
||
// Outgoing | ||
function _handleTransfer( | ||
address token, | ||
address from, | ||
uint amount | ||
) internal override { | ||
BridgedToken(token).burnFrom(from, amount); | ||
emit Burned(token, from, amount); | ||
} | ||
|
||
// Incoming | ||
function _handleAccept( | ||
address token, | ||
address recipient, | ||
uint amount | ||
) internal override { | ||
BridgedToken(token).mint(recipient, amount); | ||
emit Minted(token, recipient, amount); | ||
} | ||
} |
Oops, something went wrong.