Skip to content

Commit

Permalink
Disable/Enable rate limit for erc20 tokens (#311)
Browse files Browse the repository at this point in the history
- closes #309
  • Loading branch information
viraj124 authored Oct 1, 2024
1 parent 89313e2 commit 00add45
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/smooth-carrots-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fuel-bridge/solidity-contracts': minor
---

add rate limit disabling/re-enabling
4 changes: 4 additions & 0 deletions packages/integration-tests/tests/bridge_erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ describe('Bridging ERC20 tokens', async function () {
RATE_LIMIT_DURATION
);

await env.eth.fuelERC20Gateway
.connect(env.eth.deployer)
.updateRateLimitStatus(eth_testTokenAddress, true);

const { value: expectedGatewayContractId } = await fuel_bridge.functions
.bridged_token_gateway()
.addContracts([fuel_bridge, fuel_bridgeImpl])
Expand Down
4 changes: 4 additions & 0 deletions packages/integration-tests/tests/bridge_mainnet_tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ describe('Bridge mainnet tokens', function () {
rateLimitAmount.toString(),
RATE_LIMIT_DURATION
);

await env.eth.fuelERC20Gateway
.connect(env.eth.deployer)
.updateRateLimitStatus(tokenAddress, true);
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ contract FuelERC20GatewayV4 is
/// @dev Emitted when rate limit is reset
event RateLimitUpdated(address indexed tokenAddress, uint256 amount);

/// @dev Emitted when rate limit is enabled/disabled
event RateLimitStatusUpdated(address indexed tokenAddress, bool status);

enum MessageType {
DEPOSIT_TO_ADDRESS,
DEPOSIT_TO_CONTRACT,
Expand Down Expand Up @@ -89,6 +92,11 @@ contract FuelERC20GatewayV4 is
/// @notice The eth withdrawal limit amount for each token.
mapping(address => uint256) public limitAmount;

/// @notice Flag to indicate rate limit status for each token, whether disabled or enabled.
// if `true` it is enabled
// if `false` it is disabled
mapping(address => bool) public rateLimitStatus;

/// @notice disabling initialization
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
Expand Down Expand Up @@ -175,6 +183,17 @@ contract FuelERC20GatewayV4 is

emit RateLimitUpdated(_token, _amount);
}

/**
* @notice updates rate limit status by disabling/re-enabling rate limit.
* @param _token The token address to update rate limit status for.
* @param _rateLimitStatus bool flag to disable or re-enable rate limit.
*/
function updateRateLimitStatus(address _token, bool _rateLimitStatus) external onlyRole(SET_RATE_LIMITER_ROLE) {
rateLimitStatus[_token] = _rateLimitStatus;

emit RateLimitStatusUpdated(_token, _rateLimitStatus);
}

//////////////////////
// Public Functions //
Expand Down Expand Up @@ -287,8 +306,9 @@ contract FuelERC20GatewayV4 is
uint8 decimals = _getTokenDecimals(tokenAddress);
uint256 amount = _adjustWithdrawalDecimals(decimals, l2BurntAmount);

// rate limit check only if rate limit is initialized
if (currentPeriodEnd[tokenAddress] != 0) _addWithdrawnAmount(tokenAddress, amount);
// rate limit check is only performed when it is enabled
// if the rate limit has not been initialised then the tx will revert with `RateLimitExceeded()`
if (rateLimitStatus[tokenAddress]) _addWithdrawnAmount(tokenAddress, amount);

//reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)
_deposits[tokenAddress] = _deposits[tokenAddress] - l2BurntAmount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {
const rateLimitAmount =
RATE_LIMIT_AMOUNT / 10 ** (STANDARD_TOKEN_DECIMALS - decimals);

const tx = erc20Gateway
let tx = erc20Gateway
.connect(deployer)
.resetRateLimitAmount(
token.getAddress(),
Expand All @@ -1050,6 +1050,14 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {
await expect(tx)
.to.emit(erc20Gateway, 'RateLimitUpdated')
.withArgs(token.getAddress(), rateLimitAmount.toString());

tx = erc20Gateway
.connect(deployer)
.updateRateLimitStatus(token, true);

await expect(tx)
.to.emit(erc20Gateway, 'RateLimitStatusUpdated')
.withArgs(token.getAddress(), true);
});

it('does not update rate limit vars when it is not initialized', async () => {
Expand Down Expand Up @@ -1133,6 +1141,13 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {
RATE_LIMIT_DURATION
);

await erc20Gateway
.connect(deployer)
.updateRateLimitStatus(token, true);

const status = await erc20Gateway.rateLimitStatus(token);
expect(status).to.be.true;

const amount = parseUnits(
random(0.01, 1, true).toFixed(decimals),
Number(decimals)
Expand Down Expand Up @@ -1238,6 +1253,10 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {
RATE_LIMIT_DURATION
);

await erc20Gateway
.connect(deployer)
.updateRateLimitStatus(token, true);

const amount = parseUnits('10', Number(decimals));
const recipient = randomBytes32();

Expand Down Expand Up @@ -1273,6 +1292,7 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {

const currentWithdrawnAmountBeforeSettingLimit =
await erc20Gateway.currentPeriodAmount(token.getAddress());

rateLimitAmount =
RATE_LIMIT_AMOUNT /
5 /
Expand All @@ -1289,6 +1309,10 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {
const currentWithdrawnAmountAfterSettingLimit =
await erc20Gateway.currentPeriodAmount(token.getAddress());

expect(currentWithdrawnAmountAfterSettingLimit).to.be.equal(
withdrawAmount
);

expect(currentWithdrawnAmountAfterSettingLimit).to.be.equal(
currentWithdrawnAmountBeforeSettingLimit
);
Expand Down Expand Up @@ -1340,6 +1364,10 @@ export function behavesLikeErc20GatewayV4(fixture: () => Promise<Env>) {
RATE_LIMIT_DURATION
);

await erc20Gateway
.connect(deployer)
.updateRateLimitStatus(token, true);

const amount = parseUnits('10', Number(decimals));
const recipient = randomBytes32();

Expand Down
2 changes: 1 addition & 1 deletion packages/solidity-contracts/test/fuelChainState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe('Fuel Chain State', async () => {
).to.be.revertedWithCustomError(FuelChainState, 'TimeToFinalizeTooLarge');
});

it('reverts if time to finalise is more than circularBufferSizeInSeconds', async () => {
it('reverts if commit cooldown period is more than circularBufferSizeInSeconds', async () => {
await expect(
upgrades.deployProxy(FuelChainState, [], {
initializer: 'initialize',
Expand Down

0 comments on commit 00add45

Please sign in to comment.