From df7b43aa9c1fc3d188b7e9a33290d587bd185470 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 10:50:49 +0530 Subject: [PATCH 01/28] fix: TCB-02 --- contracts/Bridge/token/TokenController.sol | 1 + test/proxyOFT.ts | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index a5dbe50..e66ed65 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -114,6 +114,7 @@ contract TokenController is Ownable, Pausable { */ function setMintCap(address minter_, uint256 amount_) external { _ensureAllowed("setMintCap(address,uint256)"); + require(amount_ > minterToMintedAmount[minter_], "New cap should be greater than minted tokens"); minterToCap[minter_] = amount_; emit MintCapChanged(minter_, amount_); } diff --git a/test/proxyOFT.ts b/test/proxyOFT.ts index c9752c0..20fccc9 100644 --- a/test/proxyOFT.ts +++ b/test/proxyOFT.ts @@ -508,6 +508,33 @@ describe("Proxy OFTV2: ", function () { accessControlManager.isAllowedToCall.returns(true); }); + it("Reverts if try to set cap less than already minted tokens", async function () { + const initialAmount = ethers.utils.parseEther("20", 18); + await localToken.connect(acc2).faucet(initialAmount); + await localToken.connect(acc2).approve(localOFT.address, initialAmount); + const amount = ethers.utils.parseEther("10", 18); + const acc3AddressBytes32 = ethers.utils.defaultAbiCoder.encode(["address"], [acc3.address]); + const nativeFee = ( + await localOFT.estimateSendFee(remoteChainId, acc3AddressBytes32, amount, false, defaultAdapterParams) + ).nativeFee; + + await localOFT + .connect(acc2) + .sendFrom( + acc2.address, + remoteChainId, + acc3AddressBytes32, + amount, + [acc2.address, ethers.constants.AddressZero, defaultAdapterParams], + { value: nativeFee }, + ), + // Msg should reach remote chain + expect(await remoteEndpoint.inboundNonce(localChainId, localPath)).equals(1); + await expect(remoteToken.connect(acc1).setMintCap(remoteOFT.address, convertToUnit(1, 18))).to.be.revertedWith( + "New cap should be greater than minted tokens", + ); + }); + it("Reverts on remote chain if minting cap is reached", async function () { await remoteToken.connect(acc1).setMintCap(remoteOFT.address, convertToUnit(10, 18)); expect(await remoteEndpoint.inboundNonce(localChainId, localPath)).lessThanOrEqual(0); From 85a718c299a1e65034b52c9494bc8479adfb3a87 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:03:18 +0530 Subject: [PATCH 02/28] fix: BRI-06 --- contracts/Bridge/XVSProxyOFTSrc.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/Bridge/XVSProxyOFTSrc.sol b/contracts/Bridge/XVSProxyOFTSrc.sol index eef4e88..f7ae813 100644 --- a/contracts/Bridge/XVSProxyOFTSrc.sol +++ b/contracts/Bridge/XVSProxyOFTSrc.sol @@ -42,7 +42,10 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { * @param amount_ The amount of withdrawal */ function fallbackWithdraw(address to_, uint256 amount_) external onlyOwner { + require(outboundAmount >= amount_, "Withdraw amount should be less than outbound amount"); + unchecked { outboundAmount -= amount_; + } _transferFrom(address(this), to_, amount_); emit FallbackWithdraw(to_, amount_); } From 8ce11e679649956014e700aac2e7b622e1886970 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:15:10 +0530 Subject: [PATCH 03/28] fix: BRI-02 --- contracts/Bridge/BaseXVSProxyOFT.sol | 8 ++++---- contracts/Bridge/XVSBridgeAdmin.sol | 4 ++-- contracts/Bridge/XVSProxyOFTDest.sol | 2 +- contracts/Bridge/XVSProxyOFTSrc.sol | 6 +++--- contracts/Bridge/token/TokenController.sol | 6 +++--- contracts/Bridge/token/XVS.sol | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 730675e..96c1abd 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -61,12 +61,12 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { */ mapping(uint16 => uint256) public chainIdToLast24HourReceiveWindowStart; /** - * @notice Address on which cap check and bound limit is not appicable. + * @notice Address on which cap check and bound limit is not applicable. */ mapping(address => bool) public whitelist; /** - * @notice Emmited when address is added to whitelist. + * @notice Emitted when address is added to whitelist. */ event SetWhitelist(address indexed addr, bool isWhitelist); /** @@ -100,7 +100,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { /** * @param tokenAddress_ Address of the inner token. - * @param sharedDecimals_ No of shared decimals. + * @param sharedDecimals_ Number of shared decimals. * @param lzEndpoint_ Address of the layer zero endpoint contract. * @param oracle_ Address of the price oracle. * @custom:error ZeroAddressNotAllowed is thrown when token contract address is zero. @@ -203,7 +203,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { /** * @notice Sets the whitelist address to skip checks on transaction limit. - * @param user_ Adress to be add in whitelist. + * @param user_ Address to be add in whitelist. * @param val_ Boolean to be set (true for user_ address is whitelisted). * @custom:access Only owner. * @custom:event Emits setWhitelist. diff --git a/contracts/Bridge/XVSBridgeAdmin.sol b/contracts/Bridge/XVSBridgeAdmin.sol index fb7cba0..1566a8f 100644 --- a/contracts/Bridge/XVSBridgeAdmin.sol +++ b/contracts/Bridge/XVSBridgeAdmin.sol @@ -66,7 +66,7 @@ contract XVSBridgeAdmin is AccessControlledV8 { } /** - * @notice A registry of functions that are allowed to be executed from proposals + * @notice A setter for the registry of functions that are allowed to be executed from proposals. * @param signatures_ Function signature to be added or removed. * @param active_ bool value, should be true to add function. */ @@ -87,7 +87,7 @@ contract XVSBridgeAdmin is AccessControlledV8 { } /** - * @notice This function transfer the ownership of the bridge from this contract to new owner. + * @notice This function transfers the ownership of the bridge from this contract to new owner. * @param newOwner_ New owner of the XVS Bridge. * @custom:access Controlled by AccessControlManager. */ diff --git a/contracts/Bridge/XVSProxyOFTDest.sol b/contracts/Bridge/XVSProxyOFTDest.sol index 16ec43b..fda4f51 100644 --- a/contracts/Bridge/XVSProxyOFTDest.sol +++ b/contracts/Bridge/XVSProxyOFTDest.sol @@ -14,7 +14,7 @@ import { BaseXVSProxyOFT } from "./BaseXVSProxyOFT.sol"; contract XVSProxyOFTDest is BaseXVSProxyOFT { /** - * @notice Emits when stored message dropped without successfull retrying. + * @notice Emits when stored message dropped without successful retrying. */ event DropFailedMessage(uint16 srcChainId, bytes indexed srcAddress, uint64 nonce); diff --git a/contracts/Bridge/XVSProxyOFTSrc.sol b/contracts/Bridge/XVSProxyOFTSrc.sol index f7ae813..5144e23 100644 --- a/contracts/Bridge/XVSProxyOFTSrc.sol +++ b/contracts/Bridge/XVSProxyOFTSrc.sol @@ -16,7 +16,7 @@ import { BaseXVSProxyOFT } from "./BaseXVSProxyOFT.sol"; contract XVSProxyOFTSrc is BaseXVSProxyOFT { using SafeERC20 for IERC20; /** - * @notice total amount is transferred from this chain to other chains. + * @notice Total amount that is transferred from this chain to other chains. */ uint256 public outboundAmount; @@ -25,7 +25,7 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { */ event FallbackWithdraw(address indexed to, uint256 amount); /** - * @notice Emits when stored message dropped without successfull retrying. + * @notice Emits when stored message dropped without successful retrying. */ event DropFailedMessage(uint16 srcChainId, bytes indexed srcAddress, uint64 nonce); @@ -44,7 +44,7 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { function fallbackWithdraw(address to_, uint256 amount_) external onlyOwner { require(outboundAmount >= amount_, "Withdraw amount should be less than outbound amount"); unchecked { - outboundAmount -= amount_; + outboundAmount -= amount_; } _transferFrom(address(this), to_, amount_); emit FallbackWithdraw(to_, amount_); diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index e66ed65..a6128ef 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -27,7 +27,7 @@ contract TokenController is Ownable, Pausable { */ mapping(address => uint256) public minterToCap; /** - * @notice A Mapping used to keep track of the amount i.e already m inted by minter. + * @notice A Mapping used to keep track of the amount i.e already minted by minter. */ mapping(address => uint256) public minterToMintedAmount; @@ -106,7 +106,7 @@ contract TokenController is Ownable, Pausable { } /** - * @notice Sets the minitng cap for minter. + * @notice Sets the minting cap for minter. * @param minter_ Minter address. * @param amount_ Cap for the minter. * @custom:access Controlled by AccessControlManager. @@ -165,7 +165,7 @@ contract TokenController is Ownable, Pausable { } /** - * @dev This is post hook of burn function, increases minitng limit of the minter. + * @dev This is post hook of burn function, increases minting limit of the minter. * @param from_ Minter address. * @param amount_ Amount burned. */ diff --git a/contracts/Bridge/token/XVS.sol b/contracts/Bridge/token/XVS.sol index cb5c932..a42d166 100644 --- a/contracts/Bridge/token/XVS.sol +++ b/contracts/Bridge/token/XVS.sol @@ -18,12 +18,12 @@ contract XVS is ERC20, TokenController { /** * @notice Creates `amount_` tokens and assigns them to `account_`, increasing * the total supply. Checks access and eligibility. - * @param account_ Address to which tokens be assigned. + * @param account_ Address to which tokens are assigned. * @param amount_ Amount of tokens to be assigned. * @custom:access Controlled by AccessControlManager. * @custom:event Emits MintLimitDecreased with new available limit. - * @custom:error MintNotAllowed is thrown when minting is not allowed to from_ address. - * @custom:error MintLimitExceed is thrown when minting amount exceed the maximum cap. + * @custom:error MintNotAllowed is thrown when minting is not allowed to to_ address. + * @custom:error MintLimitExceed is thrown when minting amount exceeds the maximum cap. */ function mint(address account_, uint256 amount_) external whenNotPaused { _ensureAllowed("mint(address,uint256)"); From 5293d3e5c1d33e0aa41500431e1f529adf612902 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:44:32 +0530 Subject: [PATCH 04/28] fix: BXV-01 --- contracts/Bridge/BaseXVSProxyOFT.sol | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 96c1abd..bea39e4 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -124,7 +124,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { require(sharedDecimals_ <= decimals, "ProxyOFT: sharedDecimals must be <= decimals"); ld2sdRate = 10 ** (decimals - sharedDecimals_); - + ensureNonzeroAddress(oracle_); emit InnerTokenAdded(tokenAddress_); @@ -238,6 +238,23 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { emit TrustedRemoteRemoved(remoteChainId_); } + function retryMessage( + uint16 _srcChainId, + bytes calldata _srcAddress, + uint64 _nonce, + bytes calldata _payload + ) public payable override { + bytes memory trustedRemote = trustedRemoteLookup[_srcChainId]; + // it will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote. + require( + _srcAddress.length == trustedRemote.length && + trustedRemote.length > 0 && + keccak256(_srcAddress) == keccak256(trustedRemote), + "LzApp: invalid source sending contract" + ); + super.retryMessage(_srcChainId, _srcAddress, _nonce, _payload); + } + /** * @notice Empty implementation of renounce ownership to avoid any mishappening. */ @@ -341,23 +358,6 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { return innerToken.balanceOf(to_) - before; } - function _nonblockingLzReceive( - uint16 _srcChainId, - bytes memory _srcAddress, - uint64 _nonce, - bytes memory _payload - ) internal override { - bytes memory trustedRemote = trustedRemoteLookup[_srcChainId]; - // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote. - require( - _srcAddress.length == trustedRemote.length && - trustedRemote.length > 0 && - keccak256(_srcAddress) == keccak256(trustedRemote), - "LzApp: invalid source sending contract" - ); - super._nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload); - } - function _ld2sdRate() internal view override returns (uint256) { return ld2sdRate; } From 7c2193bd7e7d9de4dff59982b98050844a9b3e51 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:44:56 +0530 Subject: [PATCH 05/28] fix: BXV-03 --- contracts/Bridge/BaseXVSProxyOFT.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index bea39e4..588b2bc 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -115,6 +115,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { ) BaseOFTV2(sharedDecimals_, lzEndpoint_) { ensureNonzeroAddress(tokenAddress_); ensureNonzeroAddress(lzEndpoint_); + ensureNonzeroAddress(oracle_); innerToken = IERC20(tokenAddress_); @@ -125,7 +126,6 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { require(sharedDecimals_ <= decimals, "ProxyOFT: sharedDecimals must be <= decimals"); ld2sdRate = 10 ** (decimals - sharedDecimals_); - ensureNonzeroAddress(oracle_); emit InnerTokenAdded(tokenAddress_); emit OracleChanged(address(0), oracle_); From b017f579abd2c5709075f581fe1168e4ed9e3d2e Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:46:19 +0530 Subject: [PATCH 06/28] fix: TCB-04 --- contracts/Bridge/token/TokenController.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index a6128ef..bb33bd9 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -21,7 +21,7 @@ contract TokenController is Ownable, Pausable { /** * @notice A Mapping used to keep track of the blacklist status of addresses. */ - mapping(address => bool) public _blacklist; + mapping(address => bool) internal _blacklist; /** * @notice A mapping is used to keep track of the maximum amount a minter is permitted to mint. */ From 2ddf4c02544c010ca8d669ae02c71d8ea976f76e Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:48:14 +0530 Subject: [PATCH 07/28] fix: TCB-05 --- contracts/Bridge/token/TokenController.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index bb33bd9..6fa7445 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -160,7 +160,10 @@ contract TokenController is Ownable, Pausable { revert MintLimitExceed(); } minterToMintedAmount[from_] = totalMintedNew; - uint256 availableLimit = mintingCap - totalMintedNew; + uint256 availableLimit; + unchecked { + availableLimit = mintingCap - totalMintedNew; + } emit MintLimitDecreased(from_, availableLimit); } From 6785b84e085eaf455e35f66a6d04f79570279e5f Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:50:26 +0530 Subject: [PATCH 08/28] fix: XVS-01 --- contracts/Bridge/BaseXVSProxyOFT.sol | 1 - contracts/Bridge/XVSBridgeAdmin.sol | 3 --- 2 files changed, 4 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 588b2bc..8f1f7fa 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -125,7 +125,6 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { require(sharedDecimals_ <= decimals, "ProxyOFT: sharedDecimals must be <= decimals"); ld2sdRate = 10 ** (decimals - sharedDecimals_); - emit InnerTokenAdded(tokenAddress_); emit OracleChanged(address(0), oracle_); diff --git a/contracts/Bridge/XVSBridgeAdmin.sol b/contracts/Bridge/XVSBridgeAdmin.sol index 1566a8f..c409161 100644 --- a/contracts/Bridge/XVSBridgeAdmin.sol +++ b/contracts/Bridge/XVSBridgeAdmin.sol @@ -33,10 +33,8 @@ contract XVSBridgeAdmin is AccessControlledV8 { /** * @param accessControlManager_ Address of access control manager contract. - * @custom:error ZeroAddressNotAllowed is thrown when accessControlManager contract address is zero. */ function initialize(address accessControlManager_) external initializer { - ensureNonzeroAddress(accessControlManager_); __AccessControlled_init(accessControlManager_); } @@ -93,7 +91,6 @@ contract XVSBridgeAdmin is AccessControlledV8 { */ function transferBridgeOwnership(address newOwner_) external { _checkAccessAllowed("transferBridgeOwnership(address)"); - ensureNonzeroAddress(newOwner_); XVSBridge.transferOwnership(newOwner_); } From 6bacbf7b9a265afeb99188bfe3c3d864ae06c145 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:53:18 +0530 Subject: [PATCH 09/28] fix: XVS-02 --- contracts/Bridge/XVSBridgeAdmin.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/Bridge/XVSBridgeAdmin.sol b/contracts/Bridge/XVSBridgeAdmin.sol index c409161..66b78f1 100644 --- a/contracts/Bridge/XVSBridgeAdmin.sol +++ b/contracts/Bridge/XVSBridgeAdmin.sol @@ -71,7 +71,7 @@ contract XVSBridgeAdmin is AccessControlledV8 { function upsertSignature(string[] calldata signatures_, bool[] calldata active_) external onlyOwner { uint256 signatureLength = signatures_.length; require(signatureLength == active_.length, "Input arrays must have the same length"); - for (uint256 i; i < signatureLength; i++) { + for (uint256 i; i < signatureLength; ) { bytes4 sigHash = bytes4(keccak256(bytes(signatures_[i]))); bytes memory signature = bytes(functionRegistry[sigHash]); if (active_[i] && signature.length == 0) { @@ -81,6 +81,9 @@ contract XVSBridgeAdmin is AccessControlledV8 { delete functionRegistry[sigHash]; emit FunctionRegistryChanged(signatures_[i], false); } + unchecked { + i++; + } } } From 52ff1120d828b50ff110acb2df939abe28a3dd28 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 14:18:22 +0530 Subject: [PATCH 10/28] fix: BRI-07 --- contracts/Bridge/token/TokenController.sol | 4 +++ contracts/Bridge/token/XVS.sol | 13 ++++++++++ test/proxyOFT.ts | 29 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index 6fa7445..c7fa63d 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -60,6 +60,10 @@ contract TokenController is Ownable, Pausable { * @notice This error is used to indicate that minting is not allowed for the specified addresses. */ error MintNotAllowed(address from, address to); + /** + * @notice This error is used to indicate that transfers are not allowed for the to_ address. + */ + error TransferNotAllowed(address to); /** * @notice This error is used to indicate that sender is not allowed to perform this action. */ diff --git a/contracts/Bridge/token/XVS.sol b/contracts/Bridge/token/XVS.sol index a42d166..f259e27 100644 --- a/contracts/Bridge/token/XVS.sol +++ b/contracts/Bridge/token/XVS.sol @@ -44,4 +44,17 @@ contract XVS is ERC20, TokenController { _burn(account_, amount_); _increaseMintLimit(msg.sender, amount_); } + + /** + * @notice Moves `amount` of tokens from `from` to `to`. + * @param from_ Address of account from which tokens are to be transferred. + * @param to_ Address of the account to which tokens are to be transferred. + * @param amount_ The amount of tokens to be transferred. + */ + function _transfer(address from_, address to_, uint256 amount_) internal override { + if (_blacklist[to_]) { + revert TransferNotAllowed(to_); + } + super._transfer(from_, to_, amount_); + } } diff --git a/test/proxyOFT.ts b/test/proxyOFT.ts index 20fccc9..9aa53a1 100644 --- a/test/proxyOFT.ts +++ b/test/proxyOFT.ts @@ -508,6 +508,35 @@ describe("Proxy OFTV2: ", function () { accessControlManager.isAllowedToCall.returns(true); }); + it("Reverts transfer of remote token to blacklist address", async function () { + const amount = ethers.utils.parseEther("10", 18); + await localToken.connect(acc2).faucet(amount); + await localToken.connect(acc2).approve(localOFT.address, amount); + + const acc3AddressBytes32 = ethers.utils.defaultAbiCoder.encode(["address"], [acc3.address]); + const nativeFee = ( + await localOFT.estimateSendFee(remoteChainId, acc3AddressBytes32, amount, false, defaultAdapterParams) + ).nativeFee; + + await expect( + localOFT + .connect(acc2) + .sendFrom( + acc2.address, + remoteChainId, + acc3AddressBytes32, + amount, + [acc2.address, ethers.constants.AddressZero, defaultAdapterParams], + { value: nativeFee }, + ), + ).to.emit(remoteOFT, "ReceiveFromChain"); + await remoteToken.updateBlacklist(acc3.address, true); + await expect(remoteToken.connect(acc2).transfer(acc3.address, amount)).to.be.revertedWithCustomError( + remoteToken, + "TransferNotAllowed", + ); + }); + it("Reverts if try to set cap less than already minted tokens", async function () { const initialAmount = ethers.utils.parseEther("20", 18); await localToken.connect(acc2).faucet(initialAmount); From f57a9ab2d4688ba7269abcaaeced316aad1ccbc4 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:11:39 +0530 Subject: [PATCH 11/28] fix: XVB-02 --- contracts/Bridge/token/XVS.sol | 2 +- test/bridgeAdmin.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Bridge/token/XVS.sol b/contracts/Bridge/token/XVS.sol index f259e27..b36f32e 100644 --- a/contracts/Bridge/token/XVS.sol +++ b/contracts/Bridge/token/XVS.sol @@ -51,7 +51,7 @@ contract XVS is ERC20, TokenController { * @param to_ Address of the account to which tokens are to be transferred. * @param amount_ The amount of tokens to be transferred. */ - function _transfer(address from_, address to_, uint256 amount_) internal override { + function _transfer(address from_, address to_, uint256 amount_) internal override whenNotPaused { if (_blacklist[to_]) { revert TransferNotAllowed(to_); } diff --git a/test/bridgeAdmin.ts b/test/bridgeAdmin.ts index e006566..47c5c73 100644 --- a/test/bridgeAdmin.ts +++ b/test/bridgeAdmin.ts @@ -219,7 +219,7 @@ describe("Bridge Admin: ", function () { ).to.be.revertedWith("Function not found"); }); - it("Success on trnafer bridge owner", async function () { + it("Success on transfer bridge owner", async function () { await bridgeAdmin.connect(acc2).transferBridgeOwnership(acc2.address); expect(await remoteOFT.owner()).equals(acc2.address); }); From 7c63f14cb6ebae8f97ddbba719be6d196c59593f Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:22:08 +0530 Subject: [PATCH 12/28] fix: BRI-03 --- contracts/Bridge/BaseXVSProxyOFT.sol | 28 ++++++++++++++++++++++ contracts/Bridge/XVSBridgeAdmin.sol | 21 +++++++++++++--- contracts/Bridge/XVSProxyOFTDest.sol | 20 +++++++++++++++- contracts/Bridge/XVSProxyOFTSrc.sol | 25 +++++++++++++++++-- contracts/Bridge/token/TokenController.sol | 10 +++++++- 5 files changed, 97 insertions(+), 7 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 8f1f7fa..18100ee 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -106,6 +106,8 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { * @custom:error ZeroAddressNotAllowed is thrown when token contract address is zero. * @custom:error ZeroAddressNotAllowed is thrown when lzEndpoint contract address is zero. * @custom:error ZeroAddressNotAllowed is thrown when oracle contract address is zero. + * @custom:event Emits InnerTokenAdded with token address. + * @custom:event Emits OracleChanged with zero address and oracle address. */ constructor( address tokenAddress_, @@ -231,6 +233,8 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { /** * @notice Remove trusted remote from storage. * @param remoteChainId_ The chain's id corresponds to setting the trusted remote to empty. + * @custom:access Only owner. + * @custom:event Emits TrustedRemoteRemoved once chain id is removed from trusted remote. */ function removeTrustedRemote(uint16 remoteChainId_) external onlyOwner { delete trustedRemoteLookup[remoteChainId_]; @@ -261,11 +265,18 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { /** * @notice Return's the address of the inner token of this bridge. + * @return Address of the inner token of this bridge. */ function token() public view override returns (address) { return address(innerToken); } + /** + * @notice Checks if the sender is eligible to send tokens + * @param from_ Sender's address sending tokens + * @param dstChainId_ Chain id on which tokens should be sent + * @param amount_ Amount of tokens to be sent + */ function _isEligibleToSend(address from_, uint16 dstChainId_, uint256 amount_) internal { // Check if the sender's address is whitelisted bool isWhiteListedUser = whitelist[from_]; @@ -304,6 +315,12 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { chainIdToLast24HourTransferred[dstChainId_] = transferredInWindow; } + /** + * @notice Checks if receiver is able to receive tokens + * @param toAddress_ Receiver address + * @param srcChainId_ Source chain id from which token is send + * @param receivedAmount_ Amount of tokens received + */ function _isEligibleToReceive(address toAddress_, uint16 srcChainId_, uint256 receivedAmount_) internal { // Check if the recipient's address is whitelisted bool isWhiteListedUser = whitelist[toAddress_]; @@ -343,6 +360,13 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { chainIdToLast24HourReceived[srcChainId_] = receivedInWindow; } + /** + * @notice Transfer tokens from sender to receiver account. + * @param from_ Address from which token has to be transferred(Sender). + * @param to_ Address on which token will be tranferred(Receiver). + * @param amount_ Amount of token to be transferred. + * @return Actual balance difference. + */ function _transferFrom( address from_, address to_, @@ -357,6 +381,10 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { return innerToken.balanceOf(to_) - before; } + /** + * @notice Returns Conversion rate factor from large decimals to shared decimals. + * @return Conversion rate factor. + */ function _ld2sdRate() internal view override returns (uint256) { return ld2sdRate; } diff --git a/contracts/Bridge/XVSBridgeAdmin.sol b/contracts/Bridge/XVSBridgeAdmin.sol index 66b78f1..a0b5b0f 100644 --- a/contracts/Bridge/XVSBridgeAdmin.sol +++ b/contracts/Bridge/XVSBridgeAdmin.sol @@ -21,7 +21,9 @@ contract XVSBridgeAdmin is AccessControlledV8 { */ mapping(bytes4 => string) public functionRegistry; - // Event emitted when function registry updated + /** + * @notice emitted when function registry updated + */ event FunctionRegistryChanged(string signature, bool active); /// @custom:oz-upgrades-unsafe-allow constructor @@ -39,7 +41,8 @@ contract XVSBridgeAdmin is AccessControlledV8 { } /** - * @notice Invoked when called function does not exist in the contract + * @notice Invoked when called function does not exist in the contract. + * @return Response of low level call. * @custom:access Controlled by AccessControlManager. */ fallback(bytes calldata data) external returns (bytes memory) { @@ -52,8 +55,10 @@ contract XVSBridgeAdmin is AccessControlledV8 { } /** + * @notice Sets trusted remote on particular chain. * @param remoteChainId_ Chain Id of the destination chain. * @param remoteAddress_ Address of the destination bridge. + * @custom:access Controlled by AccessControlManager. * @custom:error ZeroAddressNotAllowed is thrown when remoteAddress_ contract address is zero. */ function setTrustedRemoteAddress(uint16 remoteChainId_, bytes calldata remoteAddress_) external { @@ -67,6 +72,8 @@ contract XVSBridgeAdmin is AccessControlledV8 { * @notice A setter for the registry of functions that are allowed to be executed from proposals. * @param signatures_ Function signature to be added or removed. * @param active_ bool value, should be true to add function. + * @custom:access Only owner. + * @custom:event Emits FunctionRegistryChanged if bool value of function changes. */ function upsertSignature(string[] calldata signatures_, bool[] calldata active_) external onlyOwner { uint256 signatureLength = signatures_.length; @@ -98,10 +105,11 @@ contract XVSBridgeAdmin is AccessControlledV8 { } /** - * @notice Returns bool = true if srcAddress_ is trustedRemote corresponds to chainId_. + * @notice Returns true if remote address is trustedRemote corresponds to chainId_. * @param remoteChainId_ Chain Id of the destination chain. * @param remoteAddress_ Address of the destination bridge. * @custom:error ZeroAddressNotAllowed is thrown when remoteAddress_ contract address is zero. + * @return Bool indicating whether the remote chain is trusted or not. */ function isTrustedRemote(uint16 remoteChainId_, bytes calldata remoteAddress_) external returns (bool) { require(remoteChainId_ != 0, "ChainId must not be zero"); @@ -116,11 +124,18 @@ contract XVSBridgeAdmin is AccessControlledV8 { /** * @dev Returns function name string associated with function signature. + * @param signature_ Four bytes of function signature. + * @return Function signature corresponding to its hash. */ function _getFunctionName(bytes4 signature_) internal view returns (string memory) { return functionRegistry[signature_]; } + /** + * @notice Converts given bytes into address. + * @param b Bytes to be converted into address. + * @return Converted address of given bytes. + */ function bytesToAddress(bytes calldata b) private pure returns (address) { return address(uint160(bytes20(b))); } diff --git a/contracts/Bridge/XVSProxyOFTDest.sol b/contracts/Bridge/XVSProxyOFTDest.sol index fda4f51..5f1aa3e 100644 --- a/contracts/Bridge/XVSProxyOFTDest.sol +++ b/contracts/Bridge/XVSProxyOFTDest.sol @@ -25,10 +25,13 @@ contract XVSProxyOFTDest is BaseXVSProxyOFT { address oracle_ ) BaseXVSProxyOFT(tokenAddress_, sharedDecimals_, lzEndpoint_, oracle_) {} - /** @notice Clear failed messages from the storage. + /** + * @notice Clear failed messages from the storage. * @param srcChainId_ Chain id of source * @param srcAddress_ Address of source followed by current bridge address * @param nonce_ Nonce_ of the transaction + * @custom:access Only owner + * @custom:event Emits DropFailedMessage on clearance of failed message. */ function dropFailedMessage(uint16 srcChainId_, bytes memory srcAddress_, uint64 nonce_) external onlyOwner { failedMessages[srcChainId_][srcAddress_][nonce_] = bytes32(0); @@ -37,11 +40,19 @@ contract XVSProxyOFTDest is BaseXVSProxyOFT { /** * @notice Returns the total circulating supply of the token on the destination chain i.e (total supply). + * @return total circulating supply of the token on the destination chain. */ function circulatingSupply() public view override returns (uint256) { return innerToken.totalSupply(); } + /** + * @notice Debit tokens from the given address + * @param from_ Address from which tokens to be debited + * @param dstChainId_ Destination chain id + * @param amount_ Amount of tokens to be debited + * @return Actual amount debited + */ function _debitFrom( address from_, uint16 dstChainId_, @@ -54,6 +65,13 @@ contract XVSProxyOFTDest is BaseXVSProxyOFT { return amount_; } + /** + * @notice Credit tokens in the given account + * @param srcChainId_ Source chain id + * @param toAddress_ Address on which token will be credited + * @param amount_ Amount of tokens to be credited + * @return Actual amount credited + */ function _creditTo( uint16 srcChainId_, address toAddress_, diff --git a/contracts/Bridge/XVSProxyOFTSrc.sol b/contracts/Bridge/XVSProxyOFTSrc.sol index 5144e23..cce5101 100644 --- a/contracts/Bridge/XVSProxyOFTSrc.sol +++ b/contracts/Bridge/XVSProxyOFTSrc.sol @@ -36,10 +36,13 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { address oracle_ ) BaseXVSProxyOFT(tokenAddress_, sharedDecimals_, lzEndpoint_, oracle_) {} - /** @notice Only call it when there is no way to recover the failed message. + /** + * @notice Only call it when there is no way to recover the failed message. * `dropFailedMessage` must be called first if transaction is from remote->local chain to avoid double spending. * @param to_ The address to withdraw to * @param amount_ The amount of withdrawal + * @custom:access Only owner. + * @custom:event Emits FallbackWithdraw, once done with transfer. */ function fallbackWithdraw(address to_, uint256 amount_) external onlyOwner { require(outboundAmount >= amount_, "Withdraw amount should be less than outbound amount"); @@ -50,10 +53,13 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { emit FallbackWithdraw(to_, amount_); } - /** @notice Clear failed messages from the storage. + /** + * @notice Clear failed messages from the storage. * @param srcChainId_ Chain id of source * @param srcAddress_ Address of source followed by current bridge address * @param nonce_ Nonce_ of the transaction + * @custom:access Only owner. + * @custom:event Emits DropFailedMessage on clearance of failed message. */ function dropFailedMessage(uint16 srcChainId_, bytes memory srcAddress_, uint64 nonce_) external onlyOwner { failedMessages[srcChainId_][srcAddress_][nonce_] = bytes32(0); @@ -62,11 +68,19 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { /** * @notice Returns the total circulating supply of the token on the source chain i.e (total supply - locked in this contract). + * @return Returns total supply of the token. */ function circulatingSupply() public view override returns (uint256) { return innerToken.totalSupply() - outboundAmount; } + /** + * @notice Debit tokens from the given address + * @param from_ Address from which tokens to be debited + * @param dstChainId_ Destination chain id + * @param amount_ Amount of tokens to be debited + * @return Actual amount debited + */ function _debitFrom( address from_, uint16 dstChainId_, @@ -81,6 +95,13 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { return amount; } + /** + * @notice Credit tokens in the given account + * @param srcChainId_ Source chain id + * @param toAddress_ Address on which token will be credited + * @param amount_ Amount of tokens to be credited + * @return Actual amount credited + */ function _creditTo( uint16 srcChainId_, address toAddress_, diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index c7fa63d..1481f84 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -151,6 +151,9 @@ contract TokenController is Ownable, Pausable { * @param from_ Minter address. * @param to_ Receiver address. * @param amount_ Amount to be mint. + * @custom:error MintNotAllowed is thrown when user is in blacklist + * @custom:error MintLimitExceed is thrown when minting limit exceeds the cap. + * @custom:event Emits MintLimitDecreased with minter address and available limits. */ function _isEligibleToMint(address from_, address to_, uint256 amount_) internal { if (_blacklist[to_]) { @@ -175,6 +178,7 @@ contract TokenController is Ownable, Pausable { * @dev This is post hook of burn function, increases minting limit of the minter. * @param from_ Minter address. * @param amount_ Amount burned. + * @custom:event Emits MintLimitIncreased with minter address and availabe limit. */ function _increaseMintLimit(address from_, uint256 amount_) internal { uint256 totalMintedOld = minterToMintedAmount[from_]; @@ -184,7 +188,11 @@ contract TokenController is Ownable, Pausable { emit MintLimitIncreased(from_, availableLimit); } - /// @dev Checks the caller is allowed to call the specified fuction + /** + * @dev Checks the caller is allowed to call the specified fuction. + * @param functionSig_ Function signatureon which access is to be checked. + * @custom:error Unauthorized, thrown when unauthorised user try to access function. + */ function _ensureAllowed(string memory functionSig_) internal view { if (!IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig_)) { revert Unauthorized(); From 06c6009e01411182d738b2249cbbb06019926b54 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:26:37 +0530 Subject: [PATCH 13/28] fix: XVO-02 --- contracts/Bridge/BaseXVSProxyOFT.sol | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 18100ee..ddc0509 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -98,6 +98,16 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { */ event InnerTokenAdded(address indexed innerToken); + /** + *@notice Emitted on sweep token success + */ + event SweepToken(address indexed token, address indexed to, uint256 sweepAmount); + + /** + *@notice Error thrown when this contract balance is less than sweep amount + */ + error InsufficientBalance(uint256 sweepAmount, uint256 balance); + /** * @param tokenAddress_ Address of the inner token. * @param sharedDecimals_ Number of shared decimals. @@ -230,6 +240,26 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { _unpause(); } + /** + * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user + * @param token_ The address of the ERC-20 token to sweep + * @param to_ The address of the recipient + * @param amount_ The amount of tokens needs to transfer + * @custom:event Emits SweepToken event + * @custom:error Throw InsufficientBalance if amount_ is greater than the available balance of the token in the contract + * @custom:access Only Owner + */ + function sweepToken(IERC20 token_, address to_, uint256 amount_) external onlyOwner { + uint256 balance = token_.balanceOf(address(this)); + if (amount_ > balance) { + revert InsufficientBalance(amount_, balance); + } + + emit SweepToken(address(token_), to_, amount_); + + token_.safeTransfer(to_, amount_); + } + /** * @notice Remove trusted remote from storage. * @param remoteChainId_ The chain's id corresponds to setting the trusted remote to empty. From acc9dfbfba60da0c615b8145a772d1d1013b13fb Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:34:55 +0530 Subject: [PATCH 14/28] feat: add isEligibleToSend function --- contracts/Bridge/BaseXVSProxyOFT.sol | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 730675e..3181280 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -238,6 +238,60 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { emit TrustedRemoteRemoved(remoteChainId_); } + /** + * @notice View function similar to _isEligibleToSend internal function. + * @param from_ Address on which eligibility has to be checked. + * @param dstChainId_ Destination chain id. + * @param amount_ Amount of tokens. + * @return isEligibleToSend_ boolean indicating eligibility to send tokens. + * @return maxSingleTransactionLimit Maximum single transaction limit corresponding to chain id. + * @return maxDailyLimit Maximum daily limit to send tokens. + * @return amountInUsd Amount in USD. + * @return transferredInWindow Number of tokens transferred in 24 hour window. + * @return last24HourWindowStart Timestamp marking the start of the last 24-hour window. + * @return isWhiteListedUser Boolean indicating whether the sender is whitelisted. + */ + function isEligibleToSend( + address from_, + uint16 dstChainId_, + uint256 amount_ + ) + external + view + returns ( + bool isEligibleToSend_, + uint256 maxSingleTransactionLimit, + uint256 maxDailyLimit, + uint256 amountInUsd, + uint256 transferredInWindow, + uint256 last24HourWindowStart, + bool isWhiteListedUser + ) + { + // Check if the sender's address is whitelisted + isWhiteListedUser = whitelist[from_]; + + // Calculate the amount in USD using the oracle price + Exp memory oraclePrice = Exp({ mantissa: oracle.getPrice(token()) }); + amountInUsd = mul_ScalarTruncate(oraclePrice, amount_); + + // Load values for the 24-hour window checks + last24HourWindowStart = chainIdToLast24HourWindowStart[dstChainId_]; + transferredInWindow = chainIdToLast24HourTransferred[dstChainId_]; + maxSingleTransactionLimit = chainIdToMaxSingleTransactionLimit[dstChainId_]; + maxDailyLimit = chainIdToMaxDailyLimit[dstChainId_]; + + // Check if the time window has changed (more than 24 hours have passed) + if (block.timestamp - last24HourWindowStart > 1 days) { + transferredInWindow = amountInUsd; + } else { + transferredInWindow += amountInUsd; + } + isEligibleToSend_ = (whitelist[from_] || + ((amountInUsd <= maxSingleTransactionLimit) && + (transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_]))); + } + /** * @notice Empty implementation of renounce ownership to avoid any mishappening. */ From 0060366ed3036534119b1ce3ab93d5a26d150350 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 14 Dec 2023 20:18:50 +0530 Subject: [PATCH 15/28] refactor: comments and add test --- contracts/Bridge/BaseXVSProxyOFT.sol | 55 +++++++++++------- test/proxyOFT.ts | 84 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 3181280..5b9cf9c 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -239,17 +239,19 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { } /** - * @notice View function similar to _isEligibleToSend internal function. - * @param from_ Address on which eligibility has to be checked. - * @param dstChainId_ Destination chain id. - * @param amount_ Amount of tokens. - * @return isEligibleToSend_ boolean indicating eligibility to send tokens. - * @return maxSingleTransactionLimit Maximum single transaction limit corresponding to chain id. - * @return maxDailyLimit Maximum daily limit to send tokens. - * @return amountInUsd Amount in USD. - * @return transferredInWindow Number of tokens transferred in 24 hour window. - * @return last24HourWindowStart Timestamp marking the start of the last 24-hour window. - * @return isWhiteListedUser Boolean indicating whether the sender is whitelisted. + * @notice Checks the eligibility of a sender to initiate a cross-chain token transfer. + * @dev This external view function assesses whether the specified sender is eligible to transfer the given amount + * to the specified destination chain. It considers factors such as whitelisting, transaction limits, and a 24-hour window. + * @param from_ The sender's address initiating the transfer. + * @param dstChainId_ Indicates destination chain. + * @param amount_ The quantity of tokens to be transferred. + * @return eligibleToSend A boolean indicating whether the sender is eligible to transfer the tokens. + * @return maxSingleTransactionLimit The maximum limit for a single transaction. + * @return maxDailyLimit The maximum daily limit for transactions. + * @return amountInUsd The equivalent amount in USD based on the oracle price. + * @return transferredInWindow The total amount transferred in the current 24-hour window. + * @return last24HourWindowStart The timestamp when the current 24-hour window started. + * @return isWhiteListedUser A boolean indicating whether the sender is whitelisted. */ function isEligibleToSend( address from_, @@ -259,7 +261,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { external view returns ( - bool isEligibleToSend_, + bool eligibleToSend, uint256 maxSingleTransactionLimit, uint256 maxDailyLimit, uint256 amountInUsd, @@ -276,20 +278,33 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { amountInUsd = mul_ScalarTruncate(oraclePrice, amount_); // Load values for the 24-hour window checks + uint256 currentBlockTimestamp = block.timestamp; last24HourWindowStart = chainIdToLast24HourWindowStart[dstChainId_]; transferredInWindow = chainIdToLast24HourTransferred[dstChainId_]; maxSingleTransactionLimit = chainIdToMaxSingleTransactionLimit[dstChainId_]; maxDailyLimit = chainIdToMaxDailyLimit[dstChainId_]; - - // Check if the time window has changed (more than 24 hours have passed) - if (block.timestamp - last24HourWindowStart > 1 days) { - transferredInWindow = amountInUsd; + if (!isWhiteListedUser) { + // Check if the time window has changed (more than 24 hours have passed) + if (currentBlockTimestamp - last24HourWindowStart > 1 days) { + transferredInWindow = amountInUsd; + last24HourWindowStart = currentBlockTimestamp; + } else { + transferredInWindow += amountInUsd; + } + eligibleToSend = (whitelist[from_] || + ((amountInUsd <= maxSingleTransactionLimit) && + (transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_]))); } else { - transferredInWindow += amountInUsd; + return ( + true, + maxSingleTransactionLimit, + maxDailyLimit, + amountInUsd, + transferredInWindow, + last24HourWindowStart, + isWhiteListedUser + ); } - isEligibleToSend_ = (whitelist[from_] || - ((amountInUsd <= maxSingleTransactionLimit) && - (transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_]))); } /** diff --git a/test/proxyOFT.ts b/test/proxyOFT.ts index c9752c0..03bfe78 100644 --- a/test/proxyOFT.ts +++ b/test/proxyOFT.ts @@ -718,4 +718,88 @@ describe("Proxy OFTV2: ", function () { }); expect(await localOFT.trustedRemoteLookup(remoteChainId)).equals("0x"); }); + it("Returns correct limits and eligibility of user initially", async function () { + const amount = ethers.utils.parseEther("10", 18); + const { + eligibleToSend, + maxSingleTransactionLimit, + maxDailyLimit, + amountInUsd, + transferredInWindow, + last24HourWindowStart, + isWhiteListedUser, + } = await localOFT.connect(acc1).isEligibleToSend(acc2.address, remoteChainId, amount); + expect(eligibleToSend).to.be.true; + expect(await localOFT.chainIdToMaxSingleTransactionLimit(remoteChainId)).to.be.equals(maxSingleTransactionLimit); + expect(await localOFT.chainIdToMaxDailyLimit(remoteChainId)).to.be.equals(maxDailyLimit); + const oraclePrice = await oracle.getPrice(await localOFT.token()); + const expectedAmount = BigInt((oraclePrice * amount) / 1e18); + expect(expectedAmount).to.be.equals(amountInUsd); + expect((await localOFT.chainIdToLast24HourTransferred(remoteChainId)).add(amountInUsd)).to.be.equals( + transferredInWindow, + ); + const currentTimestamp = (await ethers.provider.getBlock("latest")).timestamp; + expect((await localOFT.chainIdToLast24HourWindowStart(remoteChainId)).add(currentTimestamp)).to.be.equals( + last24HourWindowStart, + ); + expect(await localOFT.whitelist(acc2.address)).to.be.equals(isWhiteListedUser); + }); + + it("Returns upadted value of limits and eligibility of user", async function () { + const data = localOFT.interface.encodeFunctionData("setMaxSingleTransactionLimit", [ + remoteChainId, + singleTransactionLimit, + ]); + await acc1.sendTransaction({ + to: bridgeAdminLocal.address, + data: data, + }); + + const initialAmount = ethers.utils.parseEther("1", 18); + await localToken.connect(acc2).faucet(initialAmount); + // verify acc2 has tokens and acc3 has no tokens on remote chain + expect(await localToken.balanceOf(acc2.address)).to.be.equal(initialAmount); + expect(await remoteToken.balanceOf(acc3.address)).to.be.equal(0); + // acc2 sends tokens to acc3 on remote chain + // approve the proxy to swap your tokens + await localToken.connect(acc2).approve(localOFT.address, initialAmount); + // swaps token to remote chain + const acc3AddressBytes32 = ethers.utils.defaultAbiCoder.encode(["address"], [acc3.address]); + const nativeFee = ( + await localOFT.estimateSendFee(remoteChainId, acc3AddressBytes32, initialAmount, false, defaultAdapterParams) + ).nativeFee; + + await localOFT + .connect(acc2) + .sendFrom( + acc2.address, + remoteChainId, + acc3AddressBytes32, + initialAmount, + [acc2.address, ethers.constants.AddressZero, defaultAdapterParams], + { value: nativeFee }, + ); + + const { + eligibleToSend, + maxSingleTransactionLimit, + maxDailyLimit, + amountInUsd, + transferredInWindow, + last24HourWindowStart, + isWhiteListedUser, + } = await localOFT.connect(acc1).isEligibleToSend(acc2.address, remoteChainId, initialAmount); + + expect(eligibleToSend).to.be.true; + expect(await localOFT.chainIdToMaxSingleTransactionLimit(remoteChainId)).to.be.equals(maxSingleTransactionLimit); + expect(await localOFT.chainIdToMaxDailyLimit(remoteChainId)).to.be.equals(maxDailyLimit); + const oraclePrice = await oracle.getPrice(await localOFT.token()); + const expectedAmount = BigInt((oraclePrice * initialAmount) / 1e18); + expect(expectedAmount).to.be.equals(amountInUsd); + expect((await localOFT.chainIdToLast24HourTransferred(remoteChainId)).add(amountInUsd)).to.be.equals( + transferredInWindow, + ); + expect(await localOFT.chainIdToLast24HourWindowStart(remoteChainId)).to.be.equals(last24HourWindowStart); + expect(await localOFT.whitelist(acc2.address)).to.be.equals(isWhiteListedUser); + }); }); From b7f8aa1cb427763e08299bc7c7fbb713195bc636 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 14 Dec 2023 22:18:20 +0530 Subject: [PATCH 16/28] refactor: removed unnecessary comments --- contracts/Bridge/BaseXVSProxyOFT.sol | 2 +- test/proxyOFT.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 5b9cf9c..74c24f8 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -291,7 +291,7 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { } else { transferredInWindow += amountInUsd; } - eligibleToSend = (whitelist[from_] || + eligibleToSend = (isWhiteListedUser || ((amountInUsd <= maxSingleTransactionLimit) && (transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_]))); } else { diff --git a/test/proxyOFT.ts b/test/proxyOFT.ts index 03bfe78..16a5ebb 100644 --- a/test/proxyOFT.ts +++ b/test/proxyOFT.ts @@ -757,13 +757,9 @@ describe("Proxy OFTV2: ", function () { const initialAmount = ethers.utils.parseEther("1", 18); await localToken.connect(acc2).faucet(initialAmount); - // verify acc2 has tokens and acc3 has no tokens on remote chain expect(await localToken.balanceOf(acc2.address)).to.be.equal(initialAmount); expect(await remoteToken.balanceOf(acc3.address)).to.be.equal(0); - // acc2 sends tokens to acc3 on remote chain - // approve the proxy to swap your tokens await localToken.connect(acc2).approve(localOFT.address, initialAmount); - // swaps token to remote chain const acc3AddressBytes32 = ethers.utils.defaultAbiCoder.encode(["address"], [acc3.address]); const nativeFee = ( await localOFT.estimateSendFee(remoteChainId, acc3AddressBytes32, initialAmount, false, defaultAdapterParams) From 908e4170ccbccf80ed9b715bf14a2026720fe2e8 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Fri, 15 Dec 2023 09:12:40 +0530 Subject: [PATCH 17/28] refactor: removed dependency on isWhiteListedUser --- contracts/Bridge/BaseXVSProxyOFT.sol | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/contracts/Bridge/BaseXVSProxyOFT.sol b/contracts/Bridge/BaseXVSProxyOFT.sol index 74c24f8..e435e86 100644 --- a/contracts/Bridge/BaseXVSProxyOFT.sol +++ b/contracts/Bridge/BaseXVSProxyOFT.sol @@ -283,28 +283,14 @@ abstract contract BaseXVSProxyOFT is Pausable, ExponentialNoError, BaseOFTV2 { transferredInWindow = chainIdToLast24HourTransferred[dstChainId_]; maxSingleTransactionLimit = chainIdToMaxSingleTransactionLimit[dstChainId_]; maxDailyLimit = chainIdToMaxDailyLimit[dstChainId_]; - if (!isWhiteListedUser) { - // Check if the time window has changed (more than 24 hours have passed) - if (currentBlockTimestamp - last24HourWindowStart > 1 days) { - transferredInWindow = amountInUsd; - last24HourWindowStart = currentBlockTimestamp; - } else { - transferredInWindow += amountInUsd; - } - eligibleToSend = (isWhiteListedUser || - ((amountInUsd <= maxSingleTransactionLimit) && - (transferredInWindow <= chainIdToMaxDailyLimit[dstChainId_]))); + if (currentBlockTimestamp - last24HourWindowStart > 1 days) { + transferredInWindow = amountInUsd; + last24HourWindowStart = currentBlockTimestamp; } else { - return ( - true, - maxSingleTransactionLimit, - maxDailyLimit, - amountInUsd, - transferredInWindow, - last24HourWindowStart, - isWhiteListedUser - ); + transferredInWindow += amountInUsd; } + eligibleToSend = (isWhiteListedUser || + ((amountInUsd <= maxSingleTransactionLimit) && (transferredInWindow <= maxDailyLimit))); } /** From 4ef1a4c27fd824d8d4915f44a0c6c37d714a07c0 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:52:56 +0530 Subject: [PATCH 18/28] fix: resolve comments --- contracts/Bridge/XVSBridgeAdmin.sol | 2 +- contracts/Bridge/token/TokenController.sol | 10 +++++++++- helpers/deploymentConfig.ts | 1 + test/proxyOFT.ts | 6 +++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/contracts/Bridge/XVSBridgeAdmin.sol b/contracts/Bridge/XVSBridgeAdmin.sol index a0b5b0f..ac61317 100644 --- a/contracts/Bridge/XVSBridgeAdmin.sol +++ b/contracts/Bridge/XVSBridgeAdmin.sol @@ -89,7 +89,7 @@ contract XVSBridgeAdmin is AccessControlledV8 { emit FunctionRegistryChanged(signatures_[i], false); } unchecked { - i++; + ++i; } } } diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index 1481f84..da1de3d 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -68,6 +68,10 @@ contract TokenController is Ownable, Pausable { * @notice This error is used to indicate that sender is not allowed to perform this action. */ error Unauthorized(); + /** + * @notice This error is used to indicate that the new cap is greater than the previously minted tokens for the minter. + */ + error NewCapNotGreaterThanMintedTokens(); /** * @param accessControlManager_ Address of access control manager contract. @@ -118,7 +122,11 @@ contract TokenController is Ownable, Pausable { */ function setMintCap(address minter_, uint256 amount_) external { _ensureAllowed("setMintCap(address,uint256)"); - require(amount_ > minterToMintedAmount[minter_], "New cap should be greater than minted tokens"); + + if (amount_ < minterToMintedAmount[minter_]) { + revert NewCapNotGreaterThanMintedTokens(); + } + minterToCap[minter_] = amount_; emit MintCapChanged(minter_, amount_); } diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index a74b554..9802033 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -52,6 +52,7 @@ export const xvsBridgeMethods = [ "setPayloadSizeLimit(uint16,uint256)", "setWhitelist(address,bool)", "setConfig(uint16,uint16,uint256,bytes)", + "sweepToken(address,address,uint256)", ]; export const bridgeAdminMethods = ["setTrustedRemoteAddress(uint16,bytes)", "transferBridgeOwnership(address)"]; diff --git a/test/proxyOFT.ts b/test/proxyOFT.ts index 9aa53a1..f56ac44 100644 --- a/test/proxyOFT.ts +++ b/test/proxyOFT.ts @@ -559,9 +559,9 @@ describe("Proxy OFTV2: ", function () { ), // Msg should reach remote chain expect(await remoteEndpoint.inboundNonce(localChainId, localPath)).equals(1); - await expect(remoteToken.connect(acc1).setMintCap(remoteOFT.address, convertToUnit(1, 18))).to.be.revertedWith( - "New cap should be greater than minted tokens", - ); + await expect( + remoteToken.connect(acc1).setMintCap(remoteOFT.address, convertToUnit(1, 18)), + ).to.be.revertedWithCustomError(remoteToken, "NewCapNotGreaterThanMintedTokens"); }); it("Reverts on remote chain if minting cap is reached", async function () { From f659dee63bd5a3713e7ad0f81fa9bc515b0e8e62 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Fri, 15 Dec 2023 19:13:19 +0530 Subject: [PATCH 19/28] feat: revert on transfer of XVS for blacklisted address --- contracts/Bridge/token/XVS.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/Bridge/token/XVS.sol b/contracts/Bridge/token/XVS.sol index b36f32e..4b486d4 100644 --- a/contracts/Bridge/token/XVS.sol +++ b/contracts/Bridge/token/XVS.sol @@ -50,11 +50,15 @@ contract XVS is ERC20, TokenController { * @param from_ Address of account from which tokens are to be transferred. * @param to_ Address of the account to which tokens are to be transferred. * @param amount_ The amount of tokens to be transferred. + * @custom:error TransferNotAllowed is thrown when either `from` or `to` address is blacklisted. */ function _transfer(address from_, address to_, uint256 amount_) internal override whenNotPaused { if (_blacklist[to_]) { revert TransferNotAllowed(to_); } + if (_blacklist[from_]) { + revert TransferNotAllowed(from_); + } super._transfer(from_, to_, amount_); } } From 51168baa96a6ce64b5448726af26c3cdc105618e Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Fri, 15 Dec 2023 19:21:50 +0530 Subject: [PATCH 20/28] fix: natspec comments --- contracts/Bridge/token/TokenController.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index da1de3d..fa4f791 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -61,9 +61,9 @@ contract TokenController is Ownable, Pausable { */ error MintNotAllowed(address from, address to); /** - * @notice This error is used to indicate that transfers are not allowed for the to_ address. + * @notice This error is used to indicate that transfers are not allowed for the user address. */ - error TransferNotAllowed(address to); + error TransferNotAllowed(address user); /** * @notice This error is used to indicate that sender is not allowed to perform this action. */ From 3bd6b14becdc7ee2f9ec27031710cb16c91d0338 Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Mon, 18 Dec 2023 13:19:56 +0100 Subject: [PATCH 21/28] chore: add opbnbtestnet and opbnbmainnet to the ci step to extract addresses --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e9be239..7a90aa0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -114,7 +114,7 @@ jobs: - name: Export deployments run: | - for NETWORK in bsctestnet bscmainnet ethereum sepolia; do + for NETWORK in bsctestnet bscmainnet ethereum sepolia opbnbtestnet opbnbmainnet; do EXPORT=true yarn hardhat export --network ${NETWORK} --export ./deployments/${NETWORK}.json jq -M '{name, chainId, addresses: .contracts | map_values(.address)}' ./deployments/${NETWORK}.json > ./deployments/${NETWORK}_addresses.json done From db0c06700608e9772d580c41eb2b4b3462e836cf Mon Sep 17 00:00:00 2001 From: chechu Date: Mon, 18 Dec 2023 12:21:28 +0000 Subject: [PATCH 22/28] feat: updating deployment files --- deployments/opbnbmainnet.json | 5 +++++ deployments/opbnbmainnet_addresses.json | 5 +++++ deployments/opbnbtestnet_addresses.json | 7 +++++++ 3 files changed, 17 insertions(+) create mode 100644 deployments/opbnbmainnet.json create mode 100644 deployments/opbnbmainnet_addresses.json create mode 100644 deployments/opbnbtestnet_addresses.json diff --git a/deployments/opbnbmainnet.json b/deployments/opbnbmainnet.json new file mode 100644 index 0000000..6a503c8 --- /dev/null +++ b/deployments/opbnbmainnet.json @@ -0,0 +1,5 @@ +{ + "name": "opbnbmainnet", + "chainId": "204", + "contracts": {} +} diff --git a/deployments/opbnbmainnet_addresses.json b/deployments/opbnbmainnet_addresses.json new file mode 100644 index 0000000..cf3419c --- /dev/null +++ b/deployments/opbnbmainnet_addresses.json @@ -0,0 +1,5 @@ +{ + "name": "opbnbmainnet", + "chainId": "204", + "addresses": {} +} diff --git a/deployments/opbnbtestnet_addresses.json b/deployments/opbnbtestnet_addresses.json new file mode 100644 index 0000000..7c62449 --- /dev/null +++ b/deployments/opbnbtestnet_addresses.json @@ -0,0 +1,7 @@ +{ + "name": "opbnbtestnet", + "chainId": "5611", + "addresses": { + "XVS": "0x3d0e20D4caD958bc848B045e1da19Fe378f86f03" + } +} From 812769fdbe62978c833cc7771723f81caa0814e7 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Mon, 18 Dec 2023 12:53:47 +0000 Subject: [PATCH 23/28] chore(release): 1.0.0-dev.5 [skip ci] ## [1.0.0-dev.5](https://github.com/VenusProtocol/token-bridge/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2023-12-18) ### Features * updating deployment files ([db0c067](https://github.com/VenusProtocol/token-bridge/commit/db0c06700608e9772d580c41eb2b4b3462e836cf)) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 74ab04c..2bdc2a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/token-bridge", - "version": "1.0.0-dev.4", + "version": "1.0.0-dev.5", "description": "Contracts to bridge tokens using LayerZero technology and applying some rules on top of it", "files": [ "artifacts", From 60d4c5c88fe4f6a83b5cedb615fd20ed5f055301 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:18:38 +0530 Subject: [PATCH 24/28] fix: BRI-03 --- contracts/Bridge/XVSProxyOFTSrc.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Bridge/XVSProxyOFTSrc.sol b/contracts/Bridge/XVSProxyOFTSrc.sol index cce5101..04aadd9 100644 --- a/contracts/Bridge/XVSProxyOFTSrc.sol +++ b/contracts/Bridge/XVSProxyOFTSrc.sol @@ -68,7 +68,7 @@ contract XVSProxyOFTSrc is BaseXVSProxyOFT { /** * @notice Returns the total circulating supply of the token on the source chain i.e (total supply - locked in this contract). - * @return Returns total supply of the token. + * @return Returns difference in total supply and the outbound amount. */ function circulatingSupply() public view override returns (uint256) { return innerToken.totalSupply() - outboundAmount; From 9a4c39c78ff944e38a7d31afb4a474626eb9fe50 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 19 Dec 2023 05:49:35 +0000 Subject: [PATCH 25/28] feat: updating deployment files --- deployments/opbnbmainnet.json | 5 +++++ deployments/opbnbmainnet_addresses.json | 5 +++++ deployments/opbnbtestnet_addresses.json | 7 +++++++ 3 files changed, 17 insertions(+) create mode 100644 deployments/opbnbmainnet.json create mode 100644 deployments/opbnbmainnet_addresses.json create mode 100644 deployments/opbnbtestnet_addresses.json diff --git a/deployments/opbnbmainnet.json b/deployments/opbnbmainnet.json new file mode 100644 index 0000000..6a503c8 --- /dev/null +++ b/deployments/opbnbmainnet.json @@ -0,0 +1,5 @@ +{ + "name": "opbnbmainnet", + "chainId": "204", + "contracts": {} +} diff --git a/deployments/opbnbmainnet_addresses.json b/deployments/opbnbmainnet_addresses.json new file mode 100644 index 0000000..cf3419c --- /dev/null +++ b/deployments/opbnbmainnet_addresses.json @@ -0,0 +1,5 @@ +{ + "name": "opbnbmainnet", + "chainId": "204", + "addresses": {} +} diff --git a/deployments/opbnbtestnet_addresses.json b/deployments/opbnbtestnet_addresses.json new file mode 100644 index 0000000..7c62449 --- /dev/null +++ b/deployments/opbnbtestnet_addresses.json @@ -0,0 +1,7 @@ +{ + "name": "opbnbtestnet", + "chainId": "5611", + "addresses": { + "XVS": "0x3d0e20D4caD958bc848B045e1da19Fe378f86f03" + } +} From 66e0995d302b91621362d18d58db2cea634b4c2b Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:34:37 +0530 Subject: [PATCH 26/28] fix: BRI-07 --- contracts/Bridge/token/TokenController.sol | 12 ++---------- contracts/Bridge/token/XVS.sol | 13 ++++++------- test/proxyOFT.ts | 2 +- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/contracts/Bridge/token/TokenController.sol b/contracts/Bridge/token/TokenController.sol index fa4f791..761e2bd 100644 --- a/contracts/Bridge/token/TokenController.sol +++ b/contracts/Bridge/token/TokenController.sol @@ -57,13 +57,9 @@ contract TokenController is Ownable, Pausable { */ error MintLimitExceed(); /** - * @notice This error is used to indicate that minting is not allowed for the specified addresses. + * @notice This error is used to indicate that `mint` `burn` and `transfer` actions are not allowed for the user address. */ - error MintNotAllowed(address from, address to); - /** - * @notice This error is used to indicate that transfers are not allowed for the user address. - */ - error TransferNotAllowed(address user); + error AccountBlacklisted(address user); /** * @notice This error is used to indicate that sender is not allowed to perform this action. */ @@ -159,14 +155,10 @@ contract TokenController is Ownable, Pausable { * @param from_ Minter address. * @param to_ Receiver address. * @param amount_ Amount to be mint. - * @custom:error MintNotAllowed is thrown when user is in blacklist * @custom:error MintLimitExceed is thrown when minting limit exceeds the cap. * @custom:event Emits MintLimitDecreased with minter address and available limits. */ function _isEligibleToMint(address from_, address to_, uint256 amount_) internal { - if (_blacklist[to_]) { - revert MintNotAllowed(from_, to_); - } uint256 mintingCap = minterToCap[from_]; uint256 totalMintedOld = minterToMintedAmount[from_]; uint256 totalMintedNew = totalMintedOld + amount_; diff --git a/contracts/Bridge/token/XVS.sol b/contracts/Bridge/token/XVS.sol index 4b486d4..b1a64ff 100644 --- a/contracts/Bridge/token/XVS.sol +++ b/contracts/Bridge/token/XVS.sol @@ -22,7 +22,6 @@ contract XVS is ERC20, TokenController { * @param amount_ Amount of tokens to be assigned. * @custom:access Controlled by AccessControlManager. * @custom:event Emits MintLimitDecreased with new available limit. - * @custom:error MintNotAllowed is thrown when minting is not allowed to to_ address. * @custom:error MintLimitExceed is thrown when minting amount exceeds the maximum cap. */ function mint(address account_, uint256 amount_) external whenNotPaused { @@ -46,19 +45,19 @@ contract XVS is ERC20, TokenController { } /** - * @notice Moves `amount` of tokens from `from` to `to`. + * @notice Hook that is called before any transfer of tokens. This includes + * minting and burning. * @param from_ Address of account from which tokens are to be transferred. * @param to_ Address of the account to which tokens are to be transferred. * @param amount_ The amount of tokens to be transferred. - * @custom:error TransferNotAllowed is thrown when either `from` or `to` address is blacklisted. + * @custom:error AccountBlacklisted is thrown when either `from` or `to` address is blacklisted. */ - function _transfer(address from_, address to_, uint256 amount_) internal override whenNotPaused { + function _beforeTokenTransfer(address from_, address to_, uint256 amount_) internal override whenNotPaused { if (_blacklist[to_]) { - revert TransferNotAllowed(to_); + revert AccountBlacklisted(to_); } if (_blacklist[from_]) { - revert TransferNotAllowed(from_); + revert AccountBlacklisted(from_); } - super._transfer(from_, to_, amount_); } } diff --git a/test/proxyOFT.ts b/test/proxyOFT.ts index f56ac44..7336cf1 100644 --- a/test/proxyOFT.ts +++ b/test/proxyOFT.ts @@ -533,7 +533,7 @@ describe("Proxy OFTV2: ", function () { await remoteToken.updateBlacklist(acc3.address, true); await expect(remoteToken.connect(acc2).transfer(acc3.address, amount)).to.be.revertedWithCustomError( remoteToken, - "TransferNotAllowed", + "AccountBlacklisted", ); }); From 3e8bae9221ccc2cf5690882a0cee358361d77aed Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Wed, 20 Dec 2023 07:02:14 +0000 Subject: [PATCH 27/28] chore(release): 1.0.0-dev.6 [skip ci] ## [1.0.0-dev.6](https://github.com/VenusProtocol/token-bridge/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2023-12-20) ### Features * add isEligibleToSend function ([acc9dfb](https://github.com/VenusProtocol/token-bridge/commit/acc9dfbfba60da0c615b8145a772d1d1013b13fb)) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2bdc2a5..179a109 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/token-bridge", - "version": "1.0.0-dev.5", + "version": "1.0.0-dev.6", "description": "Contracts to bridge tokens using LayerZero technology and applying some rules on top of it", "files": [ "artifacts", From ef5cfa770fb08cb02a16b8631d0cbdd4605b7b1a Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Wed, 20 Dec 2023 07:05:34 +0000 Subject: [PATCH 28/28] chore(release): 1.0.0-dev.7 [skip ci] ## [1.0.0-dev.7](https://github.com/VenusProtocol/token-bridge/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2023-12-20) ### Features * revert on transfer of XVS for blacklisted address ([f659dee](https://github.com/VenusProtocol/token-bridge/commit/f659dee63bd5a3713e7ad0f81fa9bc515b0e8e62)) * updating deployment files ([9a4c39c](https://github.com/VenusProtocol/token-bridge/commit/9a4c39c78ff944e38a7d31afb4a474626eb9fe50)) ### Bug Fixes * BRI-02 ([8ce11e6](https://github.com/VenusProtocol/token-bridge/commit/8ce11e679649956014e700aac2e7b622e1886970)) * BRI-03 ([60d4c5c](https://github.com/VenusProtocol/token-bridge/commit/60d4c5c88fe4f6a83b5cedb615fd20ed5f055301)) * BRI-03 ([7c63f14](https://github.com/VenusProtocol/token-bridge/commit/7c63f14cb6ebae8f97ddbba719be6d196c59593f)) * BRI-06 ([85a718c](https://github.com/VenusProtocol/token-bridge/commit/85a718c299a1e65034b52c9494bc8479adfb3a87)) * BRI-07 ([66e0995](https://github.com/VenusProtocol/token-bridge/commit/66e0995d302b91621362d18d58db2cea634b4c2b)) * BRI-07 ([52ff112](https://github.com/VenusProtocol/token-bridge/commit/52ff1120d828b50ff110acb2df939abe28a3dd28)) * BXV-01 ([5293d3e](https://github.com/VenusProtocol/token-bridge/commit/5293d3e5c1d33e0aa41500431e1f529adf612902)) * BXV-03 ([7c2193b](https://github.com/VenusProtocol/token-bridge/commit/7c2193bd7e7d9de4dff59982b98050844a9b3e51)) * natspec comments ([51168ba](https://github.com/VenusProtocol/token-bridge/commit/51168baa96a6ce64b5448726af26c3cdc105618e)) * resolve comments ([4ef1a4c](https://github.com/VenusProtocol/token-bridge/commit/4ef1a4c27fd824d8d4915f44a0c6c37d714a07c0)) * TCB-02 ([df7b43a](https://github.com/VenusProtocol/token-bridge/commit/df7b43aa9c1fc3d188b7e9a33290d587bd185470)) * TCB-04 ([b017f57](https://github.com/VenusProtocol/token-bridge/commit/b017f579abd2c5709075f581fe1168e4ed9e3d2e)) * TCB-05 ([2ddf4c0](https://github.com/VenusProtocol/token-bridge/commit/2ddf4c02544c010ca8d669ae02c71d8ea976f76e)) * XVB-02 ([f57a9ab](https://github.com/VenusProtocol/token-bridge/commit/f57a9ab2d4688ba7269abcaaeced316aad1ccbc4)) * XVO-02 ([06c6009](https://github.com/VenusProtocol/token-bridge/commit/06c6009e01411182d738b2249cbbb06019926b54)) * XVS-01 ([6785b84](https://github.com/VenusProtocol/token-bridge/commit/6785b84e085eaf455e35f66a6d04f79570279e5f)) * XVS-02 ([6bacbf7](https://github.com/VenusProtocol/token-bridge/commit/6bacbf7b9a265afeb99188bfe3c3d864ae06c145)) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 179a109..a5a3e77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/token-bridge", - "version": "1.0.0-dev.6", + "version": "1.0.0-dev.7", "description": "Contracts to bridge tokens using LayerZero technology and applying some rules on top of it", "files": [ "artifacts",