From a20a7360052a3405a51811c49e27eba7e79a7347 Mon Sep 17 00:00:00 2001 From: Andrew Richardson Date: Fri, 6 Dec 2024 09:56:10 -0500 Subject: [PATCH] Add pre-issuance steps to CSD bond test Signed-off-by: Andrew Richardson --- .../paladin/pente/domain/CSDBondTest.java | 48 ++++++++++--------- .../domain/helpers/CSDBondTrackerHelper.java | 46 ++++++++++++++++++ .../domain/helpers/InvestorListHelper.java | 2 +- solidity/contracts/private/CSDBondTracker.sol | 8 +++- 4 files changed, 79 insertions(+), 25 deletions(-) diff --git a/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/CSDBondTest.java b/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/CSDBondTest.java index 5a0d61a9f..096c8d17d 100644 --- a/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/CSDBondTest.java +++ b/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/CSDBondTest.java @@ -110,11 +110,11 @@ void testCSDBond() throws Exception { String cashIssuer = "cashIssuer"; String bondIssuer = "bondIssuer"; - String bondCustodian = "bondCustodian"; + String bondChecker = "bondChecker"; String alice = "alice"; - String custodianAddress = testbed.getRpcClient().request("testbed_resolveVerifier", - bondCustodian, Algorithms.ECDSA_SECP256K1, Verifiers.ETH_ADDRESS); + String issuerAddress = testbed.getRpcClient().request("testbed_resolveVerifier", + bondIssuer, Algorithms.ECDSA_SECP256K1, Verifiers.ETH_ADDRESS); String aliceAddress = testbed.getRpcClient().request("testbed_resolveVerifier", alice, Algorithms.ECDSA_SECP256K1, Verifiers.ETH_ADDRESS); @@ -126,13 +126,13 @@ void testCSDBond() throws Exception { assertEquals("type=NotoCoin(bytes32 salt,string owner,uint256 amount),labels=[owner,amount]", notoSchema.signature()); - GroupTupleJSON issuerCustodianGroup = new GroupTupleJSON( - JsonHex.randomBytes32(), new String[]{bondIssuer, bondCustodian}); + GroupTupleJSON issuerGroup = new GroupTupleJSON( + JsonHex.randomBytes32(), new String[]{bondIssuer}); // Create the privacy groups - var issuerCustodianInstance = PenteHelper.newPrivacyGroup( - "pente", alice, testbed, issuerCustodianGroup, true); - assertFalse(issuerCustodianInstance.address().isBlank()); + var issuerInstance = PenteHelper.newPrivacyGroup( + "pente", alice, testbed, issuerGroup, true); + assertFalse(issuerInstance.address().isBlank()); // Create Noto cash token var notoCash = NotoHelper.deploy("noto", cashIssuer, testbed, @@ -142,36 +142,40 @@ void testCSDBond() throws Exception { true)); assertFalse(notoCash.address().isBlank()); - // Deploy private investor list to the issuer/custodian privacy group - var investorList = InvestorListHelper.deploy(issuerCustodianInstance, bondIssuer, new HashMap<>() {{ - put("initialOwner", custodianAddress); + // Deploy private investor list to the issuer privacy group + var investorList = InvestorListHelper.deploy(issuerInstance, bondIssuer, new HashMap<>() {{ + put("initialOwner", issuerAddress); }}); - // Deploy private bond tracker to the issuer/custodian privacy group - var bondTracker = CSDBondTrackerHelper.deploy(issuerCustodianInstance, bondIssuer, new HashMap<>() {{ + // Deploy private bond tracker to the issuer privacy group + var bondTracker = CSDBondTrackerHelper.deploy(issuerInstance, bondIssuer, new HashMap<>() {{ put("name", "BOND"); put("symbol", "BOND"); put("transferPolicy_", investorList.address()); }}); - // TODO: perform bond pre-issuance workflow + // Perform bond pre-issuance workflow + bondTracker.approveRequest(bondChecker); + bondTracker.setISIN(bondIssuer, "ZZ0123456AB0"); + bondTracker.approveISIN(bondChecker); // Create Noto bond token - var notoBond = NotoHelper.deploy("noto", bondCustodian, testbed, + var notoBond = NotoHelper.deploy("noto", bondIssuer, testbed, new NotoHelper.ConstructorParams( - bondCustodian + "@node1", + bondIssuer + "@node1", new NotoHelper.HookParams( - issuerCustodianInstance.address(), + issuerInstance.address(), bondTracker.address(), - issuerCustodianGroup), + issuerGroup), false)); assertFalse(notoBond.address().isBlank()); // Issue cash to investors notoCash.mint(cashIssuer, alice, 100000); - // Issue bond to custodian - notoBond.mint(bondIssuer, bondCustodian, 1000); + // Issue bond to issuer + bondTracker.prepareIssuance(bondIssuer); + notoBond.mint(bondChecker, bondIssuer, 1000); // Validate Noto balances var notoCashStates = notoCash.queryStates(notoSchema.id, null); @@ -181,10 +185,10 @@ void testCSDBond() throws Exception { var notoBondStates = notoBond.queryStates(notoSchema.id, null); assertEquals(1, notoBondStates.size()); assertEquals("1000", notoBondStates.getFirst().data().amount()); - assertEquals(custodianAddress, notoBondStates.getFirst().data().owner()); + assertEquals(issuerAddress, notoBondStates.getFirst().data().owner()); // Validate bond tracker balance - assertEquals("1000", bondTracker.balanceOf(bondIssuer, custodianAddress)); + assertEquals("1000", bondTracker.balanceOf(bondIssuer, issuerAddress)); } } } diff --git a/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/CSDBondTrackerHelper.java b/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/CSDBondTrackerHelper.java index d91331097..387636ea1 100644 --- a/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/CSDBondTrackerHelper.java +++ b/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/CSDBondTrackerHelper.java @@ -69,4 +69,50 @@ public String balanceOf(String sender, String account) throws IOException { ); return output.output(); } + + public void approveRequest(String sender) throws IOException { + var method = abi.getABIEntry("function", "approveRequest"); + pente.invoke( + method.name(), + method.inputs(), + sender, + address, + new HashMap<>() + ); + } + + public void setISIN(String sender, String isin) throws IOException { + var method = abi.getABIEntry("function", "setISIN"); + pente.invoke( + method.name(), + method.inputs(), + sender, + address, + new HashMap<>() {{ + put("isin_", isin); + }} + ); + } + + public void approveISIN(String sender) throws IOException { + var method = abi.getABIEntry("function", "approveISIN"); + pente.invoke( + method.name(), + method.inputs(), + sender, + address, + new HashMap<>() + ); + } + + public void prepareIssuance(String sender) throws IOException { + var method = abi.getABIEntry("function", "prepareIssuance"); + pente.invoke( + method.name(), + method.inputs(), + sender, + address, + new HashMap<>() + ); + } } diff --git a/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/InvestorListHelper.java b/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/InvestorListHelper.java index b96dc4e0b..ca641fc0d 100644 --- a/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/InvestorListHelper.java +++ b/domains/pente/src/test/java/io/kaleido/paladin/pente/domain/helpers/InvestorListHelper.java @@ -58,7 +58,7 @@ public JsonHex.Address address() { } public void addInvestor(String sender, String addr) throws IOException { - var method = abi.getABIEntry("function", "balanceOf"); + var method = abi.getABIEntry("function", "addInvestor"); pente.invoke( method.name(), method.inputs(), diff --git a/solidity/contracts/private/CSDBondTracker.sol b/solidity/contracts/private/CSDBondTracker.sol index 19f19783d..6f054f8a3 100644 --- a/solidity/contracts/private/CSDBondTracker.sol +++ b/solidity/contracts/private/CSDBondTracker.sol @@ -109,9 +109,13 @@ contract CSDBondTracker is INotoHooks, ERC20, Ownable { uint256 amount, PreparedTransaction calldata prepared ) external onlyOwner { - require(sender == owner(), "Bond must be issued by issuer to themself"); - require(to == owner(), "Bond must be issued by issuer to themself"); + require(to == owner(), "Bond must be issued to issuer"); require(status == Status.READY, "Bond is not ready to be issued"); + require( + sender != maker[LifecycleStep.BOND_ISSUANCE], + "Maker and checker cannot be the same" + ); + checker[LifecycleStep.BOND_ISSUANCE] = sender; _mint(to, amount); status = Status.ISSUED; emit PenteExternalCall(prepared.contractAddress, prepared.encodedCall);