@@ -19,6 +19,7 @@ import {
1919 ClearingTransferFacet ,
2020 BondUSAReadFacet ,
2121 TimeTravelFacet as TimeTravel ,
22+ IERC3643 ,
2223} from "@contract-types" ;
2324import {
2425 DEFAULT_PARTITION ,
@@ -82,6 +83,7 @@ describe("Bond Tests", () => {
8283 let protectedPartitionsFacet : ProtectedPartitions ;
8384 let freezeFacet : FreezeFacet ;
8485 let clearingTransferFacet : ClearingTransferFacet ;
86+ let erc3643Facet : IERC3643 ;
8587
8688 async function deploySecurityFixture ( isMultiPartition = false ) {
8789 const base = await deployBondTokenFixture ( {
@@ -134,6 +136,10 @@ describe("Bond Tests", () => {
134136 role : ATS_ROLES . _PROTECTED_PARTITIONS_ROLE ,
135137 members : [ signer_A . address ] ,
136138 } ,
139+ {
140+ role : ATS_ROLES . _AGENT_ROLE ,
141+ members : [ signer_A . address ] ,
142+ } ,
137143 ] ) ;
138144
139145 bondFacet = await ethers . getContractAt ( "BondUSAFacetTimeTravel" , diamond . address , signer_A ) ;
@@ -147,6 +153,7 @@ describe("Bond Tests", () => {
147153 timeTravelFacet = await ethers . getContractAt ( "TimeTravelFacet" , diamond . address , signer_A ) ;
148154 kycFacet = await ethers . getContractAt ( "Kyc" , diamond . address , signer_B ) ;
149155 ssiManagementFacet = await ethers . getContractAt ( "SsiManagement" , diamond . address , signer_A ) ;
156+ erc3643Facet = await ethers . getContractAt ( "IERC3643" , diamond . address ) ;
150157
151158 await ssiManagementFacet . connect ( signer_A ) . addIssuer ( signer_A . address ) ;
152159
@@ -197,6 +204,11 @@ describe("Bond Tests", () => {
197204 await expect (
198205 bondFacet . redeemAtMaturityByPartition ( ADDRESS_ZERO , DEFAULT_PARTITION , amount ) ,
199206 ) . to . be . revertedWithCustomError ( bondFacet , "ZeroAddressNotAllowed" ) ;
207+
208+ await expect ( bondFacet . fullRedeemAtMaturity ( ADDRESS_ZERO ) ) . to . be . revertedWithCustomError (
209+ bondFacet ,
210+ "ZeroAddressNotAllowed" ,
211+ ) ;
200212 } ) ;
201213
202214 it ( "GIVEN single partition mode WHEN redeeming from a non-default partition THEN transaction fails with PartitionNotAllowedInSinglePartitionMode" , async ( ) => {
@@ -211,27 +223,34 @@ describe("Bond Tests", () => {
211223 await expect (
212224 bondFacet . connect ( signer_A ) . redeemAtMaturityByPartition ( signer_B . address , DEFAULT_PARTITION , amount ) ,
213225 ) . to . be . revertedWithCustomError ( bondFacet , "AccountIsBlocked" ) ;
226+
227+ await expect ( bondFacet . connect ( signer_A ) . fullRedeemAtMaturity ( signer_B . address ) ) . to . be . revertedWithCustomError (
228+ bondFacet ,
229+ "AccountIsBlocked" ,
230+ ) ;
214231 } ) ;
215232
216233 it ( "GIVEN the caller lacks the Maturity Redeemer role WHEN redeeming at maturity THEN transaction fails with AccountHasNoRole" , async ( ) => {
217234 await expect (
218235 bondFacet . connect ( signer_B ) . redeemAtMaturityByPartition ( signer_C . address , DEFAULT_PARTITION , amount ) ,
219236 ) . to . be . revertedWithCustomError ( bondFacet , "AccountHasNoRole" ) ;
237+
238+ await expect ( bondFacet . connect ( signer_B ) . fullRedeemAtMaturity ( signer_C . address ) ) . to . be . revertedWithCustomError (
239+ bondFacet ,
240+ "AccountHasNoRole" ,
241+ ) ;
220242 } ) ;
221243 it ( "GIVEN clearing is activated WHEN redeeming at maturity THEN transaction fails with ClearingIsActivated" , async ( ) => {
222244 await clearingActionsFacet . activateClearing ( ) ;
223245
224246 await expect (
225247 bondFacet . redeemAtMaturityByPartition ( signer_C . address , DEFAULT_PARTITION , amount ) ,
226248 ) . to . be . revertedWithCustomError ( bondFacet , "ClearingIsActivated" ) ;
227- } ) ;
228-
229- it ( "GIVEN partitions are protected AND caller lacks required role WHEN redeeming at maturity THEN transaction fails with PartitionsAreProtectedAndNoRole" , async ( ) => {
230- await protectedPartitionsFacet . protectPartitions ( ) ;
231249
232- await expect (
233- bondFacet . redeemAtMaturityByPartition ( signer_C . address , DEFAULT_PARTITION , amount ) ,
234- ) . to . be . revertedWithCustomError ( bondFacet , "PartitionsAreProtectedAndNoRole" ) ;
250+ await expect ( bondFacet . fullRedeemAtMaturity ( signer_C . address ) ) . to . be . revertedWithCustomError (
251+ bondFacet ,
252+ "ClearingIsActivated" ,
253+ ) ;
235254 } ) ;
236255
237256 it ( "GIVEN the token is paused WHEN redeeming at maturity THEN transaction fails with TokenIsPaused" , async ( ) => {
@@ -247,19 +266,48 @@ describe("Bond Tests", () => {
247266 await expect (
248267 bondFacet . connect ( signer_C ) . redeemAtMaturityByPartition ( signer_C . address , DEFAULT_PARTITION , amount ) ,
249268 ) . to . be . revertedWithCustomError ( bondFacet , "TokenIsPaused" ) ;
269+
270+ await expect ( bondFacet . connect ( signer_C ) . fullRedeemAtMaturity ( signer_C . address ) ) . to . be . revertedWithCustomError (
271+ bondFacet ,
272+ "TokenIsPaused" ,
273+ ) ;
250274 } ) ;
251275
252276 it ( "GIVEN the token holder lacks valid KYC status WHEN redeeming at maturity THEN transaction fails with InvalidKycStatus" , async ( ) => {
253277 await expect (
254278 bondFacet . redeemAtMaturityByPartition ( signer_C . address , DEFAULT_PARTITION , amount ) ,
255279 ) . to . be . revertedWithCustomError ( bondFacet , "InvalidKycStatus" ) ;
280+
281+ await expect ( bondFacet . fullRedeemAtMaturity ( signer_C . address ) ) . to . be . revertedWithCustomError (
282+ bondFacet ,
283+ "InvalidKycStatus" ,
284+ ) ;
256285 } ) ;
257286
258287 it ( "GIVEN the current date is before maturity WHEN redeeming at maturity THEN transaction fails with BondMaturityDateWrong" , async ( ) => {
259288 await expect (
260289 bondFacet . redeemAtMaturityByPartition ( signer_A . address , DEFAULT_PARTITION , amount ) ,
261290 ) . to . be . revertedWithCustomError ( bondFacet , "BondMaturityDateWrong" ) ;
291+
292+ await expect ( bondFacet . fullRedeemAtMaturity ( signer_A . address ) ) . to . be . revertedWithCustomError (
293+ bondFacet ,
294+ "BondMaturityDateWrong" ,
295+ ) ;
262296 } ) ;
297+
298+ it ( "GIVEN a recovered wallet WHEN redeeming at maturity THEN transaction fails with WalletRecovered" , async ( ) => {
299+ await erc3643Facet . recoveryAddress ( signer_A . address , signer_B . address , ADDRESS_ZERO ) ;
300+
301+ await expect (
302+ bondFacet . redeemAtMaturityByPartition ( signer_A . address , DEFAULT_PARTITION , amount ) ,
303+ ) . to . be . revertedWithCustomError ( bondFacet , "WalletRecovered" ) ;
304+
305+ await expect ( bondFacet . fullRedeemAtMaturity ( signer_A . address ) ) . to . be . revertedWithCustomError (
306+ bondFacet ,
307+ "WalletRecovered" ,
308+ ) ;
309+ } ) ;
310+
263311 it ( "GIVEN all conditions are met WHEN redeeming at maturity THEN transaction succeeds and emits RedeemedByPartition" , async ( ) => {
264312 await accessControlFacet . connect ( signer_A ) . grantRole ( ATS_ROLES . _ISSUER_ROLE , signer_C . address ) ;
265313
@@ -276,6 +324,23 @@ describe("Bond Tests", () => {
276324 . to . emit ( bondFacet , "RedeemedByPartition" )
277325 . withArgs ( DEFAULT_PARTITION , signer_A . address , signer_A . address , amount , "0x" , "0x" ) ;
278326 } ) ;
327+
328+ it ( "GIVEN all conditions are met WHEN redeeming all at maturity THEN transaction succeeds and emits RedeemedByPartition" , async ( ) => {
329+ await accessControlFacet . connect ( signer_A ) . grantRole ( ATS_ROLES . _ISSUER_ROLE , signer_C . address ) ;
330+
331+ await erc1410Facet . connect ( signer_C ) . issueByPartition ( {
332+ partition : DEFAULT_PARTITION ,
333+ tokenHolder : signer_A . address ,
334+ value : amount ,
335+ data : "0x" ,
336+ } ) ;
337+
338+ await timeTravelFacet . changeSystemTimestamp ( maturityDate + 1 ) ;
339+
340+ await expect ( bondFacet . fullRedeemAtMaturity ( signer_A . address ) )
341+ . to . emit ( bondFacet , "RedeemedByPartition" )
342+ . withArgs ( DEFAULT_PARTITION , signer_A . address , signer_A . address , amount , "0x" , "0x" ) ;
343+ } ) ;
279344 } ) ;
280345
281346 describe ( "Coupons" , ( ) => {
@@ -772,5 +837,30 @@ describe("Bond Tests", () => {
772837 . to . emit ( bondFacet , "RedeemedByPartition" )
773838 . withArgs ( _PARTITION_ID , signer_A . address , signer_A . address , amount , "0x" , "0x" ) ;
774839 } ) ;
840+
841+ it ( "GIVEN a new diamond contract with multi-partition WHEN redeemAtMaturityByPartition is called THEN transaction success" , async ( ) => {
842+ await deploySecurityFixture ( true ) ;
843+ await accessControlFacet . connect ( signer_A ) . grantRole ( ATS_ROLES . _ISSUER_ROLE , signer_C . address ) ;
844+ await erc1410Facet . connect ( signer_C ) . issueByPartition ( {
845+ partition : _PARTITION_ID ,
846+ tokenHolder : signer_A . address ,
847+ value : amount ,
848+ data : "0x" ,
849+ } ) ;
850+ await erc1410Facet . connect ( signer_C ) . issueByPartition ( {
851+ partition : DEFAULT_PARTITION ,
852+ tokenHolder : signer_A . address ,
853+ value : amount ,
854+ data : "0x" ,
855+ } ) ;
856+
857+ await timeTravelFacet . changeSystemTimestamp ( maturityDate + 1 ) ;
858+
859+ await expect ( bondFacet . fullRedeemAtMaturity ( signer_A . address ) )
860+ . to . emit ( bondFacet , "RedeemedByPartition" )
861+ . withArgs ( _PARTITION_ID , signer_A . address , signer_A . address , amount , "0x" , "0x" )
862+ . to . emit ( bondFacet , "RedeemedByPartition" )
863+ . withArgs ( DEFAULT_PARTITION , signer_A . address , signer_A . address , amount , "0x" , "0x" ) ;
864+ } ) ;
775865 } ) ;
776866} ) ;
0 commit comments