Skip to content

Commit

Permalink
Merge 913e6bd into 15f0f3b
Browse files Browse the repository at this point in the history
  • Loading branch information
Ferparishuertas committed Sep 16, 2019
2 parents 15f0f3b + 913e6bd commit a0cf7e7
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ build/

# IntelliJ IDE
.idea

.vscode/
76 changes: 57 additions & 19 deletions contracts/Holdable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ contract Holdable is IHoldable, ERC20 {
function releaseHold(string memory operationId) public returns (bool) {
Hold storage releasableHold = holds[operationId.toHash()];

require(releasableHold.status == HoldStatusCode.Ordered, "A hold can only be released in status Ordered");
require(releasableHold.status == HoldStatusCode.Ordered || releasableHold.status == HoldStatusCode.ExecutedAndKeptOpen,"A hold can only be released in status Ordered or ExecutedAndKeptOpen");
require(
_isExpired(releasableHold.expiration) ||
(msg.sender == releasableHold.notary) ||
Expand All @@ -109,23 +109,43 @@ contract Holdable is IHoldable, ERC20 {
return true;
}

function executeHold(string memory operationId, uint256 value) public returns (bool) {
function executeHold(string memory operationId, uint256 value) public returns (bool) {
return _executeHold(operationId, value, false);
}

function executeHoldAndKeepOpen(string memory operationId, uint256 value) public returns (bool) {
return _executeHold(operationId, value, true);
}


function _executeHold(string memory operationId, uint256 value, bool keepOpenIfHoldHasBalance) internal returns (bool) {

Hold storage executableHold = holds[operationId.toHash()];

_setHoldToExecuted(operationId, value);
_transfer(executableHold.origin, executableHold.target, value);
require(executableHold.status == HoldStatusCode.Ordered || executableHold.status == HoldStatusCode.ExecutedAndKeptOpen,"A hold can only be executed in status Ordered or ExecutedAndKeptOpen");
require(value != 0, "Value must be greater than zero");
require(executableHold.notary == msg.sender, "The hold can only be executed by the notary");
require(!_isExpired(executableHold.expiration), "The hold has already expired");
require(value <= executableHold.value, "The value should be equal or less than the held amount");

emit HoldExecuted(
executableHold.issuer,
operationId,
executableHold.notary,
executableHold.value,
value
);

if (keepOpenIfHoldHasBalance && ((executableHold.value - value) > 0)) {
_decreaseHeldBalance(operationId, value);
_setHoldToExecutedAndKeptOpen(operationId, value);
}else {
_decreaseHeldBalance(operationId, executableHold.value);
_setHoldToExecuted(operationId, value);
}




_transfer(executableHold.origin, executableHold.target, value);

return true;
}


function renewHold(string memory operationId, uint256 timeToExpiration) public returns (bool) {
Hold storage renewableHold = holds[operationId.toHash()];

Expand Down Expand Up @@ -283,16 +303,34 @@ contract Holdable is IHoldable, ERC20 {
function _setHoldToExecuted(string memory operationId, uint256 value) internal {
Hold storage executableHold = holds[operationId.toHash()];
executableHold.status = HoldStatusCode.Executed;
require(executableHold.status == HoldStatusCode.Ordered, "A hold can only be executed in status Ordered");
require(value != 0, "Value must be greater than zero");
require(executableHold.notary == msg.sender, "The hold can only be executed by the notary");
require(!_isExpired(executableHold.expiration), "The hold has already expired");
require(value <= executableHold.value, "The value should be equal or less than the held amount");
emit HoldExecuted(
executableHold.issuer,
operationId,
executableHold.notary,
executableHold.value,
value
);
}
heldBalance[executableHold.origin] = heldBalance[executableHold.origin].sub(executableHold.value);
_totalHeldBalance = _totalHeldBalance.sub(executableHold.value);
function _setHoldToExecutedAndKeptOpen(string memory operationId, uint256 value) internal {
Hold storage executableHold = holds[operationId.toHash()];
executableHold.status = HoldStatusCode.ExecutedAndKeptOpen;
executableHold.value = executableHold.value.sub(value);
executableHold.status = HoldStatusCode.Executed;
emit HoldExecutedAndKeptOpen(
executableHold.issuer,
operationId,
executableHold.notary,
executableHold.value,
value
);
}
function _decreaseHeldBalance(string memory operationId, uint256 value) internal {
Hold storage executableHold = holds[operationId.toHash()];
heldBalance[executableHold.origin] = heldBalance[executableHold.origin].sub(value);
_totalHeldBalance = _totalHeldBalance.sub(value);
}
}
4 changes: 4 additions & 0 deletions contracts/IHoldable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ interface IHoldable {
Nonexistent,
Ordered,
Executed,
ExecutedAndKeptOpen,
ReleasedByNotary,
ReleasedByPayee,
ReleasedOnExpiration
Expand All @@ -27,6 +28,7 @@ interface IHoldable {
) external returns (bool);
function releaseHold(string calldata operationId) external returns (bool);
function executeHold(string calldata operationId, uint256 value) external returns (bool);
function executeHoldAndKeepOpen(string calldata operationId, uint256 value) external returns (bool);
function renewHold(string calldata operationId, uint256 timeToExpiration) external returns (bool);
function retrieveHoldData(string calldata operationId) external view returns (
address from,
Expand Down Expand Up @@ -55,6 +57,8 @@ interface IHoldable {
uint256 expiration
);
event HoldExecuted(address indexed holdIssuer, string operationId, address indexed notary, uint256 heldValue, uint256 transferredValue);
event HoldExecutedAndKeptOpen(address indexed holdIssuer, string operationId, address indexed notary, uint256 heldValue,
uint256 transferredValue);
event HoldReleased(address indexed holdIssuer, string operationId, HoldStatusCode status);
event HoldRenewed(address indexed holdIssuer, string operationId, uint256 oldExpiration, uint256 newExpiration);
event AuthorizedHoldOperator(address indexed operator, address indexed account);
Expand Down
7 changes: 7 additions & 0 deletions diagrams/hold_released_on_total_amount_reached.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@startuml
UserA -> "Holdable Token": hold(to: UserB)
"Holdable Token" -> Notary: HoldCreated
UserC -> "Holdable Token" : releaseHold
"Holdable Token" -> UserA: release held amount
"Holdable Token" -> UserA: HoldReleased
@enduml
10 changes: 10 additions & 0 deletions diagrams/iterative_open_hold_execution.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@startuml
UserA -> "Holdable Token": open hold(to: UserB)
"Holdable Token" -> Notary: HoldCreated
Notary-> "Holdable Token" : executeHoldAndKeepOpen
UserA -> UserB: transfer
"Holdable Token" -> UserA: HoldExecutedAndKeptOpen
Notary-> "Holdable Token" : executeHoldAndKeepOpen
UserA -> UserB: transfer (totalAmountReached)
"Holdable Token" -> UserA: HoldExecuted
@enduml

0 comments on commit a0cf7e7

Please sign in to comment.