Zero-Coupon bond

Introduction#

A Zero-Coupon bond is a bond in which the face value is repaid some predefined time after it has been released (maturity time).

In this contract, the present value of the bond (value at which the bond is traded) is computed as the face value (value at which the bond is redeemed at maturity time) minus a discount percent of face value.

A detailed presentation of the process is available in the Zero-Coupon Bond DApp example.

API#

Storage#

NameTypeDescription
issueraddressBond issuer's address.
subscriberaddressBond subscriber's address.
facevaluetezValue at which the bond is redeemed at maturity time.
discoutrationalDiscount applied to facevalue to compute present value (at emission)
maturitydurationdurationDuration before maturity time.
paybackdurationdurationDuration of payback period after maturity date
issuersignedbooltrue is issuer has signed, false otherwise.
subscribersignedbooltrue is subscriber has signed, false otherwise.
_statestatesOne of Created, Signed, Terminated, Disputed

Entrypoints#

NameParametersDescription
toSignedCalled by sign to set contract's state to Signed.
signCalled by issuer or subscriber. subscriber must transfer the present value to the contract.
terminateCalled by issuer during payback period, to transfer the face value to subscriber.
disputeCalled by subscriber if issuer has not terminated the contract in the payback period.

Code#

zcb.arl
archetype zero_coupon_bond (
issuer : address,
subscriber : address,
facevalue : tez,
discount : rational,
maturityduration : duration,
paybackduration : duration,
issuersigned : bool,
subscribersigned : bool
)
variable signaturedate : option<date> = none
states =
| Created initial
| Signed
| Terminated
| Disputed
transition toSigned() {
called by selfaddress
from Created to Signed with effect {
signaturedate := some(now)
}
}
entry sign () {
if caller = issuer then
issuersigned := true
else if caller = subscriber then begin
subscribersigned := true;
var presentvalue = discount * facevalue;
dorequire(transferred >= presentvalue, "SUBSCRIBER_INVALID_TRANSFERRED");
transfer presentvalue to issuer;
end
else fail("CALLER_NOT_A_SIGNER");
if issuersigned and subscribersigned then
transfer 0tz to entry self.toSigned();
}
transition terminate () {
called by issuer
from Signed to Terminated when {
match signaturedate with
| some(d) ->
d + maturityduration <= now <= d + maturityduration + paybackduration and
transferred >= facevalue
| none -> false
end
} with effect {
transfer facevalue to subscriber
}
}
transition dispute () {
called by subscriber
from Signed to Disputed when {
match signaturedate with
| some(d) ->
d + maturityduration + paybackduration <= now
| none -> false
end
}
}