-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PDE-410] Integrate NestTeller and NestAtomicQueue as BoringVault mod…
…ule (#137)
- Loading branch information
Showing
14 changed files
with
880 additions
and
276 deletions.
There are no files selected for viewing
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
Submodule nucleus-boring-vault
added at
5b9eec
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/ | ||
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/ | ||
@solmate/=lib/solmate/src/ | ||
@solmate/=lib/solmate/src/ | ||
@boringvault/=lib/nucleus-boring-vault/ |
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
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,17 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.25; | ||
|
||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
||
contract MockERC20 is ERC20 { | ||
|
||
// small hack to be excluded from coverage report | ||
function test() public { } | ||
|
||
constructor(string memory name, string memory symbol) ERC20(name, symbol) { } | ||
|
||
function mint(address to, uint256 amount) public { | ||
_mint(to, amount); | ||
} | ||
|
||
} |
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,83 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.25; | ||
|
||
import { MessageLibManager } from "@layerzerolabs/lz-evm-protocol-v2/contracts/MessageLibManager.sol"; | ||
import { MessagingChannel } from "@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingChannel.sol"; | ||
import { MessagingComposer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingComposer.sol"; | ||
import { MessagingContext } from "@layerzerolabs/lz-evm-protocol-v2/contracts/MessagingContext.sol"; | ||
import { | ||
ILayerZeroEndpointV2, | ||
MessagingFee, | ||
MessagingParams, | ||
MessagingReceipt, | ||
Origin | ||
} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; | ||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
||
contract MockLayerZeroEndpoint is | ||
MessagingChannel, | ||
MessageLibManager, | ||
MessagingComposer, | ||
MessagingContext, | ||
ILayerZeroEndpointV2 | ||
{ | ||
|
||
address public lzToken; | ||
mapping(address oapp => address delegate) public delegates; | ||
|
||
constructor( | ||
uint32 _eid, | ||
address _owner | ||
) MessagingChannel(_eid) MessageLibManager() MessagingComposer() MessagingContext() Ownable(_owner) { } | ||
|
||
function quote(MessagingParams calldata, address) external pure returns (MessagingFee memory) { | ||
return MessagingFee(0, 0); | ||
} | ||
|
||
function send(MessagingParams calldata _params, address) external payable returns (MessagingReceipt memory) { | ||
bytes32 guid = keccak256(abi.encodePacked(msg.sender, _params.dstEid, _params.receiver)); | ||
return MessagingReceipt(guid, 1, MessagingFee(0, 0)); | ||
} | ||
|
||
function verify(Origin calldata, address, bytes32) external pure { } | ||
|
||
function lzReceive(Origin calldata, address, bytes32, bytes calldata, bytes calldata) external payable { } | ||
|
||
function clear(address, Origin calldata, bytes32, bytes calldata) external { } | ||
|
||
function setLzToken( | ||
address _lzToken | ||
) external { | ||
lzToken = _lzToken; | ||
emit LzTokenSet(_lzToken); | ||
} | ||
|
||
function setDelegate( | ||
address _delegate | ||
) external { | ||
delegates[msg.sender] = _delegate; | ||
emit DelegateSet(msg.sender, _delegate); | ||
} | ||
|
||
function nativeToken() external pure returns (address) { | ||
return address(0); | ||
} | ||
|
||
function initializable(Origin calldata, address) external pure returns (bool) { | ||
return true; | ||
} | ||
|
||
function verifiable(Origin calldata, address) external pure returns (bool) { | ||
return true; | ||
} | ||
|
||
// Override required internal functions | ||
function _assertAuthorized( | ||
address _oapp | ||
) internal view override(MessagingChannel, MessageLibManager) { | ||
if (msg.sender != _oapp && msg.sender != delegates[_oapp]) { | ||
revert("Unauthorized"); | ||
} | ||
} | ||
|
||
} |
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 |
---|---|---|
@@ -1,117 +1,141 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.25; | ||
|
||
import { IBoringVault } from "../interfaces/IBoringVault.sol"; | ||
import { BeforeTransferHook } from "@boringvault/src/interfaces/BeforeTransferHook.sol"; | ||
import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; | ||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; | ||
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; | ||
import { Auth, Authority } from "@solmate/auth/Auth.sol"; | ||
import { ERC20 } from "@solmate/tokens/ERC20.sol"; | ||
import { SafeTransferLib } from "@solmate/utils/SafeTransferLib.sol"; | ||
|
||
import { IBoringVault } from "../interfaces/IBoringVault.sol"; | ||
|
||
contract MockVault is ERC20, Auth, ERC721Holder, ERC1155Holder, IBoringVault { | ||
|
||
using SafeERC20 for IERC20; | ||
contract MockVault is IBoringVault, Auth, ERC721Holder, ERC1155Holder { | ||
|
||
// token => account => balance | ||
mapping(address => mapping(address => uint256)) private _balances; | ||
using SafeTransferLib for ERC20; | ||
|
||
mapping(address => mapping(address => mapping(address => uint256))) private _allowances; | ||
// State variables | ||
string public name; | ||
string public symbol; | ||
uint8 public decimals; | ||
uint256 public totalSupply; | ||
mapping(address => uint256) public balanceOf; | ||
mapping(address => mapping(address => uint256)) public allowance; | ||
BeforeTransferHook public hook; | ||
|
||
IERC20 public asset; | ||
IERC20 public immutable usdc; | ||
IERC20 public immutable usdt; | ||
address public beforeTransferHook; | ||
// Events | ||
event DebugCall(string functionName, bytes data); | ||
event Enter(address indexed from, address indexed asset, uint256 amount, address indexed to, uint256 shares); | ||
event Exit(address indexed to, address indexed asset, uint256 amount, address indexed from, uint256 shares); | ||
|
||
constructor( | ||
address _owner, | ||
string memory _name, | ||
string memory _symbol, | ||
address _usdc | ||
) ERC20(_name, _symbol) Auth(_owner, Authority(address(0))) { | ||
usdc = IERC20(_usdc); | ||
uint8 _decimals | ||
) Auth(_owner, Authority(address(0))) { | ||
name = _name; | ||
symbol = _symbol; | ||
decimals = _decimals; | ||
} | ||
|
||
function enter(address from, address asset_, uint256 assetAmount, address to, uint256 shareAmount) external { | ||
if (assetAmount > 0) { | ||
IERC20(asset_).safeTransferFrom(from, address(this), assetAmount); | ||
} | ||
_balances[asset_][to] += shareAmount; | ||
_allowances[asset_][to][msg.sender] = type(uint256).max; | ||
function approve(address spender, uint256 amount) public returns (bool) { | ||
allowance[msg.sender][spender] = amount; | ||
emit Approval(msg.sender, spender, amount); | ||
return true; | ||
} | ||
|
||
function exit(address to, address asset_, uint256 assetAmount, address from, uint256 shareAmount) external { | ||
// Change from checking 'from' balance to checking the actual owner's balance | ||
address owner = from == msg.sender ? to : from; | ||
require(_balances[asset_][owner] >= shareAmount, "MockVault: insufficient balance"); | ||
function transfer(address to, uint256 amount) public returns (bool) { | ||
_callBeforeTransfer(msg.sender); | ||
return _transfer(msg.sender, to, amount); | ||
} | ||
|
||
uint256 allowed = _allowances[asset_][owner][msg.sender]; | ||
function transferFrom(address from, address to, uint256 amount) public returns (bool) { | ||
_callBeforeTransfer(from); | ||
uint256 allowed = allowance[from][msg.sender]; | ||
if (allowed != type(uint256).max) { | ||
require(allowed >= shareAmount, "MockVault: insufficient allowance"); | ||
_allowances[asset_][owner][msg.sender] = allowed - shareAmount; | ||
} | ||
|
||
_balances[asset_][owner] -= shareAmount; | ||
|
||
// Changed: Transfer to 'to' instead of msg.sender, and always transfer if we have shares | ||
if (shareAmount > 0) { | ||
IERC20(asset_).safeTransfer(to, shareAmount); | ||
require(allowed >= amount, "MockVault: insufficient allowance"); | ||
allowance[from][msg.sender] = allowed - amount; | ||
} | ||
return _transfer(from, to, amount); | ||
} | ||
|
||
function transferFrom(address asset_, address from, address to, uint256 amount) external returns (bool) { | ||
require(_balances[asset_][from] >= amount, "MockVault: insufficient balance"); | ||
function _transfer(address from, address to, uint256 amount) internal returns (bool) { | ||
require(from != address(0), "MockVault: transfer from zero address"); | ||
require(to != address(0), "MockVault: transfer to zero address"); | ||
require(balanceOf[from] >= amount, "MockVault: insufficient balance"); | ||
|
||
uint256 allowed = _allowances[asset_][from][msg.sender]; | ||
if (allowed != type(uint256).max) { | ||
require(allowed >= amount, "MockVault: insufficient allowance"); | ||
_allowances[asset_][from][msg.sender] = allowed - amount; | ||
} | ||
balanceOf[from] -= amount; | ||
balanceOf[to] += amount; | ||
|
||
_balances[asset_][from] -= amount; | ||
_balances[asset_][to] += amount; | ||
emit Transfer(from, to, amount); | ||
return true; | ||
} | ||
|
||
function approve(address asset_, address spender, uint256 amount) external returns (bool) { | ||
_allowances[asset_][msg.sender][spender] = amount; | ||
return true; | ||
function _mint(address to, uint256 amount) internal { | ||
require(to != address(0), "MockVault: mint to zero address"); | ||
totalSupply += amount; | ||
balanceOf[to] += amount; | ||
emit Transfer(address(0), to, amount); | ||
} | ||
|
||
function balanceOf( | ||
address account | ||
) public view virtual override(ERC20, IERC20) returns (uint256) { | ||
// Return total balance across all assets | ||
return _balances[address(usdc)][account] + _balances[address(usdt)][account]; | ||
function _burn(address from, uint256 amount) internal { | ||
require(from != address(0), "MockVault: burn from zero address"); | ||
require(balanceOf[from] >= amount, "MockVault: insufficient balance"); | ||
totalSupply -= amount; | ||
balanceOf[from] -= amount; | ||
emit Transfer(from, address(0), amount); | ||
} | ||
|
||
function totalSupply() public view virtual override(ERC20, IERC20) returns (uint256) { | ||
// Return total supply across all assets | ||
return _balances[address(usdc)][address(this)] + _balances[address(usdt)][address(this)]; | ||
} | ||
function enter( | ||
address from, | ||
address asset, | ||
uint256 assetAmount, | ||
address to, | ||
uint256 shareAmount | ||
) external override requiresAuth { | ||
emit DebugCall("enter", abi.encode(from, asset, assetAmount, to, shareAmount)); | ||
|
||
function decimals() public pure virtual override(ERC20, IERC20Metadata) returns (uint8) { | ||
return 6; | ||
} | ||
if (assetAmount > 0) { | ||
ERC20(asset).safeTransferFrom(from, address(this), assetAmount); | ||
} | ||
|
||
function tokenBalance(address token, address account) external view returns (uint256) { | ||
return _balances[token][account]; | ||
} | ||
_mint(to, shareAmount); | ||
|
||
function setBalance(address token, uint256 amount) external { | ||
_balances[token][address(this)] = amount; | ||
emit Enter(from, asset, assetAmount, to, shareAmount); | ||
} | ||
|
||
function allowance(address asset_, address owner, address spender) external view returns (uint256) { | ||
return _allowances[asset_][owner][spender]; | ||
function exit( | ||
address to, | ||
address asset, | ||
uint256 assetAmount, | ||
address from, | ||
uint256 shareAmount | ||
) external override requiresAuth { | ||
emit DebugCall("exit", abi.encode(to, asset, assetAmount, from, shareAmount)); | ||
|
||
_burn(from, shareAmount); | ||
|
||
if (assetAmount > 0) { | ||
ERC20(asset).safeTransfer(to, assetAmount); | ||
} | ||
|
||
emit Exit(to, address(asset), assetAmount, from, shareAmount); | ||
} | ||
|
||
function setBeforeTransferHook( | ||
address hook | ||
) external { | ||
beforeTransferHook = hook; | ||
address _hook | ||
) external requiresAuth { | ||
hook = BeforeTransferHook(_hook); | ||
} | ||
|
||
function _callBeforeTransfer( | ||
address from | ||
) internal view { | ||
if (address(hook) != address(0)) { | ||
hook.beforeTransfer(from); | ||
} | ||
} | ||
|
||
receive() external payable { } | ||
|
||
} |
Oops, something went wrong.