Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monerium #132

Closed
wants to merge 89 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
9c87a5b
add monerium accounts
CJentzsch Mar 18, 2023
e2fd21c
Prettified Code!
CJentzsch Mar 18, 2023
9281aa0
add monerium accounts - add comment
CJentzsch Mar 18, 2023
74f950a
Merge branch 'monerium' of github.com:corpus-ventures/tokenize.it-sma…
CJentzsch Mar 18, 2023
5db9103
adopt continuous fundraising to monerium accounts
CJentzsch Mar 18, 2023
74f7541
Prettified Code!
CJentzsch Mar 18, 2023
21f6a3d
add mainnet definition and token info
malteish Apr 4, 2023
d1e0606
fix test
malteish May 2, 2023
b72683c
natSpec for Token
malteish May 2, 2023
b226334
natSpec for ContinuousFundraising
malteish May 2, 2023
d7f2b90
natSpec for PersonalInvite
malteish May 2, 2023
1c154d0
more natSpec for PersonalInvite
malteish May 2, 2023
ff9e6b1
natSpec for PersonalInviteFactory
malteish May 2, 2023
cb09cc9
natSpec for AllowList
malteish May 3, 2023
6a6ed64
natSpec for FeeSettings
malteish May 3, 2023
4f890a5
more natSpec
malteish May 3, 2023
5734259
typo
malteish May 3, 2023
b98ace8
refactor ERC20 helper
malteish May 3, 2023
999bf3c
test permit for EUROC
malteish May 3, 2023
bb045f2
Prettified Code!
malteish May 3, 2023
205c849
test USDC
malteish May 3, 2023
29f8580
Prettified Code!
malteish May 3, 2023
70d8a0e
add permit for DAI
malteish May 3, 2023
5153174
Prettified Code!
malteish May 3, 2023
9eb2804
cleanup
malteish May 3, 2023
4a6ba47
add basic test for VestingWallet
malteish May 5, 2023
6a43484
add test of timeLock with PersonalInvite
malteish May 5, 2023
55222dc
fix test
malteish May 5, 2023
f6435c4
remove workspace file
malteish May 5, 2023
ac75bec
Bump @openzeppelin/contracts from 4.8.0 to 4.8.3
dependabot[bot] May 8, 2023
fa2dcf5
Bump cookiejar from 2.1.3 to 2.1.4
dependabot[bot] May 8, 2023
09744db
Bump decode-uri-component from 0.2.0 to 0.2.2
dependabot[bot] May 8, 2023
237dca0
test AllowList Events
malteish May 8, 2023
8d7e7cd
test ContinuousFundraising events
malteish May 8, 2023
582bce7
test FeeSettings events
malteish May 8, 2023
a7cf9bf
test PersonalInvite event
malteish May 8, 2023
18d05d7
test PersonalInviteFactory events
malteish May 8, 2023
f4c2b1e
test various salts
malteish May 8, 2023
2534474
test Token events
malteish May 8, 2023
05ee2e7
Merge branch 'develop' into dependabot/npm_and_yarn/decode-uri-compon…
malteish May 8, 2023
6530286
Merge branch 'develop' into dependabot/npm_and_yarn/cookiejar-2.1.4
malteish May 8, 2023
cca9349
Merge branch 'develop' into dependabot/npm_and_yarn/openzeppelin/cont…
malteish May 8, 2023
f7dbd1e
Merge pull request #146 from corpus-io/dependabot/npm_and_yarn/decode…
malteish May 8, 2023
a55a2b9
Merge pull request #145 from corpus-io/dependabot/npm_and_yarn/cookie…
malteish May 8, 2023
e652afb
Merge pull request #139 from corpus-io/feature/extendNatSpec
malteish May 8, 2023
1959ade
Merge pull request #142 from corpus-io/feature/demoTestPermit
malteish May 8, 2023
e49f9ba
Merge pull request #143 from corpus-io/feature/timelock
malteish May 8, 2023
eefe2f6
Merge pull request #144 from corpus-io/dependabot/npm_and_yarn/openze…
malteish May 8, 2023
1309c8c
Merge pull request #147 from corpus-io/feature/testEvents
malteish May 8, 2023
4777c9f
bump prettier solidity version
malteish May 8, 2023
8692951
run prettier
malteish May 8, 2023
b69815a
change prettier config, reformat all files
malteish May 8, 2023
368fbd6
Prettified Code!
malteish May 8, 2023
cb721e5
replace literal uint256max
malteish May 8, 2023
f111ca9
Merge pull request #149 from corpus-io/feature/bumpPrettier
malteish May 8, 2023
74a0a6b
add factory and first test
malteish May 17, 2023
38c9051
Prettified Code!
malteish May 17, 2023
72f5dbb
add test
malteish May 17, 2023
57434a3
improve comments
malteish May 17, 2023
42709bd
update timelock demo test to use factory
malteish May 17, 2023
26a6c00
fix test
malteish May 17, 2023
ee080d3
4.1.0-alpha.0
malteish May 19, 2023
12341a5
update npm publishing documentation
malteish May 19, 2023
7045078
add vesting wallet constructor arguments file
malteish May 24, 2023
08e956d
Merge pull request #151 from corpus-io/feature/VestingWalletFactory
malteish May 25, 2023
89de309
Merge pull request #152 from corpus-io/feature/docsNpmPublishing
malteish May 25, 2023
3359a0f
add vestingWallet deployment info and script
malteish Jun 1, 2023
c55f6f4
check for requirements == 0
malteish Jun 6, 2023
8e542ad
Mintallower can mint without minting allowance
malteish Jun 7, 2023
1292982
fix tests
malteish Jun 7, 2023
caacc8b
fix test
malteish Jun 7, 2023
9b30e5e
fix test
malteish Jun 7, 2023
d278826
fix test for mainnet execution, auto-execute
malteish Jun 7, 2023
c83dea5
fix secret definition
malteish Jun 7, 2023
092bb2f
Merge pull request #157 from corpus-io/feature/deployVestingWalletFac…
malteish Jun 16, 2023
be4d9d2
Merge pull request #156 from corpus-io/feature/automateMainnetTesting
malteish Jun 16, 2023
ce6a931
Merge pull request #155 from corpus-io/feature/mintallowerNeedsNoAllo…
malteish Jun 16, 2023
cf4267d
Merge pull request #154 from corpus-io/feature/reduceGasForTransfer
malteish Jun 16, 2023
3abe8c0
bump openzeppelin to 4.9.1
malteish Jun 16, 2023
530df5a
add test that does not work with yul
malteish Jun 27, 2023
016aa65
fix first test for yul pipeline
malteish Jun 28, 2023
b9875af
update tests to work with yul
malteish Jun 28, 2023
5922585
Merge pull request #161 from corpus-io/feature/bumpOpenzeppelinVersion
malteish Jul 7, 2023
1910bb6
update hh config to use yul pipeline
malteish Jul 7, 2023
9600dbb
Merge pull request #167 from corpus-io/feature/useYulOptimizer
malteish Jul 12, 2023
e32ea06
pin prettier version because of breaking changes
malteish Aug 2, 2023
cd680c7
Merge pull request #172 from corpus-io/feature/fixPrettierAction
malteish Aug 2, 2023
2f0c24e
Merge branch 'develop' into monerium
malteish Aug 11, 2023
8e00ddf
Prettified Code!
malteish Aug 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@ jobs:
with:
version: nightly

- name: Run tests
- name: Run local tests
working-directory: .
run: yarn test && forge coverage --no-match-test Mainnet --report lcov
- name: Coverage
uses: VeryGoodOpenSource/very_good_coverage@v2
with:
path: "./lcov.info"
path: './lcov.info'
min_coverage: 95
exclude: "test/* test/resources/* archive/* script/*"
exclude: 'test/* test/resources/* archive/* script/*'
- name: Run snapshot
working-directory: .
run: forge snapshot --no-match-test Mainnet
- name: Run mainnet tests
working-directory: .
run: forge test --match-test Mainnet --fork-url ${{ secrets.MAINNET_RPC_URL }}
3 changes: 2 additions & 1 deletion .github/workflows/prettier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
- main
workflow_dispatch:
branches:
- "**"
- '**'

name: prettier

Expand All @@ -25,3 +25,4 @@ jobs:
# This part is also where you can pass other options, for example:
prettier_options: --write **/*.{sol,md,js}
prettier_plugins: prettier-plugin-solidity
prettier_version: 2.8.8
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ broadcast/
!.env.example
.npmignore
.VSCodeCounter/
*.code-workspace
35 changes: 6 additions & 29 deletions archive/PersonalInviteOld.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,9 @@ contract PersonalInviteOld is ERC2771Context, Ownable, ReentrancyGuard {

require(_buyer != address(0), "_buyer can not be zero address");
require(_receiver != address(0), "_receiver can not be zero address");
require(
_minAmount <= _maxAmount,
"_minAmount needs to be smaller or equal to _maxAmount"
);
require(_minAmount <= _maxAmount, "_minAmount needs to be smaller or equal to _maxAmount");
require(_tokenPrice != 0, "_tokenPrice can not be zero");
require(
_expiration > block.timestamp,
"Expiration date needs to be in the future"
);
require(_expiration > block.timestamp, "Expiration date needs to be in the future");

// after creating the contract, it needs to be set up as minter
}
Expand All @@ -88,10 +82,7 @@ contract PersonalInviteOld is ERC2771Context, Ownable, ReentrancyGuard {
@param _tokenAmount Amount of tokens to buy, bits (bit = smallest subunit of token). [tok_bits]
*/
function deal(uint _tokenAmount) public nonReentrant {
require(
buyer == _msgSender(),
"Only the personally invited buyer can take this deal"
);
require(buyer == _msgSender(), "Only the personally invited buyer can take this deal");
require(
minAmount <= _tokenAmount && _tokenAmount <= maxAmount,
"Amount needs to be inbetween minAmount and maxAmount"
Expand All @@ -112,11 +103,7 @@ contract PersonalInviteOld is ERC2771Context, Ownable, ReentrancyGuard {
(_tokenAmount * tokenPrice) % (10 ** token.decimals()) == 0,
"Amount * tokenprice needs to be a multiple of 10**token.decimals()"
);
currency.safeTransferFrom(
buyer,
receiver,
(_tokenAmount * tokenPrice) / (10 ** token.decimals())
);
currency.safeTransferFrom(buyer, receiver, (_tokenAmount * tokenPrice) / (10 ** token.decimals()));
require(token.mint(buyer, _tokenAmount), "Minting new tokens failed");

emit Deal(buyer, _tokenAmount, tokenPrice, currency, token);
Expand All @@ -138,24 +125,14 @@ contract PersonalInviteOld is ERC2771Context, Ownable, ReentrancyGuard {
/**
* @dev both Ownable and ERC2771Context have a _msgSender() function, so we need to override and select which one to use.
*/
function _msgSender()
internal
view
override(Context, ERC2771Context)
returns (address)
{
function _msgSender() internal view override(Context, ERC2771Context) returns (address) {
return ERC2771Context._msgSender();
}

/**
* @dev both Ownable and ERC2771Context have a _msgData() function, so we need to override and select which one to use.
*/
function _msgData()
internal
view
override(Context, ERC2771Context)
returns (bytes calldata)
{
function _msgData() internal view override(Context, ERC2771Context) returns (bytes calldata) {
return ERC2771Context._msgData();
}

Expand Down
93 changes: 21 additions & 72 deletions archive/PersonalInviteOld.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,16 @@ contract PersonalInviteOldOldTest is Test {
CorpusToken currency; // todo: add different ERC20 token as currency!
PersonalInviteOld invite;

uint256 MAX_INT =
115792089237316195423570985008687907853269984665640564039457584007913129639935;
uint256 MAX_INT = 115792089237316195423570985008687907853269984665640564039457584007913129639935;

address public constant admin = 0x0109709eCFa91a80626FF3989D68f67f5b1dD120;
address public constant buyer = 0x1109709ecFA91a80626ff3989D68f67F5B1Dd121;
address public constant minterAdmin =
0x2109709EcFa91a80626Ff3989d68F67F5B1Dd122;
address public constant minterAdmin = 0x2109709EcFa91a80626Ff3989d68F67F5B1Dd122;
address public constant minter = 0x3109709ECfA91A80626fF3989D68f67F5B1Dd123;
address public constant owner = 0x6109709EcFA91A80626FF3989d68f67F5b1dd126;
address public constant receiver =
0x7109709eCfa91A80626Ff3989D68f67f5b1dD127;
address public constant paymentTokenProvider =
0x8109709ecfa91a80626fF3989d68f67F5B1dD128;
address public constant trustedForwarder =
0x9109709EcFA91A80626FF3989D68f67F5B1dD129;
address public constant receiver = 0x7109709eCfa91A80626Ff3989D68f67f5b1dD127;
address public constant paymentTokenProvider = 0x8109709ecfa91a80626fF3989d68f67F5B1dD128;
address public constant trustedForwarder = 0x9109709EcFA91A80626FF3989D68f67F5B1dD129;

uint256 public constant price = 10000000;

Expand Down Expand Up @@ -101,66 +96,43 @@ contract PersonalInviteOldOldTest is Test {
assertTrue(currency.balanceOf(buyer) == 10000000000);
vm.prank(buyer);
invite.deal(100);
assertTrue(
currency.balanceOf(buyer) ==
10000000000 - (100 * 10000000) / (10 ** token.decimals())
);
assertTrue(currency.balanceOf(buyer) == 10000000000 - (100 * 10000000) / (10 ** token.decimals()));
assertTrue(token.balanceOf(buyer) == 100);
assertTrue(
currency.balanceOf(receiver) ==
(100 * 10000000) / (10 ** token.decimals())
);
assertTrue(currency.balanceOf(receiver) == (100 * 10000000) / (10 ** token.decimals()));
}

function testDealHappyCase2() public {
assertTrue(currency.balanceOf(buyer) == 10000000000);
vm.prank(buyer);
invite.deal(100000000000000);
assertTrue(
currency.balanceOf(buyer) ==
10000000000 -
(100000000000000 * 10000000) /
(10 ** token.decimals())
);
assertTrue(currency.balanceOf(buyer) == 10000000000 - (100000000000000 * 10000000) / (10 ** token.decimals()));
assertTrue(token.balanceOf(buyer) == 100000000000000);
assertTrue(
currency.balanceOf(receiver) ==
(100000000000000 * 10000000) / (10 ** token.decimals())
);
assertTrue(currency.balanceOf(receiver) == (100000000000000 * 10000000) / (10 ** token.decimals()));
}

// todo: make sure a valid test case is found
function testDealHappyCaseX(uint256 tokenSaleBits) public {
// limit tokenSaleBits to to values [minAmount, maxAmount]
vm.assume(tokenSaleBits >= invite.minAmount());
vm.assume(tokenSaleBits <= invite.maxAmount());
if (
(tokenSaleBits * invite.tokenPrice()) % (10 ** token.decimals()) ==
0
) {
if ((tokenSaleBits * invite.tokenPrice()) % (10 ** token.decimals()) == 0) {
// test cases without rest must be successful
uint256 buyerStartCurrencyBalance = currency.balanceOf(buyer);
// uint256 tokenSaleBits = 2.7 * 10**14;
uint256 currencyCost = (tokenSaleBits * price) /
(10 ** token.decimals());
uint256 expectedBuyerCurrencyBalance = buyerStartCurrencyBalance -
currencyCost;
uint256 currencyCost = (tokenSaleBits * price) / (10 ** token.decimals());
uint256 expectedBuyerCurrencyBalance = buyerStartCurrencyBalance - currencyCost;

assertTrue(currency.balanceOf(buyer) == buyerStartCurrencyBalance); // buyer owns 10**10 currency, so 10**10 * 10**currency.decimals() currency bits (bit = smallest subunit of token)
vm.prank(buyer);
invite.deal(tokenSaleBits); // buyer brings in their amount of payment currency in bits

assertTrue(
currency.balanceOf(buyer) == expectedBuyerCurrencyBalance
);
assertTrue(currency.balanceOf(buyer) == expectedBuyerCurrencyBalance);
assertTrue(token.balanceOf(buyer) == tokenSaleBits);
assertTrue(currency.balanceOf(receiver) == currencyCost);
} else {
// test cases with rest must fail
vm.prank(buyer);
vm.expectRevert(
"Amount * tokenprice needs to be a multiple of 10**token.decimals()"
);
vm.expectRevert("Amount * tokenprice needs to be a multiple of 10**token.decimals()");
invite.deal(tokenSaleBits);
}
}
Expand All @@ -172,11 +144,7 @@ contract PersonalInviteOldOldTest is Test {
uint8 maxDecimals = 25;
FakePaymentToken paymentToken;

for (
uint8 paymentTokenDecimals = 1;
paymentTokenDecimals < maxDecimals;
paymentTokenDecimals++
) {
for (uint8 paymentTokenDecimals = 1; paymentTokenDecimals < maxDecimals; paymentTokenDecimals++) {
//uint8 paymentTokenDecimals = 10;

/*
Expand All @@ -192,10 +160,7 @@ contract PersonalInviteOldOldTest is Test {
list = new AllowList();
token = new CorpusToken(admin, list, 0x0, "TESTTOKEN", "TEST");
vm.prank(paymentTokenProvider);
paymentToken = new FakePaymentToken(
_paymentTokenAmount,
paymentTokenDecimals
);
paymentToken = new FakePaymentToken(_paymentTokenAmount, paymentTokenDecimals);
vm.prank(owner);

invite = new PersonalInviteOld(
Expand Down Expand Up @@ -235,16 +200,11 @@ contract PersonalInviteOldOldTest is Test {
vm.prank(buyer);
invite.deal(33 * 10 ** 18);
// buyer should have 10 FPT left
assertTrue(
paymentToken.balanceOf(buyer) == 10 * 10 ** paymentTokenDecimals
);
assertTrue(paymentToken.balanceOf(buyer) == 10 * 10 ** paymentTokenDecimals);
// buyer should have the 33 CT they bought
assertTrue(token.balanceOf(buyer) == 33 * 10 ** 18);
// receiver should have the 990 FPT that were paid
assertTrue(
paymentToken.balanceOf(receiver) ==
990 * 10 ** paymentTokenDecimals
);
assertTrue(paymentToken.balanceOf(receiver) == 990 * 10 ** paymentTokenDecimals);
}
}

Expand Down Expand Up @@ -370,10 +330,7 @@ contract PersonalInviteOldOldTest is Test {

// give invite contract allowance
vm.prank(buyer);
currency.approve(
address(invite),
200000000000000000000 * 2000000000000
);
currency.approve(address(invite), 200000000000000000000 * 2000000000000);
vm.prank(buyer);
invite.deal(10000000000000000000);
}
Expand All @@ -387,17 +344,9 @@ contract PersonalInviteOldOldTest is Test {
assertTrue(currency.balanceOf(buyer) == 10000000000);
vm.prank(buyer);
invite.deal(100000000000000);
assertTrue(
currency.balanceOf(buyer) ==
10000000000 -
(100000000000000 * 10000000) /
(10 ** token.decimals())
);
assertTrue(currency.balanceOf(buyer) == 10000000000 - (100000000000000 * 10000000) / (10 ** token.decimals()));
assertTrue(token.balanceOf(buyer) == 100000000000000);
assertTrue(
currency.balanceOf(receiver) ==
(100000000000000 * 10000000) / (10 ** token.decimals())
);
assertTrue(currency.balanceOf(receiver) == (100000000000000 * 10000000) / (10 ** token.decimals()));
// after deal, all state variables are deleted. Therefore, even buyer can not buy anymore, rendering the deal unusable.
vm.expectRevert("Only the personally invited buyer can take this deal");
vm.prank(buyer);
Expand Down
74 changes: 42 additions & 32 deletions contracts/AllowList.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,61 @@ pragma solidity 0.8.17;

import "@openzeppelin/contracts/access/Ownable2Step.sol";

/*
The AllowList contract is used to manage a list of addresses and attest each address certain attributes.
Examples for possible attributes are: is KYCed, is american, is of age, etc.
One AllowList managed by one entity (e.g. tokenize.it) can manage up to 252 different attributes, and one tier with 5 levels, and can be used by an unlimited number of other Tokens.
*/
/**
* @title AllowList
* @author malteish, cjentzsch
* @notice The AllowList contract is used to manage a list of addresses and attest each address certain attributes.
* Examples for possible attributes are: is KYCed, is american, is of age, etc.
* One AllowList managed by one entity (e.g. tokenize.it) can manage up to 252 different attributes, and one tier with 5 levels, and can be used by an unlimited number of other Tokens.
*/
contract AllowList is Ownable2Step {
/**
@dev Attributes are defined as bit mask, with the bit position encoding it's meaning and the bit's value whether this attribute is attested or not.
Example:
- position 0: 1 = has been KYCed (0 = not KYCed)
- position 1: 1 = is american citizen (0 = not american citizen)
- position 2: 1 = is a penguin (0 = not a penguin)
These meanings are not defined within code, neither in the token contract nor the allowList. Nevertheless, the definition used by the people responsible for both contracts MUST match,
or the token contract will not work as expected. E.g. if the allowList defines position 2 as "is a penguin", while the token contract uses position 2 as "is a hedgehog", then the tokens
might be sold to hedgehogs, which was never the intention.
Here some examples of how requirements can be used in practice:
value 0b0000000000000000000000000000000000000000000000000000000000000101, means "is KYCed and is a penguin"
value 0b0000000000000000000000000000000000000000000000000000000000000111, means "is KYCed, is american and is a penguin"
value 0b0000000000000000000000000000000000000000000000000000000000000000, means "has not proven any relevant attributes to the allowList operator" (default value)

The highest four bits are defined as tiers as follows (depicted with less bits because 256 is a lot):
- 0b0000000000000000000000000000000000000000000000000000000000000000 = tier 0
- 0b0001000000000000000000000000000000000000000000000000000000000000 = tier 1
- 0b0011000000000000000000000000000000000000000000000000000000000000 = tier 2 (and 1)
- 0b0111000000000000000000000000000000000000000000000000000000000000 = tier 3 (and 2 and 1)
- 0b1111000000000000000000000000000000000000000000000000000000000000 = tier 4 (and 3 and 2 and 1)
This very simple definition allows for a maximum of 5 tiers, even though 4 bits are used for encoding. By sacrificing some space it can be implemented without code changes.

* @notice Stores the attributes for each address.
* @dev Attributes are defined as bit mask, with the bit position encoding it's meaning and the bit's value whether this attribute is attested or not.
* Example:
* - position 0: 1 = has been KYCed (0 = not KYCed)
* - position 1: 1 = is american citizen (0 = not american citizen)
* - position 2: 1 = is a penguin (0 = not a penguin)
* These meanings are not defined within code, neither in the token contract nor the allowList. Nevertheless, the definition used by the people responsible for both contracts MUST match,
* or the token contract will not work as expected. E.g. if the allowList defines position 2 as "is a penguin", while the token contract uses position 2 as "is a hedgehog", then the tokens
* might be sold to hedgehogs, which was never the intention.
* Here some examples of how requirements can be used in practice:
* value 0b0000000000000000000000000000000000000000000000000000000000000101, means "is KYCed and is a penguin"
* value 0b0000000000000000000000000000000000000000000000000000000000000111, means "is KYCed, is american and is a penguin"
* value 0b0000000000000000000000000000000000000000000000000000000000000000, means "has not proven any relevant attributes to the allowList operator" (default value)
*
* The highest four bits are defined as tiers as follows (depicted with less bits because 256 is a lot):
* - 0b0000000000000000000000000000000000000000000000000000000000000000 = tier 0
* - 0b0001000000000000000000000000000000000000000000000000000000000000 = tier 1
* - 0b0011000000000000000000000000000000000000000000000000000000000000 = tier 2 (and 1)
* - 0b0111000000000000000000000000000000000000000000000000000000000000 = tier 3 (and 2 and 1)
* - 0b1111000000000000000000000000000000000000000000000000000000000000 = tier 4 (and 3 and 2 and 1)
* This very simple definition allows for a maximum of 5 tiers, even though 4 bits are used for encoding. By sacrificing some space it can be implemented without code changes.
*/
mapping(address => uint256) public map;

event Set(address indexed key, uint256 value);
/**
* @notice Attributes for `key` have been set to `value`
* @param _addr address the attributes are set for
* @param _attributes new attributes
*/
event Set(address indexed _addr, uint256 _attributes);

/**
@notice sets (or updates) the attributes for an address
*/
* @notice sets (or updates) the attributes for an address
* @param _addr address to be set
* @param _attributes new attributes
*/
function set(address _addr, uint256 _attributes) external onlyOwner {
map[_addr] = _attributes;
emit Set(_addr, _attributes);
}

/**
@notice purges an address from the allowList
@dev this is a convenience function, it is equivalent to calling set(_addr, 0)
*/
* @notice purges an address from the allowList
* @dev this is a convenience function, it is equivalent to calling set(_addr, 0)
* @param _addr address to be removed
*/
function remove(address _addr) external onlyOwner {
delete map[_addr];
emit Set(_addr, 0);
Expand Down
Loading