-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/delayed close #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments, a few subjective.
Most critical is that I don't think proposeAndSign can work?
Did not review tests.
src/CyberDealRegistry.sol
Outdated
@@ -199,7 +222,9 @@ contract CyberDealRegistry is Initializable, UUPSUpgradeable, BorgAuthACL { | |||
string[] memory globalValues, | |||
address[] memory parties, | |||
string[] memory creatingPartyValues, | |||
string[] memory counterPartyValues | |||
string[] memory counterPartyValues, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assumes two parties - I wonder if we should account for more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't think so for dealmanager, escrow will only be for 2 parties.
src/CyberDealRegistry.sol
Outdated
string[] memory counterPartyValues | ||
string[] memory counterPartyValues, | ||
bytes32 secretHash, | ||
address finalizer | ||
) external returns (bytes32 contractId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a neater implementation would be:
- have
createContract
always accept an array of arrays of party values:string[][] partyValues
- check every array inside
partyValues
is the correct length, and check that the corresponding party is not the zero address. - loop through partyValues[] setting the mapping per the
parties
This way you only have a single createContract
function. If you wanted to have two explicity entry points, you could make it internal and call it _createContract
, and keep the two functions you have that call through appropriately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, have made the string[][] param throughout and kept it all one create method.
src/CyberDealRegistry.sol
Outdated
@@ -55,6 +58,12 @@ contract CyberDealRegistry is Initializable, UUPSUpgradeable, BorgAuthACL { | |||
// A mapping connecting an address to all the agreements they are a party to | |||
mapping(address => bytes32[]) public agreementsForParty; | |||
|
|||
mapping(bytes32 => address[]) public voidedBy; | |||
|
|||
mapping(bytes32 => uint256) public expiry; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This expiry never gets set AFAICT.
Is there a good reason that voidedBy
and expiry
are not in the AgreementData
struct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also for voidedBy
if moved AgreementData
, I prefer `mapping(address => bool) voidRequested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added expiry (and secretHash) but kept the voidRequestedBy mapping outside -- I think this is probably preferable than nested mappings/arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright. We still have signedAt as a mapping though, just poitning out it's inconsistent really
if(!isParty(contractId, party)) revert NotAParty(); | ||
|
||
AgreementData storage agreementData = agreements[contractId]; | ||
if (agreementData.finalized) revert ContractAlreadyFinalized(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since finalization is optional, I think we should probably check if there finalizer is a zero address, and if so, disallow voiding if the number of signatures is equal to the number of parties (i.e. it is fully signed)
That way you can't void if finalization of the contract is simply that it is fully signed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I now set the finalized flag if finalizer is set to 0 and the contract is fully signed on the last signature.
if (keccak256(abi.encode(counterPartyCheck)) != keccak256(abi.encode(partyValues))) revert CounterPartyValueMismatch(); | ||
} | ||
|
||
if(!conditionCheck(agreementId)) revert AgreementConditionsNotMet(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
currently nowhere to set conditions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to allow these to be set on creation to remove any chance of signing before they are added. Also added editing by the issuer if the deal is pending.
emit DealFinalized( | ||
agreementId, | ||
msg.sender, | ||
CORP, | ||
address(DEAL_REGISTRY), | ||
_fillUnallocated | ||
false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can remove this bool from the event I think - don't think it needs to be in here?
if(deal.status != EscrowStatus.PAID) revert EscrowNotPaid(); | ||
if(!ICyberDealRegistry(DEAL_REGISTRY).isVoided(agreementId)) revert DealNotVoided(); | ||
|
||
// Refund buyer assets first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels like something should be done with the corpAssets... I know in the case of the safe it will be burned, so this is ok for that... but wonder if we should still have the loop for corpassets regardless given we do in other functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Send them back to the printer contract, maybe? We won't burn the NFT's just void them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comments, a few subjective.
Most critical is that I don't think proposeAndSign can work?
Did not review tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to think about @gpxl-dev 's comment on void workflow so flushing what I have for now
Escrow storage deal = escrows[agreementId]; | ||
for(uint256 i = 0; i < deal.corpAssets.length; i++) { | ||
if(deal.corpAssets[i].tokenType == TokenType.ERC721) { | ||
IIssuanceManager(ISSUANCE_MANAGER).voidCertificate(deal.corpAssets[i].tokenAddress, deal.corpAssets[i].tokenId); | ||
} | ||
} | ||
voidEscrow(agreementId); | ||
ICyberDealRegistry(DEAL_REGISTRY).voidContractFor(agreementId, signer, signature); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Missing expiry checks?
-
Not sure if it is intentional: it will make
voidExpiredDeal
exclusive to party members only. It used to be open to anyone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updates: nvm, expiry checks is in voidContractFor()
;
however, what happens if none of the following conditions are met? (1) the number of void requests is equal to the number of parties, and (2) the expiry is in the past.
Wouldn't we end up with a weird state like this?
agreement.voided = false
escrow.state = VOIDED
Escrow storage deal = escrows[agreementId]; | ||
for(uint256 i = 0; i < deal.corpAssets.length; i++) { | ||
if(deal.corpAssets[i].tokenType == TokenType.ERC721) { | ||
IIssuanceManager(ISSUANCE_MANAGER).voidCertificate(deal.corpAssets[i].tokenAddress, deal.corpAssets[i].tokenId); | ||
} | ||
} | ||
voidEscrow(agreementId); | ||
ICyberDealRegistry(DEAL_REGISTRY).voidContractFor(agreementId, signer, signature); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updates: nvm, expiry checks is in voidContractFor()
;
however, what happens if none of the following conditions are met? (1) the number of void requests is equal to the number of parties, and (2) the expiry is in the past.
Wouldn't we end up with a weird state like this?
agreement.voided = false
escrow.state = VOIDED
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed the merge of closed/open offers. A few minor suggestions
} | ||
//matching address cannot be 0 | ||
if (parties[i] == address(0)) { | ||
revert FirstPartyZeroAddress(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest refactoring it to PartyZeroAddress(uint256 index)
due to its more general usage
src/CyberAgreementRegistry.sol
Outdated
} | ||
|
||
if(agreementData.voided) | ||
emit ContractVoided(contractId, voidRequestedBy[contractId], block.timestamp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't it revert if agreementData
not voided? Otherwise we'd end up with a non-void agreement + a voided escrow
No description provided.