Skip to content

Commit 5edfce9

Browse files
committed
✨ exa: add crosschain mint and burn support
1 parent 946d9bf commit 5edfce9

File tree

5 files changed

+239
-54
lines changed

5 files changed

+239
-54
lines changed

.changeset/silent-chefs-marry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@exactly/protocol": minor
3+
---
4+
5+
✨ exa: add crosschain mint and burn support

.gas-snapshot

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ DebtManagerTest:testFloatingToFixedRollHigherThanAvailableLiquidityWithSlippage(
4949
DebtManagerTest:testFloatingToFixedRollHigherThanAvailableLiquidityWithSlippageWithThreePools() (gas: 2818426)
5050
DebtManagerTest:testFloatingToFixedRollWithAccurateSlippage() (gas: 1732739)
5151
DebtManagerTest:testFloatingToFixedRollWithAccurateSlippageWithPreviousPosition() (gas: 1954939)
52-
DebtManagerTest:testFuzzRolls(uint8[4],uint8[4],uint256[4],uint40[4],uint8[4]) (runs: 256, μ: 8020203, ~: 8068563)
52+
DebtManagerTest:testFuzzRolls(uint8[4],uint8[4],uint256[4],uint40[4],uint8[4]) (runs: 256, μ: 8002773, ~: 8075362)
5353
DebtManagerTest:testLateFixedRoll() (gas: 1454770)
5454
DebtManagerTest:testLateFixedRollWithThreeLoops() (gas: 2043936)
5555
DebtManagerTest:testLateFixedToFloatingRoll() (gas: 1449634)
@@ -99,39 +99,54 @@ DebtRollerTest:test_rollFixed_reverts_whenInvalidOperation() (gas: 51027)
9999
DebtRollerTest:test_rollFixed_reverts_whenNotMarket() (gas: 49047)
100100
DebtRollerTest:test_rollFixed_rolls() (gas: 1100854)
101101
DebtRollerTest:test_rollFixed_rolls_partial() (gas: 1140051)
102-
EscrowedEXATest:testCancelExternalStreams() (gas: 383574)
102+
EXATest:test_burn_burnsAndEmitsCrosschainBurn() (gas: 143092)
103+
EXATest:test_burn_reverts_whenCallerLacksBridgeRole() (gas: 67534)
104+
EXATest:test_crosschainBurn_burnsAndEmitsCrosschainBurn() (gas: 143113)
105+
EXATest:test_crosschainBurn_reverts_whenCallerLacksBridgeRole() (gas: 67481)
106+
EXATest:test_crosschainMint_mintsAndEmitsCrosschainMint() (gas: 98776)
107+
EXATest:test_crosschainMint_reverts_whenCallerLacksBridgeRole() (gas: 67490)
108+
EXATest:test_initializeV2_grantsAdminRole() (gas: 25887)
109+
EXATest:test_initializeV2_reverts_whenCalledTwice() (gas: 39159)
110+
EXATest:test_initialize_setsNameSymbolAndSupply() (gas: 48893)
111+
EXATest:test_mint_mintsAndEmitsCrosschainMint() (gas: 98821)
112+
EXATest:test_mint_reverts_whenCallerLacksBridgeRole() (gas: 67533)
113+
EXATest:test_supportsInterface_returnsFalse_forInvalidInterface() (gas: 13533)
114+
EXATest:test_supportsInterface_returnsTrue_forIAccessControl() (gas: 13542)
115+
EXATest:test_supportsInterface_returnsTrue_forIERC165() (gas: 13509)
116+
EXATest:test_supportsInterface_returnsTrue_forIERC7802() (gas: 13410)
117+
EscrowedEXATest:testCancelExternalStreams() (gas: 398267)
103118
EscrowedEXATest:testCancelExternalStreamsWithesEXACancel() (gas: 1137424)
104-
EscrowedEXATest:testCancelShouldDeleteReserves() (gas: 774852)
105-
EscrowedEXATest:testCancelShouldGiveReservesBack() (gas: 1185805)
106-
EscrowedEXATest:testCancelTwiceShouldRevert() (gas: 731099)
107-
EscrowedEXATest:testCancelWithInvalidAccount() (gas: 552511)
119+
EscrowedEXATest:testCancelShouldDeleteReserves() (gas: 801977)
120+
EscrowedEXATest:testCancelShouldGiveReservesBack() (gas: 1229121)
121+
EscrowedEXATest:testCancelTwiceShouldRevert() (gas: 748504)
122+
EscrowedEXATest:testCancelWithInvalidAccount() (gas: 573278)
108123
EscrowedEXATest:testFakeTokenWithesEXARecipient() (gas: 1203505)
109124
EscrowedEXATest:testGrantTransferrerRoleAsAdmin() (gas: 74807)
110-
EscrowedEXATest:testMint() (gas: 187548)
111-
EscrowedEXATest:testMintMoreThanBalance() (gas: 41491)
112-
EscrowedEXATest:testMintToAnother() (gas: 189756)
125+
EscrowedEXATest:testMint() (gas: 192860)
126+
EscrowedEXATest:testMintMoreThanBalance() (gas: 46423)
127+
EscrowedEXATest:testMintToAnother() (gas: 195068)
113128
EscrowedEXATest:testMintZero() (gas: 35366)
114-
EscrowedEXATest:testRedeemAsNotRedeemer() (gas: 329073)
115-
EscrowedEXATest:testRedeemAsRedeemer() (gas: 256283)
116-
EscrowedEXATest:testRedeemAsRedeemerToAnother() (gas: 271558)
129+
EscrowedEXATest:testRedeemAsNotRedeemer() (gas: 344155)
130+
EscrowedEXATest:testRedeemAsRedeemer() (gas: 271700)
131+
EscrowedEXATest:testRedeemAsRedeemerToAnother() (gas: 291835)
117132
EscrowedEXATest:testSetReserveRatioAsAdmin() (gas: 54918)
118133
EscrowedEXATest:testSetReserveRatioAsNotAdmin() (gas: 67189)
119134
EscrowedEXATest:testSetReserveRatioAsZero() (gas: 37264)
120135
EscrowedEXATest:testSetVestingPeriodAsAdmin() (gas: 55030)
121136
EscrowedEXATest:testSetVestingPeriodAsNotAdmin() (gas: 67179)
122-
EscrowedEXATest:testTransferToNotTransferrer() (gas: 213681)
123-
EscrowedEXATest:testTransferToTransferrer() (gas: 302944)
124-
EscrowedEXATest:testVest() (gas: 519779)
125-
EscrowedEXATest:testVestDisagreement() (gas: 300084)
126-
EscrowedEXATest:testVestToAnother() (gas: 657280)
127-
EscrowedEXATest:testVestToAnotherAndCancel() (gas: 749929)
128-
EscrowedEXATest:testVestWithPermitReserve() (gas: 738759)
137+
EscrowedEXATest:testTransferToNotTransferrer() (gas: 218993)
138+
EscrowedEXATest:testTransferToTransferrer() (gas: 308256)
139+
EscrowedEXATest:testVest() (gas: 545406)
140+
EscrowedEXATest:testVestDisagreement() (gas: 305396)
141+
EscrowedEXATest:testVestToAnother() (gas: 692635)
142+
EscrowedEXATest:testVestToAnotherAndCancel() (gas: 772194)
143+
EscrowedEXATest:testVestWithPermitReserve() (gas: 789988)
129144
EscrowedEXATest:testVestZero() (gas: 60469)
130-
EscrowedEXATest:testWithdrawFromStreamAndGetReserveBack() (gas: 648887)
145+
EscrowedEXATest:testWithdrawFromStreamAndGetReserveBack() (gas: 684250)
131146
EscrowedEXATest:testWithdrawFromUnknownStream() (gas: 1111375)
132-
EscrowedEXATest:testWithdrawMaxFromMultipleStreams() (gas: 1736065)
133-
EscrowedEXATest:testWithdrawMaxShouldGiveReserveBackWhenDepleted() (gas: 587458)
134-
EscrowedEXATest:testWithdrawMaxWithInvalidSender() (gas: 517048)
147+
EscrowedEXATest:testWithdrawMaxFromMultipleStreams() (gas: 1781140)
148+
EscrowedEXATest:testWithdrawMaxShouldGiveReserveBackWhenDepleted() (gas: 613461)
149+
EscrowedEXATest:testWithdrawMaxWithInvalidSender() (gas: 528095)
135150
FirewallTest:test_allow_allows_whenAllower() (gas: 69731)
136151
FirewallTest:test_allow_allows_whenDisallowedAndNotOriginalAllower() (gas: 227184)
137152
FirewallTest:test_allow_disallows_whenAllower() (gas: 112510)
@@ -171,18 +186,18 @@ IntegrationPreviewerTest:test_fixedRepayPosition_beforeMaturity() (gas: 579991)
171186
IntegrationPreviewerTest:test_fixedRepayPosition_maxUint() (gas: 79468)
172187
IntegrationPreviewerTest:test_fixedRepayPosition_saturatedFallback() (gas: 63069)
173188
IntegrationPreviewerTest:test_healthFactor() (gas: 463879)
174-
IntegrationPreviewerTest:test_previewDeposit_(uint256) (runs: 256, μ: 1590498, ~: 1594531)
189+
IntegrationPreviewerTest:test_previewDeposit_(uint256) (runs: 256, μ: 1590522, ~: 1594531)
175190
IntegrationPreviewerTest:test_previewHealthFactor() (gas: 5805369)
176-
IntegrationPreviewerTest:test_previewWithdraw_(uint256) (runs: 256, μ: 1649878, ~: 1654116)
191+
IntegrationPreviewerTest:test_previewWithdraw_(uint256) (runs: 256, μ: 1649866, ~: 1654116)
177192
InterestRateModelTest:testFixedBorrowRate() (gas: 2088868)
178193
InterestRateModelTest:testFixedRateRevertAlreadyMatured() (gas: 2083135)
179194
InterestRateModelTest:testFixedRateRevertUtilizationExceeded() (gas: 2097203)
180195
InterestRateModelTest:testFloatingBorrowRate() (gas: 2082456)
181-
InterestRateModelTest:testFuzzFixedRateGrowth(uint256,uint256,uint256,uint256) (runs: 256, μ: 2109190, ~: 2105195)
182-
InterestRateModelTest:testFuzzFixedRateTimeSensitivity(uint256,uint256,uint256) (runs: 256, μ: 2117000, ~: 2117161)
183-
InterestRateModelTest:testFuzzReferenceLegacyRateFixed(uint32,uint256,uint256[2],uint256[2],uint256,uint256,uint256) (runs: 256, μ: 12923635, ~: 13133097)
184-
InterestRateModelTest:testFuzzReferenceRateFixed(uint256,uint256,uint256,uint256,uint256,uint256,(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int256,uint256,uint256)) (runs: 256, μ: 2384745, ~: 2386875)
185-
InterestRateModelTest:testFuzzReferenceRateFloating(uint256,uint256,(uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 256, μ: 2324314, ~: 2325007)
196+
InterestRateModelTest:testFuzzFixedRateGrowth(uint256,uint256,uint256,uint256) (runs: 256, μ: 2109504, ~: 2112742)
197+
InterestRateModelTest:testFuzzFixedRateTimeSensitivity(uint256,uint256,uint256) (runs: 256, μ: 2117003, ~: 2117161)
198+
InterestRateModelTest:testFuzzReferenceLegacyRateFixed(uint32,uint256,uint256[2],uint256[2],uint256,uint256,uint256) (runs: 256, μ: 12893486, ~: 13132915)
199+
InterestRateModelTest:testFuzzReferenceRateFixed(uint256,uint256,uint256,uint256,uint256,uint256,(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,int256,uint256,uint256)) (runs: 256, μ: 2384344, ~: 2386613)
200+
InterestRateModelTest:testFuzzReferenceRateFloating(uint256,uint256,(uint256,uint256,uint256,uint256,uint256,uint256,uint256)) (runs: 256, μ: 2324315, ~: 2324948)
186201
InterestRateModelTest:testMinTimeToMaturity() (gas: 2107232)
187202
InterestRateModelTest:testRevertMaxUtilizationLowerThanWad() (gas: 268402)
188203
MarketTest:testAccountLiquidityAdjustedDebt() (gas: 654335)
@@ -337,7 +352,7 @@ PoolLibTest:testAtomicDepositBorrowRepayWithdraw() (gas: 45922)
337352
PoolLibTest:testBackupBorrow() (gas: 33624)
338353
PoolLibTest:testEarningsAccrual() (gas: 38952)
339354
PoolLibTest:testEarningsDistribution() (gas: 32679)
340-
PoolLibTest:testFuzzAddRemoveAll(uint8[12]) (runs: 256, μ: 104449, ~: 105534)
355+
PoolLibTest:testFuzzAddRemoveAll(uint8[12]) (runs: 256, μ: 106488, ~: 107653)
341356
PoolLibTest:testMaturityRangeLimit() (gas: 7866)
342357
PoolLibTest:testMaturityRangeTooWide() (gas: 11656)
343358
PreviewerTest:testAccountsReturningAccurateAmounts() (gas: 1686539)
@@ -516,8 +531,8 @@ StakedEXATest:invariantNoDuplicatedReward() (runs: 10, calls: 5000, reverts: 0)
516531
StakedEXATest:invariantRewardsUpOnly() (runs: 10, calls: 5000, reverts: 0)
517532
StakedEXATest:invariantShareValueIsOne() (runs: 10, calls: 5000, reverts: 0)
518533
StakedEXATest:testAlreadyListedError() (gas: 43677)
519-
StakedEXATest:testAvgIndex(uint256[3],uint256[2]) (runs: 256, μ: 1313851, ~: 1370678)
520-
StakedEXATest:testAvgStartTime(uint256[3],uint256[2]) (runs: 256, μ: 1241917, ~: 1298744)
534+
StakedEXATest:testAvgIndex(uint256[3],uint256[2]) (runs: 256, μ: 1317429, ~: 1370678)
535+
StakedEXATest:testAvgStartTime(uint256[3],uint256[2]) (runs: 256, μ: 1245495, ~: 1298744)
521536
StakedEXATest:testBalanceOfDeposit(uint80) (runs: 256, μ: 331886, ~: 339807)
522537
StakedEXATest:testBalanceOfWithdraw(uint256) (runs: 256, μ: 82393, ~: 82407)
523538
StakedEXATest:testCanChangeRewardsDurationWhenDisabled() (gas: 176331)
@@ -526,12 +541,12 @@ StakedEXATest:testClaimAndUnstake() (gas: 1622618)
526541
StakedEXATest:testClaimAndWithdrawAfterRefTime() (gas: 1029325)
527542
StakedEXATest:testClaimBeforeFirstHarvest() (gas: 527334)
528543
StakedEXATest:testDepositClaimsRewardsToReceiver() (gas: 1121108)
529-
StakedEXATest:testDepositEvent(uint256) (runs: 256, μ: 335227, ~: 334966)
530-
StakedEXATest:testDepositShouldClaim(uint256[2],uint32) (runs: 256, μ: 815891, ~: 754868)
544+
StakedEXATest:testDepositEvent(uint256) (runs: 256, μ: 335238, ~: 334966)
545+
StakedEXATest:testDepositShouldClaim(uint256[2],uint32) (runs: 256, μ: 832846, ~: 755532)
531546
StakedEXATest:testDepositToAnotherWithAllowance() (gas: 375284)
532547
StakedEXATest:testDepositToAnotherWithoutAllowanceShouldFail() (gas: 121959)
533-
StakedEXATest:testDepositWithdrawAvgStartTimeAndIndex(uint256[3],uint256,uint256[5]) (runs: 256, μ: 1881512, ~: 1904719)
534-
StakedEXATest:testEarnedWithTime(uint256) (runs: 256, μ: 86098, ~: 86314)
548+
StakedEXATest:testDepositWithdrawAvgStartTimeAndIndex(uint256[3],uint256,uint256[5]) (runs: 256, μ: 1887155, ~: 1906094)
549+
StakedEXATest:testEarnedWithTime(uint256) (runs: 256, μ: 86112, ~: 86314)
535550
StakedEXATest:testEmergencyAdminCanPauseNotUnpause() (gas: 175029)
536551
StakedEXATest:testFinishDistributionEmitEvent() (gas: 240752)
537552
StakedEXATest:testFinishDistributionLetsClaimUnclaimed() (gas: 1784865)
@@ -542,9 +557,9 @@ StakedEXATest:testGrantRevokeEmergencyAdmin() (gas: 117824)
542557
StakedEXATest:testGrantRevokePauser() (gas: 117836)
543558
StakedEXATest:testHandlerClaim(uint8) (runs: 256, μ: 485340, ~: 485340)
544559
StakedEXATest:testHandlerDeposit(uint80) (runs: 256, μ: 1231152, ~: 1263054)
545-
StakedEXATest:testHandlerHarvest(uint64) (runs: 256, μ: 403155, ~: 411143)
546-
StakedEXATest:testHandlerNotifyRewardAmount(uint64) (runs: 256, μ: 143611, ~: 136610)
547-
StakedEXATest:testHandlerSetDuration(uint32) (runs: 256, μ: 189027, ~: 218699)
560+
StakedEXATest:testHandlerHarvest(uint64) (runs: 256, μ: 403144, ~: 411143)
561+
StakedEXATest:testHandlerNotifyRewardAmount(uint64) (runs: 256, μ: 142888, ~: 136565)
562+
StakedEXATest:testHandlerSetDuration(uint32) (runs: 256, μ: 193976, ~: 218711)
548563
StakedEXATest:testHandlerSetMarket() (gas: 144553)
549564
StakedEXATest:testHandlerWithdraw(uint256) (runs: 256, μ: 102852, ~: 102866)
550565
StakedEXATest:testHarvestAmountWithReducedAllowance() (gas: 184605)
@@ -555,13 +570,13 @@ StakedEXATest:testHarvestWhenFinished() (gas: 326352)
555570
StakedEXATest:testHarvestX() (gas: 180952)
556571
StakedEXATest:testHarvestZero() (gas: 255436)
557572
StakedEXATest:testInitialValues() (gas: 196483)
558-
StakedEXATest:testInsufficientBalanceError(uint256) (runs: 256, μ: 63949, ~: 64151)
573+
StakedEXATest:testInsufficientBalanceError(uint256) (runs: 256, μ: 63948, ~: 64151)
559574
StakedEXATest:testMaxRewardsGasConsumption() (gas: 144674963)
560575
StakedEXATest:testMultipleClaimsVsOne() (gas: 21936440)
561576
StakedEXATest:testMultipleHarvests() (gas: 284083)
562-
StakedEXATest:testNoRewardsAfterPeriod(uint256) (runs: 256, μ: 1809808, ~: 1804391)
577+
StakedEXATest:testNoRewardsAfterPeriod(uint256) (runs: 256, μ: 1810574, ~: 1816281)
563578
StakedEXATest:testNotPausingRoleError() (gas: 39124)
564-
StakedEXATest:testNotifyRewardAmount(uint256,uint256) (runs: 256, μ: 155584, ~: 155564)
579+
StakedEXATest:testNotifyRewardAmount(uint256,uint256) (runs: 256, μ: 155609, ~: 155564)
565580
StakedEXATest:testNotifyRewardWithUnderlyingAsset() (gas: 460608)
566581
StakedEXATest:testOnlyAdminEnableReward() (gas: 1297302)
567582
StakedEXATest:testOnlyAdminFinishDistribution() (gas: 213640)
@@ -579,13 +594,13 @@ StakedEXATest:testPenaltyThresholdRange() (gas: 36989)
579594
StakedEXATest:testPermitAndDeposit() (gas: 452146)
580595
StakedEXATest:testPermitFailKeepsFlow() (gas: 484480)
581596
StakedEXATest:testRemoveDepositAllowance() (gas: 466913)
582-
StakedEXATest:testResetDepositAfterRefTime(uint256) (runs: 256, μ: 1033237, ~: 1032994)
583-
StakedEXATest:testRewardAmountNotifiedEvent(uint256) (runs: 256, μ: 105539, ~: 105269)
597+
StakedEXATest:testResetDepositAfterRefTime(uint256) (runs: 256, μ: 1033250, ~: 1032994)
598+
StakedEXATest:testRewardAmountNotifiedEvent(uint256) (runs: 256, μ: 105542, ~: 105269)
584599
StakedEXATest:testRewardNotListedError() (gas: 1177184)
585-
StakedEXATest:testRewardPaidEvent(uint256,uint256) (runs: 256, μ: 809095, ~: 854321)
586-
StakedEXATest:testRewardsAmounts(uint256) (runs: 256, μ: 1707492, ~: 1707275)
600+
StakedEXATest:testRewardPaidEvent(uint256,uint256) (runs: 256, μ: 807482, ~: 854316)
601+
StakedEXATest:testRewardsAmounts(uint256) (runs: 256, μ: 1707508, ~: 1707275)
587602
StakedEXATest:testRewardsDurationSetEvent(uint40) (runs: 256, μ: 52170, ~: 52149)
588-
StakedEXATest:testSetDuration(uint256,uint40) (runs: 256, μ: 65967, ~: 64453)
603+
StakedEXATest:testSetDuration(uint256,uint40) (runs: 256, μ: 65856, ~: 64453)
589604
StakedEXATest:testSetMarketAddressZero() (gas: 36979)
590605
StakedEXATest:testSetMarketOnlyAdmin() (gas: 1345554)
591606
StakedEXATest:testSetMaxRewardsTokensExceeded() (gas: 111958823)
@@ -597,12 +612,12 @@ StakedEXATest:testSetSavingsZeroAddressError() (gas: 37006)
597612
StakedEXATest:testTotalSupplyDeposit(uint80) (runs: 256, μ: 331272, ~: 339193)
598613
StakedEXATest:testTotalSupplyWithdraw(uint256) (runs: 256, μ: 81753, ~: 81767)
599614
StakedEXATest:testUntransferable(uint80) (runs: 256, μ: 339593, ~: 348672)
600-
StakedEXATest:testWithdrawEvent(uint256) (runs: 256, μ: 483392, ~: 483140)
615+
StakedEXATest:testWithdrawEvent(uint256) (runs: 256, μ: 483404, ~: 483140)
601616
StakedEXATest:testWithdrawRewardUnderlyingAsset() (gas: 456617)
602617
StakedEXATest:testWithdrawRewardsOnlyAdmin() (gas: 242200)
603618
StakedEXATest:testWithdrawRewardsOnlyReward() (gas: 1177174)
604-
StakedEXATest:testWithdrawSameAmountRewardsShouldEqual(uint256,uint256) (runs: 256, μ: 1064622, ~: 1107874)
605-
StakedEXATest:testWithdrawWithRewards(uint256) (runs: 256, μ: 895610, ~: 895358)
619+
StakedEXATest:testWithdrawSameAmountRewardsShouldEqual(uint256,uint256) (runs: 256, μ: 1062756, ~: 1107874)
620+
StakedEXATest:testWithdrawWithRewards(uint256) (runs: 256, μ: 895622, ~: 895358)
606621
StakedEXATest:testZeroRateError() (gas: 58274)
607622
StakingPreviewerTest:testAllClaimable() (gas: 769205)
608623
StakingPreviewerTest:testAllClaimed() (gas: 818952)

contracts/periphery/EXA.sol

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,53 @@
11
// SPDX-License-Identifier: BUSL-1.1
22
pragma solidity ^0.8.17;
33

4+
import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable-v4/access/AccessControlUpgradeable.sol";
45
import {
56
ERC20VotesUpgradeable
67
} from "@openzeppelin/contracts-upgradeable-v4/token/ERC20/extensions/ERC20VotesUpgradeable.sol";
8+
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
9+
import { IERC7802 } from "@openzeppelin/contracts/interfaces/draft-IERC7802.sol";
10+
11+
contract EXA is ERC20VotesUpgradeable, AccessControlUpgradeable, IERC7802 {
12+
bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE");
13+
14+
/// @custom:oz-upgrades-unsafe-allow constructor
15+
constructor() {
16+
_disableInitializers();
17+
}
718

8-
contract EXA is ERC20VotesUpgradeable {
919
function initialize() external initializer {
1020
__ERC20_init("exactly", "EXA");
1121
__ERC20Permit_init("exactly");
1222
__ERC20Votes_init();
1323
_mint(msg.sender, 10_000_000e18);
1424
}
1525

26+
function initializeV2(address admin_) external reinitializer(2) {
27+
__AccessControl_init();
28+
_grantRole(DEFAULT_ADMIN_ROLE, admin_);
29+
}
30+
31+
function mint(address to, uint256 amount) external {
32+
crosschainMint(to, amount);
33+
}
34+
35+
function burn(address from, uint256 amount) external {
36+
crosschainBurn(from, amount);
37+
}
38+
39+
/// @inheritdoc IERC7802
40+
function crosschainMint(address to, uint256 amount) public onlyRole(BRIDGE_ROLE) {
41+
_mint(to, amount);
42+
emit CrosschainMint(to, amount, msg.sender);
43+
}
44+
45+
/// @inheritdoc IERC7802
46+
function crosschainBurn(address from, uint256 amount) public onlyRole(BRIDGE_ROLE) {
47+
_burn(from, amount);
48+
emit CrosschainBurn(from, amount, msg.sender);
49+
}
50+
1651
function clock() public view override returns (uint48) {
1752
return uint48(block.timestamp);
1853
}
@@ -21,4 +56,10 @@ contract EXA is ERC20VotesUpgradeable {
2156
function CLOCK_MODE() public pure override returns (string memory) {
2257
return "mode=timestamp";
2358
}
59+
60+
function supportsInterface(
61+
bytes4 interfaceId
62+
) public view override(AccessControlUpgradeable, IERC165) returns (bool) {
63+
return interfaceId == type(IERC7802).interfaceId || super.supportsInterface(interfaceId);
64+
}
2465
}

0 commit comments

Comments
 (0)