Skip to content

Commit

Permalink
Merge branch 'master' into amie-deprecate-restrictednori
Browse files Browse the repository at this point in the history
  • Loading branch information
amiecorso committed Mar 7, 2024
2 parents ce02a7e + 447f6fb commit 7019edc
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 68 deletions.
78 changes: 39 additions & 39 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ AddressArrayLib_fill:test_library() (gas: 13081)
AddressArrayLib_fill:test_reference() (gas: 13691)
BridgedPolygonNORI_name:test() (gas: 17205)
BridgedPolygonNORI_permit:test() (gas: 92382)
Certificate__msgSenderERC721A:test() (gas: 422)
Certificate**msgSenderERC721A:test() (gas: 422)
Certificate_approve:test() (gas: 17906)
Certificate_burn:test() (gas: 188509)
Certificate_burn:test_reverts_when_paused() (gas: 54783)
Expand Down Expand Up @@ -51,26 +51,26 @@ MarketSupplierSelectionNotUsingUpSuppliersLastRemoval:test() (gas: 644634)
Market_ALLOWLIST_ROLE:test() (gas: 12799)
Market_SANCTION_ALLOWLIST_ROLE:test() (gas: 12897)
Market_USDC_swap_respects_decimal_mismatch:test() (gas: 786938)
Market__addActiveRemoval:test() (gas: 183344)
Market__addActiveRemoval:test__lis2VintagesFor1SupplierFor2SubIdentifiers() (gas: 242879)
Market__addActiveRemoval:test__list1VintageFor1Supplier() (gas: 188309)
Market__addActiveRemoval:test__list1VintageFor2Suppliers() (gas: 360670)
Market__addActiveRemoval:test__list2VintagesFor1SupplierFor1SubIdentifier() (gas: 262754)
Market__isAuthorizedWithdrawal_false:test_returnsFalseWhenAllConditionsAreFalse() (gas: 7452)
Market__isAuthorizedWithdrawal_true:test_returnsTrueWhenMsgSenderEqualsOwner() (gas: 377)
Market__isAuthorizedWithdrawal_true:test_returnsTrueWhenMsgSenderHasDefaultAdminRole() (gas: 96578)
Market__isAuthorizedWithdrawal_true:test_returnsTrueWhenMsgSenderIsApprovedForAll() (gas: 8923)
Market__multicall_empty_bytes_reverts:test() (gas: 20935)
Market__multicall_initialize_reverts:test() (gas: 33859)
Market__setPriceMultiple:test() (gas: 29035)
Market__setPriceMultiple:test_revertsWhenSetBelow100() (gas: 3505)
Market__setPurchasingToken:test() (gas: 1021494)
Market__validatePrioritySupply:test_supplyAfterPurchaseIsLessThanPriorityRestrictedThreshold() (gas: 2499)
Market__validatePrioritySupply:test_supplyAfterPurchaseIsZero() (gas: 2544)
Market__validatePrioritySupply_buyerIsAllowlistedAndAmountExceedsPriorityRestrictedThreshold:test() (gas: 4848)
Market__validatePrioritySupply_reverts_LowSupplyAllowlistRequired:test() (gas: 7692)
Market__validateSupply:test() (gas: 292)
Market__validateSupply:test_reverts_OutOfSupply() (gas: 3172)
Market**addActiveRemoval:test() (gas: 183344)
Market**addActiveRemoval:test**lis2VintagesFor1SupplierFor2SubIdentifiers() (gas: 242879)
Market**addActiveRemoval:test**list1VintageFor1Supplier() (gas: 188309)
Market**addActiveRemoval:test**list1VintageFor2Suppliers() (gas: 360670)
Market**addActiveRemoval:test**list2VintagesFor1SupplierFor1SubIdentifier() (gas: 262754)
Market**isAuthorizedWithdrawal_false:test_returnsFalseWhenAllConditionsAreFalse() (gas: 7452)
Market**isAuthorizedWithdrawal_true:test_returnsTrueWhenMsgSenderEqualsOwner() (gas: 377)
Market**isAuthorizedWithdrawal_true:test_returnsTrueWhenMsgSenderHasDefaultAdminRole() (gas: 96578)
Market**isAuthorizedWithdrawal_true:test_returnsTrueWhenMsgSenderIsApprovedForAll() (gas: 8923)
Market**multicall_empty_bytes_reverts:test() (gas: 20935)
Market**multicall_initialize_reverts:test() (gas: 33859)
Market**setPriceMultiple:test() (gas: 29035)
Market**setPriceMultiple:test_revertsWhenSetBelow100() (gas: 3505)
Market**setPurchasingToken:test() (gas: 1021494)
Market**validatePrioritySupply:test_supplyAfterPurchaseIsLessThanPriorityRestrictedThreshold() (gas: 2499)
Market**validatePrioritySupply:test_supplyAfterPurchaseIsZero() (gas: 2544)
Market**validatePrioritySupply_buyerIsAllowlistedAndAmountExceedsPriorityRestrictedThreshold:test() (gas: 4848)
Market**validatePrioritySupply_reverts_LowSupplyAllowlistRequired:test() (gas: 7692)
Market**validateSupply:test() (gas: 292)
Market**validateSupply:test_reverts_OutOfSupply() (gas: 3172)
Market_calculates_prices_using_decimal:test() (gas: 66514)
Market_convertPurchasingTokenDecimalsToRemovalDecimals:test() (gas: 26029)
Market_convertRemovalDecimalsToPurchasingTokenDecimals:test() (gas: 29773)
Expand Down Expand Up @@ -115,23 +115,23 @@ RemovalQueue_getTotalBalanceFromRemovalQueue:test_100xRemovalsOfTheDifferentVint
RemovalQueue_getTotalBalanceFromRemovalQueue:test_100xRemovalsOfTheSameVintage() (gas: 620321)
RemovalQueue_insertRemovalByVintage:test_insertRemovalOnce() (gas: 119613)
RemovalQueue_insertRemovalByVintage:test_insertRemovalTwice() (gas: 121103)
Removal__beforeTokenTransfer:test() (gas: 18010)
Removal__beforeTokenTransfer:test_paused_reverts_Paused() (gas: 29432)
Removal__createRemovalData:test() (gas: 22593)
Removal__createRemovalData:test_reverts_InvalidData() (gas: 25689)
Removal__createRemovalDataBatch:test() (gas: 29594)
Removal__createRemovalDataBatch:test_reverts_InvalidData2() (gas: 36802)
Removal__isValidTransferAmount:testFuzz_ReturnFalse_NonMultiplesOf1e14(uint256) (runs: 256, μ: 13913, ~: 13869)
Removal__isValidTransferAmount:testFuzz_ReturnTrue_MultiplesOf1e14(uint256) (runs: 256, μ: 14397, ~: 14519)
Removal__isValidTransferAmount:testFuzz_ReturnTrue_SmallestGranularity() (gas: 6854)
Removal__isValidTransferAmount:test_ReturnFalse_AmountIsTooGranular() (gas: 6832)
Removal__isValidTransferAmount:test_ReturnFalse_AmountIsTooGranularAndToIsTheCertificate() (gas: 4767)
Removal__isValidTransferAmount:test_ReturnFalse_AmountIsTooGranularAndToIsTheMarket() (gas: 2630)
Removal__isValidTransferAmount:test_ReturnFalse_AmountIsZeroAndToIsTheCertificate() (gas: 4705)
Removal__isValidTransferAmount:test_ReturnFalse_AmountIsZeroAndToIsTheMarket() (gas: 2543)
Removal__isValidTransferAmount:test_ReturnTrue_AmountIsZeroAndToIsNeitherTheMarketNorCertificate() (gas: 6852)
Removal__validateRemoval:test() (gas: 2491)
Removal__validateRemoval:test_reverts_InvalidData() (gas: 5373)
Removal**beforeTokenTransfer:test() (gas: 18010)
Removal**beforeTokenTransfer:test_paused_reverts_Paused() (gas: 29432)
Removal**createRemovalData:test() (gas: 22593)
Removal**createRemovalData:test_reverts_InvalidData() (gas: 25689)
Removal**createRemovalDataBatch:test() (gas: 29594)
Removal**createRemovalDataBatch:test_reverts_InvalidData2() (gas: 36802)
Removal**isValidTransferAmount:testFuzz_ReturnFalse_NonMultiplesOf1e14(uint256) (runs: 256, μ: 13913, ~: 13869)
Removal**isValidTransferAmount:testFuzz_ReturnTrue_MultiplesOf1e14(uint256) (runs: 256, μ: 14397, ~: 14519)
Removal**isValidTransferAmount:testFuzz_ReturnTrue_SmallestGranularity() (gas: 6854)
Removal**isValidTransferAmount:test_ReturnFalse_AmountIsTooGranular() (gas: 6832)
Removal**isValidTransferAmount:test_ReturnFalse_AmountIsTooGranularAndToIsTheCertificate() (gas: 4767)
Removal**isValidTransferAmount:test_ReturnFalse_AmountIsTooGranularAndToIsTheMarket() (gas: 2630)
Removal**isValidTransferAmount:test_ReturnFalse_AmountIsZeroAndToIsTheCertificate() (gas: 4705)
Removal**isValidTransferAmount:test_ReturnFalse_AmountIsZeroAndToIsTheMarket() (gas: 2543)
Removal**isValidTransferAmount:test_ReturnTrue_AmountIsZeroAndToIsNeitherTheMarketNorCertificate() (gas: 6852)
Removal**validateRemoval:test() (gas: 2491)
Removal**validateRemoval:test_reverts_InvalidData() (gas: 5373)
Removal_addBalance:test() (gas: 60302)
Removal_addBalance_reverts_RemovalNotYetMinted:test() (gas: 31137)
Removal_consign_revertsForSoldRemovals:test() (gas: 896804)
Expand Down Expand Up @@ -189,4 +189,4 @@ UInt256ArrayLib_sum:test() (gas: 91155)
UInt256ArrayLib_sum:test_gas() (gas: 91317)
UInt256ArrayLib_sum:test_library() (gas: 40528)
UInt256ArrayLib_sum:test_library_overflow() (gas: 9518)
UInt256ArrayLib_sum:test_reference() (gas: 55513)
UInt256ArrayLib_sum:test_reference() (gas: 55513)
31 changes: 23 additions & 8 deletions contracts/Removal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,22 @@ contract Removal is
uint256[] removalAmounts
);

/**
* @notice Emitted when removals are directly retired into a certificate by Nori.
* @param certificateRecipient The recipient of the certificate.
* @param certificateAmount The total amount of the certificate to mint (denominated in RTs).
* @param certificateId The ID of the certificate being minted.
* @param removalIds The removal IDs to use to mint the certificate.
* @param removalAmounts The amounts to retire from each corresponding removal ID.
*/
event Retire(
address indexed certificateRecipient,
uint256 indexed certificateAmount,
uint256 indexed certificateId,
uint256[] removalIds,
uint256[] removalAmounts
);

/**
* @notice Locks the contract, preventing any future re-initialization.
* @dev See more [here](https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-_disableInitializers--).
Expand Down Expand Up @@ -341,19 +357,18 @@ contract Removal is

/**
* @notice Transfers the provided `amounts` (denominated in NRTs) of the specified removal `ids` directly to the
* Certificate contract to mint a legacy certificate. This function provides Nori the ability to execute a one-off
* migration of legacy certificates and removals (legacy certificates and removals are those which existed prior to
* our deployment to Polygon and covers all historic issuances and purchases up until the date that we start using the
* Market contract).
* Certificate contract to mint a certificate. This function provides Nori the ability to retire removals directly
* into the Certificate contract and to specify exactly which removals will be retired.
* @dev The Certificate contract implements `onERC1155BatchReceived`, which is invoked upon receipt of a batch of
* removals (triggered via `_safeBatchTransferFrom`). This function circumvents the market contract's lifecycle by
* removals (triggered via `_safeBatchTransferFrom`). This function circumvents the market contract by
* transferring the removals from an account with the `CONSIGNOR_ROLE` role.
* Emits a `Retire` event.
*
* It is necessary that the consignor holds the removals because of the following:
* - `ids` can be composed of a list of removal IDs that belong to one or more suppliers.
* - `_safeBatchTransferFrom` only accepts one `from` address.
* - `Certificate.onERC1155BatchReceived` will mint a *new* certificate every time an additional batch is received, so
* we must ensure that all the removals comprising the certificate to be migrated come from a single batch.
* we must ensure that all the removals comprising the certificate come from a single batch.
*
* ##### Requirements:
* - The caller must have the `CONSIGNOR_ROLE` role.
Expand All @@ -367,13 +382,13 @@ contract Removal is
* @param certificateRecipient The recipient of the certificate to be minted.
* @param certificateAmount The total amount of the certificate.
*/
function migrate(
function retire(
uint256[] calldata ids,
uint256[] calldata amounts,
address certificateRecipient,
uint256 certificateAmount
) external onlyRole(CONSIGNOR_ROLE) {
emit Migrate({
emit Retire({
certificateRecipient: certificateRecipient,
certificateAmount: certificateAmount,
certificateId: _certificate.totalMinted(),
Expand Down
33 changes: 25 additions & 8 deletions docs/Removal.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,24 @@ Emitted when legacy removals are minted and then immediately used to migrate a l
| removalAmounts | uint256[] | The amounts for each corresponding removal ID to use to mint the certificate via migration. |


### Retire

```solidity
event Retire(address certificateRecipient, uint256 certificateAmount, uint256 certificateId, uint256[] removalIds, uint256[] removalAmounts)
```

Emitted when removals are directly retired into a certificate by Nori.


| Name | Type | Description |
| ---- | ---- | ----------- |
| certificateRecipient | address | The recipient of the certificate. |
| certificateAmount | uint256 | The total amount of the certificate to mint (denominated in RTs). |
| certificateId | uint256 | The ID of the certificate being minted. |
| removalIds | uint256[] | The removal IDs to use to mint the certificate. |
| removalAmounts | uint256[] | The amounts to retire from each corresponding removal ID. |


### constructor

```solidity
Expand Down Expand Up @@ -300,27 +318,26 @@ this contract, and handles the mechanics of listing this token for sale.</i>
| amount | uint256 | The balance of this token ID to transfer to the Market contract |


### migrate
### retire

```solidity
function migrate(uint256[] ids, uint256[] amounts, address certificateRecipient, uint256 certificateAmount) external
function retire(uint256[] ids, uint256[] amounts, address certificateRecipient, uint256 certificateAmount) external
```

Transfers the provided `amounts` (denominated in NRTs) of the specified removal `ids` directly to the
Certificate contract to mint a legacy certificate. This function provides Nori the ability to execute a one-off
migration of legacy certificates and removals (legacy certificates and removals are those which existed prior to
our deployment to Polygon and covers all historic issuances and purchases up until the date that we start using the
Market contract).
Certificate contract to mint a certificate. This function provides Nori the ability to retire removals directly
into the Certificate contract and to specify exactly which removals will be retired.

<i>The Certificate contract implements `onERC1155BatchReceived`, which is invoked upon receipt of a batch of
removals (triggered via `_safeBatchTransferFrom`). This function circumvents the market contract's lifecycle by
removals (triggered via `_safeBatchTransferFrom`). This function circumvents the market contract by
transferring the removals from an account with the `CONSIGNOR_ROLE` role.
Emits a `Retire` event.

It is necessary that the consignor holds the removals because of the following:
- `ids` can be composed of a list of removal IDs that belong to one or more suppliers.
- `_safeBatchTransferFrom` only accepts one `from` address.
- `Certificate.onERC1155BatchReceived` will mint a *new* certificate every time an additional batch is received, so
we must ensure that all the removals comprising the certificate to be migrated come from a single batch.
we must ensure that all the removals comprising the certificate come from a single batch.

##### Requirements:
- The caller must have the `CONSIGNOR_ROLE` role.
Expand Down
6 changes: 3 additions & 3 deletions tasks/migrate-certificates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ const validateMigrateEvents = ({
}[] = parseTransactionLogs({
contractInstance: removalContract,
txReceipt: txResult,
eventNames: ['Migrate'],
eventNames: ['Retire'],
}).map((log) => ({
certificateId: log.args.certificateId.toNumber(),
removalAmounts: log.args.removalAmounts.map((a: BigNumber) =>
Expand Down Expand Up @@ -503,7 +503,7 @@ export const GET_MIGRATE_CERTIFICATES_TASK = () =>
)
.div(1_000_000)
.toString();
return removalContract.interface.encodeFunctionData('migrate', [
return removalContract.interface.encodeFunctionData('retire', [
ids,
amounts,
recipient,
Expand Down Expand Up @@ -588,7 +588,7 @@ export const GET_MIGRATE_CERTIFICATES_TASK = () =>
tokenIds = parseTransactionLogs({
contractInstance: removalContract,
txReceipt,
eventNames: ['Migrate'],
eventNames: ['Retire'],
}).map((log) => log.args.certificateId.toNumber());
if (tokenIds.length !== batch.length) {
throw new Error(
Expand Down
20 changes: 10 additions & 10 deletions test/Removal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ using AddressArrayLib for address[];
// todo fuzz RemovalIdLib
// todo test that checks Removal.consign can happen using multi call with mix-match project IDs

contract Removal_migrate_revertsIfRemovalBalanceSumDifferentFromCertificateAmount is
contract Removal_retire_revertsIfRemovalBalanceSumDifferentFromCertificateAmount is
UpgradeableMarket
{
/*//////////////////////////////////////////////////////////////
Expand All @@ -34,7 +34,7 @@ contract Removal_migrate_revertsIfRemovalBalanceSumDifferentFromCertificateAmoun
address[] suppliers;

function setUp() external {
// todo reuse setup in Removal_migrate_gasLimit
// todo reuse setup in Removal_retire_gasLimit
_removal.grantRole({
role: _removal.CONSIGNOR_ROLE(),
account: _namedAccounts.admin
Expand Down Expand Up @@ -67,7 +67,7 @@ contract Removal_migrate_revertsIfRemovalBalanceSumDifferentFromCertificateAmoun
function test() external {
vm.prank(_namedAccounts.admin);
vm.expectRevert("Incorrect supply allocation");
_removal.migrate({
_removal.retire({
ids: idsForAllSuppliers,
amounts: amountsForAllSuppliers,
certificateRecipient: _namedAccounts.buyer,
Expand Down Expand Up @@ -135,7 +135,7 @@ contract Removal_consign_revertsForSoldRemovals is UpgradeableMarket {
}
}

contract Removal_migrate is UpgradeableMarket {
contract Removal_retire is UpgradeableMarket {
/*//////////////////////////////////////////////////////////////
INPUTS
//////////////////////////////////////////////////////////////*/
Expand All @@ -156,7 +156,7 @@ contract Removal_migrate is UpgradeableMarket {
address[] suppliers;

function setUp() external {
// todo reuse setup in Removal_migrate_gasLimit
// todo reuse setup in Removal_retire_gasLimit
_removal.grantRole({
role: _removal.CONSIGNOR_ROLE(),
account: _namedAccounts.admin
Expand Down Expand Up @@ -186,7 +186,7 @@ contract Removal_migrate is UpgradeableMarket {
}
}

event Migrate(
event Retire(
address indexed certificateRecipient,
uint256 indexed certificateAmount,
uint256 indexed certificateId,
Expand All @@ -197,7 +197,7 @@ contract Removal_migrate is UpgradeableMarket {
function test() external {
vm.prank(_namedAccounts.admin);
vm.recordLogs();
_removal.migrate({
_removal.retire({
ids: idsForAllSuppliers,
amounts: amountsForAllSuppliers,
certificateRecipient: _namedAccounts.buyer,
Expand All @@ -215,7 +215,7 @@ contract Removal_migrate is UpgradeableMarket {
assertEq(entries.length, 4);
assertEq(
entries[0].topics[0],
keccak256("Migrate(address,uint256,uint256,uint256[],uint256[])") // todo if we move contract events to interfaces we can use IRemoval.Migrate.selector instead
keccak256("Retire(address,uint256,uint256,uint256[],uint256[])") // todo if we move contract events to interfaces we can use IRemoval.Retire.selector instead
);
assertEq(entries[0].topics.length, 4);
assertEq(
Expand All @@ -233,7 +233,7 @@ contract Removal_migrate is UpgradeableMarket {
}
}

contract Removal_migrate_gasLimit is UpgradeableMarket {
contract Removal_retire_gasLimit is UpgradeableMarket {
/*//////////////////////////////////////////////////////////////
INPUTS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -286,7 +286,7 @@ contract Removal_migrate_gasLimit is UpgradeableMarket {
function test() external {
vm.prank(_namedAccounts.admin);
uint256 initialGas = gasleft();
_removal.migrate({
_removal.retire({
ids: idsForAllSuppliers,
amounts: amountsForAllSuppliers,
certificateRecipient: _namedAccounts.buyer,
Expand Down
5 changes: 5 additions & 0 deletions types/events/Removal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
ApprovalForAllEvent,
InitializedEvent,
MigrateEvent,
RetireEvent,
PausedEvent,
ReleaseRemovalEvent,
RoleAdminChangedEvent,
Expand Down Expand Up @@ -33,6 +34,10 @@ export interface RemovalEventMap {
name: 'Migrate';
args: MigrateEvent['args'];
};
Retire: {
name: 'Retire';
args: RetireEvent['args'];
};
Paused: {
name: 'Paused';
args: PausedEvent['args'];
Expand Down

0 comments on commit 7019edc

Please sign in to comment.