From b9af64d4dcde3d22252032f8b8e76421efa4dce0 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Thu, 15 Aug 2024 18:02:42 +0300 Subject: [PATCH 01/13] feat: add increase/decrease freeze balance functions --- contracts/base/ERC20Freezable.sol | 39 +++++++++++++++++++ contracts/base/interfaces/IERC20Freezable.sol | 25 ++++++++++++ 2 files changed, 64 insertions(+) diff --git a/contracts/base/ERC20Freezable.sol b/contracts/base/ERC20Freezable.sol index 3d7bed68..d3b349dd 100644 --- a/contracts/base/ERC20Freezable.sol +++ b/contracts/base/ERC20Freezable.sol @@ -110,6 +110,45 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { _transfer(from, to, amount); } + /** + * @inheritdoc IERC20Freezable + */ + function frozenIncrease(address account, uint256 amount) external onlyBlocklister { + if (account == address(0)) { + revert ZeroAddress(); + } + if (amount == 0) { + revert ZeroAmount(); + } + + uint256 oldBalance = _frozenBalances[account]; + uint256 newBalance = oldBalance + amount; + _frozenBalances[account] = newBalance; + + emit FrozenUpdated(account, newBalance, oldBalance); + } + + /** + * @inheritdoc IERC20Freezable + */ + function frozenDecrease(address account, uint256 amount) external onlyBlocklister { + uint256 oldBalance = _frozenBalances[account]; + if (account == address(0)) { + revert ZeroAddress(); + } + if (amount == 0) { + revert ZeroAmount(); + } + if (amount > oldBalance) { + revert LackOfFrozenBalance(); + } + + uint256 newBalance = oldBalance - amount; + _frozenBalances[account] = newBalance; + + emit FrozenUpdated(account, newBalance, oldBalance); + } + /** * @inheritdoc IERC20Freezable */ diff --git a/contracts/base/interfaces/IERC20Freezable.sol b/contracts/base/interfaces/IERC20Freezable.sol index bd559e34..3162b9c0 100644 --- a/contracts/base/interfaces/IERC20Freezable.sol +++ b/contracts/base/interfaces/IERC20Freezable.sol @@ -32,6 +32,15 @@ interface IERC20Freezable { */ event Freeze(address indexed account, uint256 newFrozenBalance, uint256 oldFrozenBalance); + /** + * @notice Emitted when the frozen balance is updated for an account + * + * @param account The account the frozen is updated for + * @param newBalance The new frozen balance + * @param oldBalance The old frozen balance + */ + event FrozenUpdated(address indexed account, uint256 newBalance, uint256 oldBalance); + /** * @notice Approves token freezing for the caller * @@ -60,6 +69,22 @@ interface IERC20Freezable { */ function transferFrozen(address from, address to, uint256 amount) external; + /** + * @notice Increases the frozen balance for an account + * + * @param account The account to increase frozen for + * @param amount The amount to increase the frozen balance by + */ + function frozenIncrease(address account, uint256 amount) external; + + /** + * @notice Decreases the frozen balance for an account + * + * @param account The account to decrease frozen for + * @param amount The amount to decrease the frozen balance by + */ + function frozenDecrease(address account, uint256 amount) external; + /** * @notice Checks if token freezing is approved for an account * From 36818f3aab5b9f8a1a3771ab29a26c2d91d74033 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Thu, 15 Aug 2024 18:41:34 +0300 Subject: [PATCH 02/13] feat: add test for freeze increase/decrease --- test/base/ERC20Freezable.test.ts | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/test/base/ERC20Freezable.test.ts b/test/base/ERC20Freezable.test.ts index 033dfca0..3c1b505e 100644 --- a/test/base/ERC20Freezable.test.ts +++ b/test/base/ERC20Freezable.test.ts @@ -22,6 +22,7 @@ describe("Contract 'ERC20Freezable'", async () => { const EVENT_NAME_FREEZE = "Freeze"; const EVENT_NAME_FREEZE_APPROVAL = "FreezeApproval"; const EVENT_NAME_FREEZE_TRANSFER = "FreezeTransfer"; + const EVENT_NAME_FROZEN_UPDATED = "FrozenUpdated"; const REVERT_MESSAGE_INITIALIZABLE_CONTRACT_IS_ALREADY_INITIALIZED = "Initializable: contract is already initialized"; const REVERT_MESSAGE_INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING = "Initializable: contract is not initializing"; @@ -32,6 +33,8 @@ describe("Contract 'ERC20Freezable'", async () => { const REVERT_ERROR_FREEZING_ALREADY_APPROVED = "FreezingAlreadyApproved"; const REVERT_ERROR_FREEZING_NOT_APPROVED = "FreezingNotApproved"; const REVERT_ERROR_LACK_OF_FROZEN_BALANCE = "LackOfFrozenBalance"; + const REVERT_ERROR_ZERO_AMOUNT = "ZeroAmount"; + const REVERT_ERROR_ZERO_ADDRESS = "ZeroAddress"; let tokenFactory: ContractFactory; let deployer: HardhatEthersSigner; @@ -318,4 +321,82 @@ describe("Contract 'ERC20Freezable'", async () => { }); }); }); + + describe("Function 'frozenIncrease()'", async () => { + it("Increase frozen and emits the correct event", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + + expect(await token.balanceOfFrozen(user1.address)).to.eq(0); + + await expect(connect(token, blocklister).frozenIncrease(user1.address, 100)) + .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .withArgs(user1.address, 100, 0); + expect(await token.balanceOfFrozen(user1.address)).to.eq(100); + + await expect(connect(token, blocklister).frozenIncrease(user1.address, 100)) + .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .withArgs(user1.address, 200, 100); + expect(await token.balanceOfFrozen(user1.address)).to.eq(200); + }); + + it("Is reverted if the caller is not a blocklister", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await expect( + connect(token, user1).frozenIncrease(user2.address, 100) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_UNAUTHORIZED_BLOCKLISTER); + }); + + it("Is reverted if the provided account is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await expect( + connect(token, blocklister).frozenIncrease(ethers.ZeroAddress, 100) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); + }); + + it("Is reverted if the provided amount is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await expect( + connect(token, blocklister).frozenIncrease(user2.address, 0) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); + }); + }); + + describe("Function 'frozenDecrease()'", async () => { + it("Decrease frozen and emits the correct event", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + + await proveTx(connect(token, blocklister).frozenIncrease(user1.address, 200)); + + await expect(connect(token, blocklister).frozenDecrease(user1.address, 100)) + .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .withArgs(user1.address, 100, 200); + expect(await token.balanceOfFrozen(user1.address)).to.eq(100); + + await expect(connect(token, blocklister).frozenDecrease(user1.address, 100)) + .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .withArgs(user1.address, 0, 100); + expect(await token.balanceOfFrozen(user1.address)).to.eq(0); + }); + + it("Is reverted if the caller is not a blocklister", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await expect( + connect(token, user1).frozenDecrease(user1.address, 100) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_UNAUTHORIZED_BLOCKLISTER); + }); + + it("Is reverted if the provided account is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await expect( + connect(token, blocklister).frozenDecrease(ethers.ZeroAddress, 100) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); + }); + + it("Is reverted if the provided amount is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await expect( + connect(token, blocklister).frozenDecrease(user1.address, 0) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); + }); + }); }); From 71ac8c2911583e91211b7de543854ebb2d170f06 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Fri, 16 Aug 2024 18:48:11 +0300 Subject: [PATCH 03/13] feat: inc/dec functions --- contracts/base/ERC20Freezable.sol | 41 ++++++++++--------- contracts/base/interfaces/IERC20Freezable.sol | 14 ++++--- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/contracts/base/ERC20Freezable.sol b/contracts/base/ERC20Freezable.sol index d3b349dd..c45745de 100644 --- a/contracts/base/ERC20Freezable.sol +++ b/contracts/base/ERC20Freezable.sol @@ -80,6 +80,7 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { } emit Freeze(account, amount, _frozenBalances[account]); + emit FrozenBalanceUpdated(account, amount, _frozenBalances[account]); _frozenBalances[account] = amount; } @@ -105,6 +106,7 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { emit FreezeTransfer(from, amount); emit Freeze(from, newFrozenBalance, oldFrozenBalance); + emit FrozenBalanceUpdated(from, newFrozenBalance, oldFrozenBalance); _frozenBalances[from] = newFrozenBalance; _transfer(from, to, amount); @@ -113,40 +115,39 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { /** * @inheritdoc IERC20Freezable */ - function frozenIncrease(address account, uint256 amount) external onlyBlocklister { - if (account == address(0)) { - revert ZeroAddress(); - } - if (amount == 0) { - revert ZeroAmount(); - } - - uint256 oldBalance = _frozenBalances[account]; - uint256 newBalance = oldBalance + amount; - _frozenBalances[account] = newBalance; - - emit FrozenUpdated(account, newBalance, oldBalance); + function freezeIncrease(address account, uint256 amount) external onlyBlocklister { + _freezeChange(account, amount, true); } /** * @inheritdoc IERC20Freezable */ - function frozenDecrease(address account, uint256 amount) external onlyBlocklister { - uint256 oldBalance = _frozenBalances[account]; + function freezeDecrease(address account, uint256 amount) external onlyBlocklister { + _freezeChange(account, amount, false); + } + + function _freezeChange(address account, uint256 amount, bool increasing) internal onlyBlocklister { if (account == address(0)) { revert ZeroAddress(); } - if (amount == 0) { - revert ZeroAmount(); + if (!_freezeApprovals[account]) { + revert FreezingNotApproved(); } - if (amount > oldBalance) { + + uint256 oldBalance = _frozenBalances[account]; + uint256 newBalance; + + if (increasing) { + newBalance = oldBalance + amount; + } else if (!increasing && amount <= oldBalance) { + newBalance = oldBalance - amount; + } else { revert LackOfFrozenBalance(); } - uint256 newBalance = oldBalance - amount; _frozenBalances[account] = newBalance; - emit FrozenUpdated(account, newBalance, oldBalance); + emit FrozenBalanceUpdated(account, newBalance, oldBalance); } /** diff --git a/contracts/base/interfaces/IERC20Freezable.sol b/contracts/base/interfaces/IERC20Freezable.sol index 3162b9c0..db486266 100644 --- a/contracts/base/interfaces/IERC20Freezable.sol +++ b/contracts/base/interfaces/IERC20Freezable.sol @@ -39,7 +39,7 @@ interface IERC20Freezable { * @param newBalance The new frozen balance * @param oldBalance The old frozen balance */ - event FrozenUpdated(address indexed account, uint256 newBalance, uint256 oldBalance); + event FrozenBalanceUpdated(address indexed account, uint256 newBalance, uint256 oldBalance); /** * @notice Approves token freezing for the caller @@ -72,18 +72,22 @@ interface IERC20Freezable { /** * @notice Increases the frozen balance for an account * - * @param account The account to increase frozen for + * Emits a {FrozenBalanceUpdated} event + * + * @param account The account to increase frozen balance for * @param amount The amount to increase the frozen balance by */ - function frozenIncrease(address account, uint256 amount) external; + function freezeIncrease(address account, uint256 amount) external; /** * @notice Decreases the frozen balance for an account * - * @param account The account to decrease frozen for + * Emits a {FrozenBalanceUpdated} event + * + * @param account The account to decrease frozen balance for * @param amount The amount to decrease the frozen balance by */ - function frozenDecrease(address account, uint256 amount) external; + function freezeDecrease(address account, uint256 amount) external; /** * @notice Checks if token freezing is approved for an account From 6d5f8bcab521c232b3cac76e73d58e20e71947da Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Fri, 16 Aug 2024 18:48:36 +0300 Subject: [PATCH 04/13] feat: update inc/dec freeze tests --- test/base/ERC20Freezable.test.ts | 48 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/test/base/ERC20Freezable.test.ts b/test/base/ERC20Freezable.test.ts index 3c1b505e..abb381d7 100644 --- a/test/base/ERC20Freezable.test.ts +++ b/test/base/ERC20Freezable.test.ts @@ -22,7 +22,7 @@ describe("Contract 'ERC20Freezable'", async () => { const EVENT_NAME_FREEZE = "Freeze"; const EVENT_NAME_FREEZE_APPROVAL = "FreezeApproval"; const EVENT_NAME_FREEZE_TRANSFER = "FreezeTransfer"; - const EVENT_NAME_FROZEN_UPDATED = "FrozenUpdated"; + const EVENT_NAME_FROZEN_UPDATED = "FrozenBalanceUpdated"; const REVERT_MESSAGE_INITIALIZABLE_CONTRACT_IS_ALREADY_INITIALIZED = "Initializable: contract is already initialized"; const REVERT_MESSAGE_INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING = "Initializable: contract is not initializing"; @@ -322,18 +322,18 @@ describe("Contract 'ERC20Freezable'", async () => { }); }); - describe("Function 'frozenIncrease()'", async () => { - it("Increase frozen and emits the correct event", async () => { + describe("Function 'freezeIncrease()'", async () => { + it("Increase frozen balance and emits the correct event", async () => { const { token } = await setUpFixture(deployAndConfigureToken); - + await proveTx(connect(token, user1).approveFreezing()); expect(await token.balanceOfFrozen(user1.address)).to.eq(0); - await expect(connect(token, blocklister).frozenIncrease(user1.address, 100)) + await expect(connect(token, blocklister).freezeIncrease(user1.address, 100)) .to.emit(token, EVENT_NAME_FROZEN_UPDATED) .withArgs(user1.address, 100, 0); expect(await token.balanceOfFrozen(user1.address)).to.eq(100); - await expect(connect(token, blocklister).frozenIncrease(user1.address, 100)) + await expect(connect(token, blocklister).freezeIncrease(user1.address, 100)) .to.emit(token, EVENT_NAME_FROZEN_UPDATED) .withArgs(user1.address, 200, 100); expect(await token.balanceOfFrozen(user1.address)).to.eq(200); @@ -342,37 +342,32 @@ describe("Contract 'ERC20Freezable'", async () => { it("Is reverted if the caller is not a blocklister", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await expect( - connect(token, user1).frozenIncrease(user2.address, 100) + connect(token, user1).freezeIncrease(user2.address, 100) ).to.be.revertedWithCustomError(token, REVERT_ERROR_UNAUTHORIZED_BLOCKLISTER); }); it("Is reverted if the provided account is zero", async () => { const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, user1).approveFreezing()); await expect( - connect(token, blocklister).frozenIncrease(ethers.ZeroAddress, 100) + connect(token, blocklister).freezeIncrease(ethers.ZeroAddress, 100) ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); }); - - it("Is reverted if the provided amount is zero", async () => { - const { token } = await setUpFixture(deployAndConfigureToken); - await expect( - connect(token, blocklister).frozenIncrease(user2.address, 0) - ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); - }); }); - describe("Function 'frozenDecrease()'", async () => { - it("Decrease frozen and emits the correct event", async () => { + describe("Function 'freezeDecrease()'", async () => { + it("Decrease frozen balance and emits the correct event", async () => { const { token } = await setUpFixture(deployAndConfigureToken); - await proveTx(connect(token, blocklister).frozenIncrease(user1.address, 200)); + await proveTx(connect(token, user1).approveFreezing()); + await proveTx(connect(token, blocklister).freezeIncrease(user1.address, 200)); - await expect(connect(token, blocklister).frozenDecrease(user1.address, 100)) + await expect(connect(token, blocklister).freezeDecrease(user1.address, 100)) .to.emit(token, EVENT_NAME_FROZEN_UPDATED) .withArgs(user1.address, 100, 200); expect(await token.balanceOfFrozen(user1.address)).to.eq(100); - await expect(connect(token, blocklister).frozenDecrease(user1.address, 100)) + await expect(connect(token, blocklister).freezeDecrease(user1.address, 100)) .to.emit(token, EVENT_NAME_FROZEN_UPDATED) .withArgs(user1.address, 0, 100); expect(await token.balanceOfFrozen(user1.address)).to.eq(0); @@ -381,22 +376,25 @@ describe("Contract 'ERC20Freezable'", async () => { it("Is reverted if the caller is not a blocklister", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await expect( - connect(token, user1).frozenDecrease(user1.address, 100) + connect(token, user1).freezeDecrease(user1.address, 100) ).to.be.revertedWithCustomError(token, REVERT_ERROR_UNAUTHORIZED_BLOCKLISTER); }); it("Is reverted if the provided account is zero", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await expect( - connect(token, blocklister).frozenDecrease(ethers.ZeroAddress, 100) + connect(token, blocklister).freezeDecrease(ethers.ZeroAddress, 100) ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); }); - it("Is reverted if the provided amount is zero", async () => { + it("Is reverted if the provided amount is greater then old balance", async () => { const { token } = await setUpFixture(deployAndConfigureToken); + + await proveTx(connect(token, user1).approveFreezing()); + await proveTx(connect(token, blocklister).freezeIncrease(user1.address, 100)); await expect( - connect(token, blocklister).frozenDecrease(user1.address, 0) - ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); + connect(token, blocklister).freezeDecrease(user1.address, 200) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_LACK_OF_FROZEN_BALANCE); }); }); }); From fe505ca84e6f1a8eb9b1761a471db79d3a070ea0 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Mon, 19 Aug 2024 10:42:46 +0300 Subject: [PATCH 05/13] feat: add zero amount/zero address --- contracts/base/ERC20Freezable.sol | 15 ++++++++++++--- contracts/base/interfaces/IERC20Freezable.sol | 13 ++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/base/ERC20Freezable.sol b/contracts/base/ERC20Freezable.sol index c45745de..414e13e5 100644 --- a/contracts/base/ERC20Freezable.sol +++ b/contracts/base/ERC20Freezable.sol @@ -75,12 +75,14 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { * @dev The token freezing must be approved by the `account` */ function freeze(address account, uint256 amount) external whenNotPaused onlyBlocklister { + if (account == address(0)) { + revert ZeroAddress(); + } if (!_freezeApprovals[account]) { revert FreezingNotApproved(); } emit Freeze(account, amount, _frozenBalances[account]); - emit FrozenBalanceUpdated(account, amount, _frozenBalances[account]); _frozenBalances[account] = amount; } @@ -106,7 +108,6 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { emit FreezeTransfer(from, amount); emit Freeze(from, newFrozenBalance, oldFrozenBalance); - emit FrozenBalanceUpdated(from, newFrozenBalance, oldFrozenBalance); _frozenBalances[from] = newFrozenBalance; _transfer(from, to, amount); @@ -116,6 +117,10 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { * @inheritdoc IERC20Freezable */ function freezeIncrease(address account, uint256 amount) external onlyBlocklister { + if (amount == 0) { + revert ZeroAmount(); + } + _freezeChange(account, amount, true); } @@ -123,6 +128,10 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { * @inheritdoc IERC20Freezable */ function freezeDecrease(address account, uint256 amount) external onlyBlocklister { + if (amount == 0) { + revert ZeroAmount(); + } + _freezeChange(account, amount, false); } @@ -147,7 +156,7 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { _frozenBalances[account] = newBalance; - emit FrozenBalanceUpdated(account, newBalance, oldBalance); + emit Freeze(account, newBalance, oldBalance); } /** diff --git a/contracts/base/interfaces/IERC20Freezable.sol b/contracts/base/interfaces/IERC20Freezable.sol index db486266..a53440b1 100644 --- a/contracts/base/interfaces/IERC20Freezable.sol +++ b/contracts/base/interfaces/IERC20Freezable.sol @@ -32,15 +32,6 @@ interface IERC20Freezable { */ event Freeze(address indexed account, uint256 newFrozenBalance, uint256 oldFrozenBalance); - /** - * @notice Emitted when the frozen balance is updated for an account - * - * @param account The account the frozen is updated for - * @param newBalance The new frozen balance - * @param oldBalance The old frozen balance - */ - event FrozenBalanceUpdated(address indexed account, uint256 newBalance, uint256 oldBalance); - /** * @notice Approves token freezing for the caller * @@ -72,7 +63,7 @@ interface IERC20Freezable { /** * @notice Increases the frozen balance for an account * - * Emits a {FrozenBalanceUpdated} event + * Emits a {Freeze} event * * @param account The account to increase frozen balance for * @param amount The amount to increase the frozen balance by @@ -82,7 +73,7 @@ interface IERC20Freezable { /** * @notice Decreases the frozen balance for an account * - * Emits a {FrozenBalanceUpdated} event + * Emits a {Freeze} event * * @param account The account to decrease frozen balance for * @param amount The amount to decrease the frozen balance by From 513b3c3ad37e73eb8bbcbc8e7af72721cbb67211 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Mon, 19 Aug 2024 10:43:01 +0300 Subject: [PATCH 06/13] feat: update freeze tests --- test/base/ERC20Freezable.test.ts | 33 +++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/test/base/ERC20Freezable.test.ts b/test/base/ERC20Freezable.test.ts index abb381d7..9b62a2c3 100644 --- a/test/base/ERC20Freezable.test.ts +++ b/test/base/ERC20Freezable.test.ts @@ -22,7 +22,6 @@ describe("Contract 'ERC20Freezable'", async () => { const EVENT_NAME_FREEZE = "Freeze"; const EVENT_NAME_FREEZE_APPROVAL = "FreezeApproval"; const EVENT_NAME_FREEZE_TRANSFER = "FreezeTransfer"; - const EVENT_NAME_FROZEN_UPDATED = "FrozenBalanceUpdated"; const REVERT_MESSAGE_INITIALIZABLE_CONTRACT_IS_ALREADY_INITIALIZED = "Initializable: contract is already initialized"; const REVERT_MESSAGE_INITIALIZABLE_CONTRACT_IS_NOT_INITIALIZING = "Initializable: contract is not initializing"; @@ -174,6 +173,14 @@ describe("Contract 'ERC20Freezable'", async () => { .to.be.revertedWithCustomError(token, REVERT_ERROR_UNAUTHORIZED_BLOCKLISTER) .withArgs(user1.address); }); + + it("Is reverted if the provided account is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, user1).approveFreezing()); + await expect( + connect(token, blocklister).freezeIncrease(ethers.ZeroAddress, 100) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); + }); }); describe("Function 'transferFrozen()'", async () => { @@ -329,12 +336,12 @@ describe("Contract 'ERC20Freezable'", async () => { expect(await token.balanceOfFrozen(user1.address)).to.eq(0); await expect(connect(token, blocklister).freezeIncrease(user1.address, 100)) - .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .to.emit(token, EVENT_NAME_FREEZE) .withArgs(user1.address, 100, 0); expect(await token.balanceOfFrozen(user1.address)).to.eq(100); await expect(connect(token, blocklister).freezeIncrease(user1.address, 100)) - .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .to.emit(token, EVENT_NAME_FREEZE) .withArgs(user1.address, 200, 100); expect(await token.balanceOfFrozen(user1.address)).to.eq(200); }); @@ -353,6 +360,14 @@ describe("Contract 'ERC20Freezable'", async () => { connect(token, blocklister).freezeIncrease(ethers.ZeroAddress, 100) ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); }); + + it("Is reverted if amount is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, user1).approveFreezing()); + await expect( + connect(token, blocklister).freezeIncrease(user1.address, 0) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); + }); }); describe("Function 'freezeDecrease()'", async () => { @@ -363,12 +378,12 @@ describe("Contract 'ERC20Freezable'", async () => { await proveTx(connect(token, blocklister).freezeIncrease(user1.address, 200)); await expect(connect(token, blocklister).freezeDecrease(user1.address, 100)) - .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .to.emit(token, EVENT_NAME_FREEZE) .withArgs(user1.address, 100, 200); expect(await token.balanceOfFrozen(user1.address)).to.eq(100); await expect(connect(token, blocklister).freezeDecrease(user1.address, 100)) - .to.emit(token, EVENT_NAME_FROZEN_UPDATED) + .to.emit(token, EVENT_NAME_FREEZE) .withArgs(user1.address, 0, 100); expect(await token.balanceOfFrozen(user1.address)).to.eq(0); }); @@ -396,5 +411,13 @@ describe("Contract 'ERC20Freezable'", async () => { connect(token, blocklister).freezeDecrease(user1.address, 200) ).to.be.revertedWithCustomError(token, REVERT_ERROR_LACK_OF_FROZEN_BALANCE); }); + + it("Is reverted if amount is zero", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, user1).approveFreezing()); + await expect( + connect(token, blocklister).freezeDecrease(user1.address, 0) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); + }); }); }); From 0cefa763332c303ca7a863919a2b6ddfccfe74b5 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Mon, 19 Aug 2024 10:46:24 +0300 Subject: [PATCH 07/13] feat: add comments --- contracts/base/ERC20Freezable.sol | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/contracts/base/ERC20Freezable.sol b/contracts/base/ERC20Freezable.sol index 414e13e5..bd175f3e 100644 --- a/contracts/base/ERC20Freezable.sol +++ b/contracts/base/ERC20Freezable.sol @@ -121,7 +121,11 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { revert ZeroAmount(); } - _freezeChange(account, amount, true); + _freezeChange( + account, + amount, + true // increasing + ); } /** @@ -132,7 +136,11 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { revert ZeroAmount(); } - _freezeChange(account, amount, false); + _freezeChange( + account, + amount, + false // decreasing + ); } function _freezeChange(address account, uint256 amount, bool increasing) internal onlyBlocklister { From 0b6570ef0f843f2907687affbf759bdda18efd25 Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Mon, 19 Aug 2024 13:01:24 +0300 Subject: [PATCH 08/13] feat: freeze refactoring --- contracts/base/ERC20Freezable.sol | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/contracts/base/ERC20Freezable.sol b/contracts/base/ERC20Freezable.sol index bd175f3e..28183448 100644 --- a/contracts/base/ERC20Freezable.sol +++ b/contracts/base/ERC20Freezable.sol @@ -116,11 +116,7 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { /** * @inheritdoc IERC20Freezable */ - function freezeIncrease(address account, uint256 amount) external onlyBlocklister { - if (amount == 0) { - revert ZeroAmount(); - } - + function freezeIncrease(address account, uint256 amount) external whenNotPaused onlyBlocklister { _freezeChange( account, amount, @@ -131,11 +127,7 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { /** * @inheritdoc IERC20Freezable */ - function freezeDecrease(address account, uint256 amount) external onlyBlocklister { - if (amount == 0) { - revert ZeroAmount(); - } - + function freezeDecrease(address account, uint256 amount) external whenNotPaused onlyBlocklister { _freezeChange( account, amount, @@ -143,23 +135,29 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { ); } - function _freezeChange(address account, uint256 amount, bool increasing) internal onlyBlocklister { + function _freezeChange(address account, uint256 amount, bool increasing) internal { if (account == address(0)) { revert ZeroAddress(); } + if (amount == 0) { + revert ZeroAmount(); + } if (!_freezeApprovals[account]) { revert FreezingNotApproved(); } uint256 oldBalance = _frozenBalances[account]; - uint256 newBalance; + uint256 newBalance = oldBalance; if (increasing) { - newBalance = oldBalance + amount; - } else if (!increasing && amount <= oldBalance) { - newBalance = oldBalance - amount; + newBalance += amount; } else { - revert LackOfFrozenBalance(); + if (amount > oldBalance) { + revert LackOfFrozenBalance(); + } + unchecked { + newBalance -= amount; + } } _frozenBalances[account] = newBalance; From a8470df967a79764e03f25c1ba3763b537c1029b Mon Sep 17 00:00:00 2001 From: ihoroleksiienko Date: Mon, 19 Aug 2024 13:01:39 +0300 Subject: [PATCH 09/13] feat: update tests --- test/base/ERC20Freezable.test.ts | 68 +++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/test/base/ERC20Freezable.test.ts b/test/base/ERC20Freezable.test.ts index 9b62a2c3..7cb3ef7e 100644 --- a/test/base/ERC20Freezable.test.ts +++ b/test/base/ERC20Freezable.test.ts @@ -151,14 +151,6 @@ describe("Contract 'ERC20Freezable'", async () => { expect(await token.balanceOfFrozen(user1.address)).to.eq(TOKEN_AMOUNT - 2); }); - it("Is reverted if freezing is not approved", async () => { - const { token } = await setUpFixture(deployAndConfigureToken); - expect(await token.freezeApproval(user1.address)).to.eq(false); - await expect( - connect(token, blocklister).freeze(user1.address, TOKEN_AMOUNT) - ).to.be.revertedWithCustomError(token, REVERT_ERROR_FREEZING_NOT_APPROVED); - }); - it("Is reverted if contract is paused", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await proveTx(connect(token, pauser).pause()); @@ -178,9 +170,17 @@ describe("Contract 'ERC20Freezable'", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await proveTx(connect(token, user1).approveFreezing()); await expect( - connect(token, blocklister).freezeIncrease(ethers.ZeroAddress, 100) + connect(token, blocklister).freeze(ethers.ZeroAddress, 100) ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); }); + + it("Is reverted if freezing is not approved", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + expect(await token.freezeApproval(user1.address)).to.eq(false); + await expect( + connect(token, blocklister).freeze(user1.address, TOKEN_AMOUNT) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_FREEZING_NOT_APPROVED); + }); }); describe("Function 'transferFrozen()'", async () => { @@ -346,6 +346,14 @@ describe("Contract 'ERC20Freezable'", async () => { expect(await token.balanceOfFrozen(user1.address)).to.eq(200); }); + it("Is reverted if contract is paused", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, pauser).pause()); + await expect( + connect(token, blocklister).freezeIncrease(user1.address, TOKEN_AMOUNT) + ).to.be.revertedWith(REVERT_MESSAGE_PAUSABLE_PAUSED); + }); + it("Is reverted if the caller is not a blocklister", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await expect( @@ -361,13 +369,21 @@ describe("Contract 'ERC20Freezable'", async () => { ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); }); - it("Is reverted if amount is zero", async () => { + it("Is reverted if the provided amount is zero", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await proveTx(connect(token, user1).approveFreezing()); await expect( connect(token, blocklister).freezeIncrease(user1.address, 0) ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); }); + + it("Is reverted if freezing is not approved", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + expect(await token.freezeApproval(user1.address)).to.eq(false); + await expect( + connect(token, blocklister).freezeIncrease(user1.address, TOKEN_AMOUNT) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_FREEZING_NOT_APPROVED); + }); }); describe("Function 'freezeDecrease()'", async () => { @@ -388,6 +404,14 @@ describe("Contract 'ERC20Freezable'", async () => { expect(await token.balanceOfFrozen(user1.address)).to.eq(0); }); + it("Is reverted if contract is paused", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, pauser).pause()); + await expect( + connect(token, blocklister).freezeDecrease(user1.address, TOKEN_AMOUNT) + ).to.be.revertedWith(REVERT_MESSAGE_PAUSABLE_PAUSED); + }); + it("Is reverted if the caller is not a blocklister", async () => { const { token } = await setUpFixture(deployAndConfigureToken); await expect( @@ -402,22 +426,30 @@ describe("Contract 'ERC20Freezable'", async () => { ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_ADDRESS); }); - it("Is reverted if the provided amount is greater then old balance", async () => { + it("Is reverted if the provided amount is zero", async () => { const { token } = await setUpFixture(deployAndConfigureToken); - await proveTx(connect(token, user1).approveFreezing()); - await proveTx(connect(token, blocklister).freezeIncrease(user1.address, 100)); await expect( - connect(token, blocklister).freezeDecrease(user1.address, 200) - ).to.be.revertedWithCustomError(token, REVERT_ERROR_LACK_OF_FROZEN_BALANCE); + connect(token, blocklister).freezeDecrease(user1.address, 0) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); }); - it("Is reverted if amount is zero", async () => { + it("Is reverted if freezing is not approved", async () => { + const { token } = await setUpFixture(deployAndConfigureToken); + expect(await token.freezeApproval(user1.address)).to.eq(false); + await expect( + connect(token, blocklister).freezeDecrease(user1.address, TOKEN_AMOUNT) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_FREEZING_NOT_APPROVED); + }); + + it("Is reverted if the provided amount is greater then old balance", async () => { const { token } = await setUpFixture(deployAndConfigureToken); + await proveTx(connect(token, user1).approveFreezing()); + await proveTx(connect(token, blocklister).freezeIncrease(user1.address, 100)); await expect( - connect(token, blocklister).freezeDecrease(user1.address, 0) - ).to.be.revertedWithCustomError(token, REVERT_ERROR_ZERO_AMOUNT); + connect(token, blocklister).freezeDecrease(user1.address, 200) + ).to.be.revertedWithCustomError(token, REVERT_ERROR_LACK_OF_FROZEN_BALANCE); }); }); }); From d2f702425ce7922ce7f5ca4ab392227b60aeaa37 Mon Sep 17 00:00:00 2001 From: Evgenii Zaitsev Date: Mon, 19 Aug 2024 21:13:40 +0700 Subject: [PATCH 10/13] feat: mark the "freeze()" function deprecated, improve comments --- contracts/base/ERC20Freezable.sol | 76 +++++++++++++------ contracts/base/interfaces/IERC20Freezable.sol | 10 --- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/contracts/base/ERC20Freezable.sol b/contracts/base/ERC20Freezable.sol index 28183448..8a750815 100644 --- a/contracts/base/ERC20Freezable.sol +++ b/contracts/base/ERC20Freezable.sol @@ -68,11 +68,22 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { } /** - * @inheritdoc IERC20Freezable + * @dev [DEPRECATED] Freezes tokens of the specified account * - * @dev The contract must not be paused - * @dev Can only be called by the blocklister account - * @dev The token freezing must be approved by the `account` + * Emits a {Freeze} event + * + * IMPORTANT: This function is deprecated and will be removed in the future updates of the contract. + * Use the {freezeIncrease} and {freezeDecrease} functions instead. + * + * Requirements: + * + * - The contract must not be paused + * - Can only be called by the blocklister account + * - The account address must not be zero + * - The token freezing must be approved by the `account` + * + * @param account The account whose tokens will be frozen + * @param amount The amount of tokens to freeze */ function freeze(address account, uint256 amount) external whenNotPaused onlyBlocklister { if (account == address(0)) { @@ -115,6 +126,12 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { /** * @inheritdoc IERC20Freezable + * + * @dev The contract must not be paused + * @dev Can only be called by the blocklister account + * @dev The account address must not be zero + * @dev The amount must not be zero + * @dev The token freezing must be approved by the `account` */ function freezeIncrease(address account, uint256 amount) external whenNotPaused onlyBlocklister { _freezeChange( @@ -126,6 +143,12 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { /** * @inheritdoc IERC20Freezable + * + * @dev The contract must not be paused + * @dev Can only be called by the blocklister account + * @dev The account address must not be zero + * @dev The amount must not be zero + * @dev The token freezing must be approved by the `account` */ function freezeDecrease(address account, uint256 amount) external whenNotPaused onlyBlocklister { _freezeChange( @@ -135,6 +158,30 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { ); } + /** + * @inheritdoc IERC20Freezable + */ + function freezeApproval(address account) external view returns (bool) { + return _freezeApprovals[account]; + } + + /** + * @inheritdoc IERC20Freezable + */ + function balanceOfFrozen(address account) public view returns (uint256) { + return _frozenBalances[account]; + } + + /** + * @dev [DEPRECATED] Keep this function for backward compatibility + */ + function frozenBalance(address account) public view returns (uint256) { + return balanceOfFrozen(account); + } + + /** + * @dev Changes the frozen balance internally + */ function _freezeChange(address account, uint256 amount, bool increasing) internal { if (account == address(0)) { revert ZeroAddress(); @@ -165,27 +212,6 @@ abstract contract ERC20Freezable is ERC20Base, IERC20Freezable { emit Freeze(account, newBalance, oldBalance); } - /** - * @inheritdoc IERC20Freezable - */ - function freezeApproval(address account) external view returns (bool) { - return _freezeApprovals[account]; - } - - /** - * @inheritdoc IERC20Freezable - */ - function balanceOfFrozen(address account) public view returns (uint256) { - return _frozenBalances[account]; - } - - /** - * @dev [DEPRECATED] Keep this function for backward compatibility - */ - function frozenBalance(address account) public view returns (uint256) { - return balanceOfFrozen(account); - } - /** * @dev This empty reserved space is put in place to allow future versions * to add new variables without shifting down storage in the inheritance chain diff --git a/contracts/base/interfaces/IERC20Freezable.sol b/contracts/base/interfaces/IERC20Freezable.sol index a53440b1..2d9e7c0b 100644 --- a/contracts/base/interfaces/IERC20Freezable.sol +++ b/contracts/base/interfaces/IERC20Freezable.sol @@ -39,16 +39,6 @@ interface IERC20Freezable { */ function approveFreezing() external; - /** - * @notice Freezes tokens of the specified account - * - * Emits a {Freeze} event - * - * @param account The account whose tokens will be frozen - * @param amount The amount of tokens to freeze - */ - function freeze(address account, uint256 amount) external; - /** * @notice Transfers frozen tokens on behalf of an account * From 7458fa9ac557f3bec2ec3508d48b552bb11091e4 Mon Sep 17 00:00:00 2001 From: Evgenii Zaitsev Date: Mon, 19 Aug 2024 21:14:10 +0700 Subject: [PATCH 11/13] chore: update helper scripts --- scripts/deployProxy.ts | 4 ++-- scripts/prepareUpgrade.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/deployProxy.ts b/scripts/deployProxy.ts index 7dd811cd..ab3cd6fa 100644 --- a/scripts/deployProxy.ts +++ b/scripts/deployProxy.ts @@ -6,9 +6,9 @@ async function main() { const factory = await ethers.getContractFactory(CONTRACT_NAME); const proxy = await upgrades.deployProxy(factory); - await proxy.deployed(); + await proxy.waitForDeployment(); - console.log("Proxy deployed to:", proxy.address); + console.log("Proxy deployed to:", await proxy.getAddress()); } main().then().catch(err => { diff --git a/scripts/prepareUpgrade.ts b/scripts/prepareUpgrade.ts index 81547db6..7364b891 100644 --- a/scripts/prepareUpgrade.ts +++ b/scripts/prepareUpgrade.ts @@ -9,9 +9,9 @@ async function main() { // unsafeSkipStorageCheck: true const factory = await ethers.getContractFactory(CONTRACT_NAME); - await upgrades.prepareUpgrade(PROXY_ADDRESS, factory); + const response = await upgrades.prepareUpgrade(PROXY_ADDRESS, factory); - console.log("Upgrade prepared"); + console.log("Upgrade prepared:", response); } main().then().catch(err => { From 97e4d3fb02796df6fe7f8c27bcb95393fb8a30a2 Mon Sep 17 00:00:00 2001 From: Evgenii Zaitsev Date: Mon, 19 Aug 2024 21:55:31 +0700 Subject: [PATCH 12/13] build: upgrade `BRLCToken` and `USJimToken` contracts in Testnet --- .openzeppelin/unknown-2008.json | 726 ++++++++++++++++++++++++++++++++ 1 file changed, 726 insertions(+) diff --git a/.openzeppelin/unknown-2008.json b/.openzeppelin/unknown-2008.json index ca478f06..b9cb77df 100644 --- a/.openzeppelin/unknown-2008.json +++ b/.openzeppelin/unknown-2008.json @@ -10347,6 +10347,732 @@ }, "namespaces": {} } + }, + "2eacf3c019b3e831b0fbca735cbafb968650b857a34f5bec1c6d283c79e810f3": { + "address": "0xf977cED9f20C722246E5FC3214076EACf6f68fB3", + "txHash": "0x99dcfa176de8bdd749578bfbc43ee248138d542bcf6fbee125a592b6ee0fa31a", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_rescuer", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "RescuableUpgradeable", + "src": "contracts/base/common/RescuableUpgradeable.sol:20" + }, + { + "label": "_paused", + "offset": 20, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_pauser", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "PausableExtUpgradeable", + "src": "contracts/base/common/PausableExtUpgradeable.sol:17" + }, + { + "label": "_mainBlocklister", + "offset": 0, + "slot": "152", + "type": "t_address", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:28" + }, + { + "label": "_blocklisted", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_bool)", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "156", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "157", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "158", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "159", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "_mainMinter", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:40" + }, + { + "label": "_minters", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:43" + }, + { + "label": "_mintersAllowance", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:46" + }, + { + "label": "_freezeApprovals", + "offset": 0, + "slot": "207", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:15" + }, + { + "label": "_frozenBalances", + "offset": 0, + "slot": "208", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:18" + }, + { + "label": "__gap", + "offset": 0, + "slot": "209", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:219" + }, + { + "label": "_purposeAssignments", + "offset": 0, + "slot": "257", + "type": "t_mapping(t_address,t_array(t_bytes32)dyn_storage)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:15" + }, + { + "label": "_totalRestrictedBalances", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:18" + }, + { + "label": "_restrictedPurposeBalances", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:21" + }, + { + "label": "__gap", + "offset": 0, + "slot": "260", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:174" + }, + { + "label": "_beforeTokenTransferHooks", + "offset": 0, + "slot": "307", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:16" + }, + { + "label": "_afterTokenTransferHooks", + "offset": 0, + "slot": "308", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:19" + }, + { + "label": "_trusted", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:15" + }, + { + "label": "__gap", + "offset": 0, + "slot": "310", + "type": "t_array(t_uint256)49_storage", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:85" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(Hook)6537_storage)dyn_storage": { + "label": "struct IERC20Hookable.Hook[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(ErrorHandlingPolicy)6528": { + "label": "enum IERC20Hookable.ErrorHandlingPolicy", + "members": [ + "Revert", + "Event" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_bytes32)dyn_storage)": { + "label": "mapping(address => bytes32[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": { + "label": "mapping(address => mapping(bytes32 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Hook)6537_storage": { + "label": "struct IERC20Hookable.Hook", + "members": [ + { + "label": "account", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "policy", + "type": "t_enum(ErrorHandlingPolicy)6528", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "d8a288ac7cf5220b93aef80d55e69372169e5cc7d8a5190d9d5f387b70cb27ed": { + "address": "0x0270c0915f4b951bB4EdCFd9b62F8F4897278711", + "txHash": "0x8b6df13c2b56bce77d6cceb0568d7d28a85f7bb4d7ffb91aa13f15fd91f19f88", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_rescuer", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "RescuableUpgradeable", + "src": "contracts/base/common/RescuableUpgradeable.sol:20" + }, + { + "label": "_paused", + "offset": 20, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_pauser", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "PausableExtUpgradeable", + "src": "contracts/base/common/PausableExtUpgradeable.sol:17" + }, + { + "label": "_mainBlocklister", + "offset": 0, + "slot": "152", + "type": "t_address", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:28" + }, + { + "label": "_blocklisted", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_bool)", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "156", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "157", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "158", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "159", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "_mainMinter", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:40" + }, + { + "label": "_minters", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:43" + }, + { + "label": "_mintersAllowance", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:46" + }, + { + "label": "_freezeApprovals", + "offset": 0, + "slot": "207", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:15" + }, + { + "label": "_frozenBalances", + "offset": 0, + "slot": "208", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:18" + }, + { + "label": "__gap", + "offset": 0, + "slot": "209", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:219" + }, + { + "label": "_purposeAssignments", + "offset": 0, + "slot": "257", + "type": "t_mapping(t_address,t_array(t_bytes32)dyn_storage)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:15" + }, + { + "label": "_totalRestrictedBalances", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:18" + }, + { + "label": "_restrictedPurposeBalances", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:21" + }, + { + "label": "__gap", + "offset": 0, + "slot": "260", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:174" + }, + { + "label": "_beforeTokenTransferHooks", + "offset": 0, + "slot": "307", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:16" + }, + { + "label": "_afterTokenTransferHooks", + "offset": 0, + "slot": "308", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:19" + }, + { + "label": "_trusted", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:15" + }, + { + "label": "__gap", + "offset": 0, + "slot": "310", + "type": "t_array(t_uint256)49_storage", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:85" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(Hook)6537_storage)dyn_storage": { + "label": "struct IERC20Hookable.Hook[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(ErrorHandlingPolicy)6528": { + "label": "enum IERC20Hookable.ErrorHandlingPolicy", + "members": [ + "Revert", + "Event" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_bytes32)dyn_storage)": { + "label": "mapping(address => bytes32[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": { + "label": "mapping(address => mapping(bytes32 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Hook)6537_storage": { + "label": "struct IERC20Hookable.Hook", + "members": [ + { + "label": "account", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "policy", + "type": "t_enum(ErrorHandlingPolicy)6528", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } From 7bf0932f91c63ce389acef4f321794210f0763d8 Mon Sep 17 00:00:00 2001 From: Evgenii Zaitsev Date: Mon, 19 Aug 2024 21:56:57 +0700 Subject: [PATCH 13/13] build: prepare upgrade of `BRLCToken` and `USJimToken` in Mainnet --- .openzeppelin/unknown-2009.json | 726 ++++++++++++++++++++++++++++++++ 1 file changed, 726 insertions(+) diff --git a/.openzeppelin/unknown-2009.json b/.openzeppelin/unknown-2009.json index 033b4ca1..bfc9fe74 100644 --- a/.openzeppelin/unknown-2009.json +++ b/.openzeppelin/unknown-2009.json @@ -9789,6 +9789,732 @@ }, "namespaces": {} } + }, + "2eacf3c019b3e831b0fbca735cbafb968650b857a34f5bec1c6d283c79e810f3": { + "address": "0x0112B7a3Ec91d1225B0A06F3CDb897CbDA6d73F2", + "txHash": "0x9b936a9031f16093e273032786844a5bb4e2b4773d652d27fd6da56397d8a9a2", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_rescuer", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "RescuableUpgradeable", + "src": "contracts/base/common/RescuableUpgradeable.sol:20" + }, + { + "label": "_paused", + "offset": 20, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_pauser", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "PausableExtUpgradeable", + "src": "contracts/base/common/PausableExtUpgradeable.sol:17" + }, + { + "label": "_mainBlocklister", + "offset": 0, + "slot": "152", + "type": "t_address", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:28" + }, + { + "label": "_blocklisted", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_bool)", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "156", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "157", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "158", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "159", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "_mainMinter", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:40" + }, + { + "label": "_minters", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:43" + }, + { + "label": "_mintersAllowance", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:46" + }, + { + "label": "_freezeApprovals", + "offset": 0, + "slot": "207", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:15" + }, + { + "label": "_frozenBalances", + "offset": 0, + "slot": "208", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:18" + }, + { + "label": "__gap", + "offset": 0, + "slot": "209", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:219" + }, + { + "label": "_purposeAssignments", + "offset": 0, + "slot": "257", + "type": "t_mapping(t_address,t_array(t_bytes32)dyn_storage)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:15" + }, + { + "label": "_totalRestrictedBalances", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:18" + }, + { + "label": "_restrictedPurposeBalances", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:21" + }, + { + "label": "__gap", + "offset": 0, + "slot": "260", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:174" + }, + { + "label": "_beforeTokenTransferHooks", + "offset": 0, + "slot": "307", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:16" + }, + { + "label": "_afterTokenTransferHooks", + "offset": 0, + "slot": "308", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:19" + }, + { + "label": "_trusted", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:15" + }, + { + "label": "__gap", + "offset": 0, + "slot": "310", + "type": "t_array(t_uint256)49_storage", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:85" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(Hook)6537_storage)dyn_storage": { + "label": "struct IERC20Hookable.Hook[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(ErrorHandlingPolicy)6528": { + "label": "enum IERC20Hookable.ErrorHandlingPolicy", + "members": [ + "Revert", + "Event" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_bytes32)dyn_storage)": { + "label": "mapping(address => bytes32[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": { + "label": "mapping(address => mapping(bytes32 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Hook)6537_storage": { + "label": "struct IERC20Hookable.Hook", + "members": [ + { + "label": "account", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "policy", + "type": "t_enum(ErrorHandlingPolicy)6528", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "d8a288ac7cf5220b93aef80d55e69372169e5cc7d8a5190d9d5f387b70cb27ed": { + "address": "0x374BBcc9bdC80f4eb0773176CaE455B4029d00EC", + "txHash": "0xdd21961a46d11435d4a5343261c8d3a7dae0fef9da0f8972ed80c9e9e09fbf12", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_rescuer", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "RescuableUpgradeable", + "src": "contracts/base/common/RescuableUpgradeable.sol:20" + }, + { + "label": "_paused", + "offset": 20, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "_pauser", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "PausableExtUpgradeable", + "src": "contracts/base/common/PausableExtUpgradeable.sol:17" + }, + { + "label": "_mainBlocklister", + "offset": 0, + "slot": "152", + "type": "t_address", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:28" + }, + { + "label": "_blocklisted", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_bool)", + "contract": "BlocklistableUpgradeable", + "src": "contracts/base/common/BlocklistableUpgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "156", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "157", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "158", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "159", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "_mainMinter", + "offset": 0, + "slot": "204", + "type": "t_address", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:40" + }, + { + "label": "_minters", + "offset": 0, + "slot": "205", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:43" + }, + { + "label": "_mintersAllowance", + "offset": 0, + "slot": "206", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Mintable", + "src": "contracts/base/ERC20Mintable.sol:46" + }, + { + "label": "_freezeApprovals", + "offset": 0, + "slot": "207", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:15" + }, + { + "label": "_frozenBalances", + "offset": 0, + "slot": "208", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:18" + }, + { + "label": "__gap", + "offset": 0, + "slot": "209", + "type": "t_array(t_uint256)48_storage", + "contract": "ERC20Freezable", + "src": "contracts/base/ERC20Freezable.sol:219" + }, + { + "label": "_purposeAssignments", + "offset": 0, + "slot": "257", + "type": "t_mapping(t_address,t_array(t_bytes32)dyn_storage)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:15" + }, + { + "label": "_totalRestrictedBalances", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:18" + }, + { + "label": "_restrictedPurposeBalances", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:21" + }, + { + "label": "__gap", + "offset": 0, + "slot": "260", + "type": "t_array(t_uint256)47_storage", + "contract": "ERC20Restrictable", + "src": "contracts/base/ERC20Restrictable.sol:174" + }, + { + "label": "_beforeTokenTransferHooks", + "offset": 0, + "slot": "307", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:16" + }, + { + "label": "_afterTokenTransferHooks", + "offset": 0, + "slot": "308", + "type": "t_array(t_struct(Hook)6537_storage)dyn_storage", + "contract": "ERC20Hookable", + "src": "contracts/base/ERC20Hookable.sol:19" + }, + { + "label": "_trusted", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:15" + }, + { + "label": "__gap", + "offset": 0, + "slot": "310", + "type": "t_array(t_uint256)49_storage", + "contract": "ERC20Trustable", + "src": "contracts/base/ERC20Trustable.sol:85" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(Hook)6537_storage)dyn_storage": { + "label": "struct IERC20Hookable.Hook[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(ErrorHandlingPolicy)6528": { + "label": "enum IERC20Hookable.ErrorHandlingPolicy", + "members": [ + "Revert", + "Event" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_bytes32)dyn_storage)": { + "label": "mapping(address => bytes32[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": { + "label": "mapping(address => mapping(bytes32 => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Hook)6537_storage": { + "label": "struct IERC20Hookable.Hook", + "members": [ + { + "label": "account", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "policy", + "type": "t_enum(ErrorHandlingPolicy)6528", + "offset": 20, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } }