Skip to content

Commit

Permalink
Add pre-issuance steps to CSD bond test
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Richardson <[email protected]>
  • Loading branch information
awrichar committed Dec 9, 2024
1 parent ed6d6f2 commit a20a736
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<>()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
8 changes: 6 additions & 2 deletions solidity/contracts/private/CSDBondTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit a20a736

Please sign in to comment.