Skip to content

Commit

Permalink
feat: tt 160 reject transfer (#21)
Browse files Browse the repository at this point in the history
* feat: remark storage

* feat: Reject Transfer

* fix: commit lint fix

* fix: test case updated

---------

Co-authored-by: Rishabh Singh <[email protected]>
  • Loading branch information
RishabhS7 and RishabhSGT authored Sep 20, 2024
1 parent 35287ac commit 7ce8ce2
Show file tree
Hide file tree
Showing 7 changed files with 942 additions and 75 deletions.
85 changes: 85 additions & 0 deletions contracts/TitleEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ contract TitleEscrow is Initializable, IERC165, TitleEscrowErrors, ITitleEscrow
address public override beneficiary;
address public override holder;

address public override prevBeneficiary;
address public override prevHolder;

address public override nominee;

bool public override active;
Expand Down Expand Up @@ -157,6 +160,8 @@ contract TitleEscrow is Initializable, IERC165, TitleEscrowErrors, ITitleEscrow
if (nominee == _nominee) {
revert NomineeAlreadyNominated();
}
prevBeneficiary = address(0);
if (beneficiary == holder) prevHolder = address(0);
remark = _remark;

_setNominee(_nominee, _remark);
Expand All @@ -175,6 +180,8 @@ contract TitleEscrow is Initializable, IERC165, TitleEscrowErrors, ITitleEscrow
if (!(beneficiary == holder || nominee == _nominee)) {
revert InvalidNominee();
}
prevHolder = address(0);
prevBeneficiary = beneficiary;
remark = _remark;

_setBeneficiary(_nominee, _remark);
Expand All @@ -193,6 +200,8 @@ contract TitleEscrow is Initializable, IERC165, TitleEscrowErrors, ITitleEscrow
if (holder == newHolder) {
revert RecipientAlreadyHolder();
}
if (beneficiary == holder) prevBeneficiary = address(0);
prevHolder = holder;
remark = _remark;

_setHolder(newHolder, _remark);
Expand All @@ -206,6 +215,80 @@ contract TitleEscrow is Initializable, IERC165, TitleEscrowErrors, ITitleEscrow
transferHolder(newHolder, _remark);
}

/**
* @dev See {ITitleEscrow-rejectTransferBeneficiary}.
*/
function rejectTransferBeneficiary(
bytes calldata _remark
) public virtual override whenNotPaused whenActive onlyBeneficiary whenHoldingToken remarkLengthLimit(_remark) {
if (prevBeneficiary == address(0)) {
revert InvalidTransferToZeroAddress();
}
if (beneficiary == holder) {
revert DualRoleRejectionRequired();
}
remark = _remark;
address from = beneficiary;
address to = prevBeneficiary;

_setBeneficiary(to, _remark);
prevBeneficiary = address(0);
emit RejectTransferBeneficiary(from, to, registry, tokenId, _remark);
}

/**
* @dev See {ITitleEscrow-rejectTransferHolder}.
*/
function rejectTransferHolder(
bytes calldata _remark
) public virtual override whenNotPaused whenActive onlyHolder whenHoldingToken remarkLengthLimit(_remark) {
if (prevHolder == address(0)) {
revert InvalidTransferToZeroAddress();
}
if (holder == beneficiary) {
revert DualRoleRejectionRequired();
}
remark = _remark;
address from = holder;
address to = prevHolder;

_setHolder(to, _remark);
prevHolder = address(0);

emit RejectTransferHolder(from, to, registry, tokenId, _remark);
}

/**
* @dev See {ITitleEscrow-rejectTransferOwners}.
*/
function rejectTransferOwners(
bytes calldata _remark
)
external
virtual
override
whenNotPaused
whenActive
whenHoldingToken
onlyBeneficiary
onlyHolder
remarkLengthLimit(_remark)
{
if (prevBeneficiary == address(0) || prevHolder == address(0)) {
revert InvalidTransferToZeroAddress();
}
remark = _remark;
address fromHolder = holder;
address toHolder = prevHolder;
address fromBeneficiary = beneficiary;
address toBeneficiary = prevBeneficiary;
_setBeneficiary(toBeneficiary, _remark);
_setHolder(toHolder, _remark);
prevBeneficiary = address(0);
prevHolder = address(0);
emit RejectTransferOwners(fromBeneficiary, toBeneficiary, fromHolder, toHolder, registry, tokenId, _remark);
}

/**
* @dev See {ITitleEscrow-surrender}.
*/
Expand All @@ -225,6 +308,8 @@ contract TitleEscrow is Initializable, IERC165, TitleEscrowErrors, ITitleEscrow
_setNominee(address(0), "");
ITradeTrustToken(registry).transferFrom(address(this), registry, tokenId, "");
remark = _remark;
prevBeneficiary = address(0);
prevHolder = address(0);

emit Surrender(msg.sender, registry, tokenId, _remark);
}
Expand Down
45 changes: 45 additions & 0 deletions contracts/interfaces/ITitleEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,29 @@ interface ITitleEscrow is IERC721Receiver {
);
event Surrender(address indexed surrenderer, address registry, uint256 tokenId, bytes remark);
event Shred(address registry, uint256 tokenId, bytes remark);
event RejectTransferOwners(
address indexed fromBeneficiary,
address indexed toBeneficiary,
address indexed fromHolder,
address toHolder,
address registry,
uint256 tokenId,
bytes remark
);
event RejectTransferBeneficiary(
address indexed fromBeneficiary,
address indexed toBeneficiary,
address registry,
uint256 tokenId,
bytes remark
);
event RejectTransferHolder(
address indexed fromHolder,
address indexed toHolder,
address registry,
uint256 tokenId,
bytes remark
);

/**
* @notice Allows the beneficiary to nominate a new beneficiary
Expand Down Expand Up @@ -67,10 +90,32 @@ interface ITitleEscrow is IERC721Receiver {
*/
function transferOwners(address nominee, address newHolder, bytes calldata remark) external;

/**
* @notice Allows the new beneficiary to reject the nomination
* @param _remark The remark for the rejection
*/
function rejectTransferBeneficiary(bytes calldata _remark) external;

/**
* @notice Allows the new holder to reject the transfer of the holder role
* @param _remark The remark for the rejection
*/
function rejectTransferHolder(bytes calldata _remark) external;

/**
* @notice Allows the new beneficiary and holder to reject the transfer of both roles
* @param _remark The remark for the rejection
*/
function rejectTransferOwners(bytes calldata _remark) external;

function beneficiary() external view returns (address);

function holder() external view returns (address);

function prevBeneficiary() external view returns (address);

function prevHolder() external view returns (address);

function active() external view returns (bool);

function nominee() external view returns (address);
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/TitleEscrowErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ interface TitleEscrowErrors {
error TokenNotSurrendered();

error RemarkLengthExceeded();

error DualRoleRejectionRequired();
}
5 changes: 5 additions & 0 deletions src/constants/contract-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ export const contractInterfaces = {
"transferBeneficiary(address,bytes)",
"transferHolder(address,bytes)",
"transferOwners(address,address,bytes)",
"rejectTransferBeneficiary(bytes)",
"rejectTransferHolder(bytes)",
"rejectTransferOwners(bytes)",
"beneficiary()",
"holder()",
"prevBeneficiary()",
"prevHolder()",
"active()",
"nominee()",
"registry()",
Expand Down
Loading

0 comments on commit 7ce8ce2

Please sign in to comment.